ModelAnimationCache.js 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. import Cartesian3 from '../Core/Cartesian3.js';
  2. import ComponentDatatype from '../Core/ComponentDatatype.js';
  3. import defaultValue from '../Core/defaultValue.js';
  4. import defined from '../Core/defined.js';
  5. import LinearSpline from '../Core/LinearSpline.js';
  6. import Matrix4 from '../Core/Matrix4.js';
  7. import Quaternion from '../Core/Quaternion.js';
  8. import QuaternionSpline from '../Core/QuaternionSpline.js';
  9. import WebGLConstants from '../Core/WebGLConstants.js';
  10. import WeightSpline from '../Core/WeightSpline.js';
  11. import getAccessorByteStride from '../ThirdParty/GltfPipeline/getAccessorByteStride.js';
  12. import numberOfComponentsForType from '../ThirdParty/GltfPipeline/numberOfComponentsForType.js';
  13. import AttributeType from './AttributeType.js';
  14. /**
  15. * @private
  16. */
  17. function ModelAnimationCache() {
  18. }
  19. var dataUriRegex = /^data\:/i;
  20. function getAccessorKey(model, accessor) {
  21. var gltf = model.gltf;
  22. var buffers = gltf.buffers;
  23. var bufferViews = gltf.bufferViews;
  24. var bufferView = bufferViews[accessor.bufferView];
  25. var buffer = buffers[bufferView.buffer];
  26. var byteOffset = bufferView.byteOffset + accessor.byteOffset;
  27. var byteLength = accessor.count * numberOfComponentsForType(accessor.type);
  28. var uriKey = dataUriRegex.test(buffer.uri) ? '' : buffer.uri;
  29. return model.cacheKey + '//' + uriKey + '/' + byteOffset + '/' + byteLength;
  30. }
  31. var cachedAnimationParameters = {
  32. };
  33. ModelAnimationCache.getAnimationParameterValues = function(model, accessor) {
  34. var key = getAccessorKey(model, accessor);
  35. var values = cachedAnimationParameters[key];
  36. if (!defined(values)) {
  37. // Cache miss
  38. var gltf = model.gltf;
  39. var buffers = gltf.buffers;
  40. var bufferViews = gltf.bufferViews;
  41. var bufferView = bufferViews[accessor.bufferView];
  42. var bufferId = bufferView.buffer;
  43. var buffer = buffers[bufferId];
  44. var source = buffer.extras._pipeline.source;
  45. var componentType = accessor.componentType;
  46. var type = accessor.type;
  47. var numberOfComponents = numberOfComponentsForType(type);
  48. var count = accessor.count;
  49. var byteStride = getAccessorByteStride(gltf, accessor);
  50. values = new Array(count);
  51. var accessorByteOffset = defaultValue(accessor.byteOffset, 0);
  52. var byteOffset = bufferView.byteOffset + accessorByteOffset;
  53. for (var i = 0; i < count; i++) {
  54. var typedArrayView = ComponentDatatype.createArrayBufferView(componentType, source.buffer, source.byteOffset + byteOffset, numberOfComponents);
  55. if (type === 'SCALAR') {
  56. values[i] = typedArrayView[0];
  57. } else if (type === 'VEC3') {
  58. values[i] = Cartesian3.fromArray(typedArrayView);
  59. } else if (type === 'VEC4') {
  60. values[i] = Quaternion.unpack(typedArrayView);
  61. }
  62. byteOffset += byteStride;
  63. }
  64. // GLTF_SPEC: Support more parameter types when glTF supports targeting materials. https://github.com/KhronosGroup/glTF/issues/142
  65. if (defined(model.cacheKey)) {
  66. // Only cache when we can create a unique id
  67. cachedAnimationParameters[key] = values;
  68. }
  69. }
  70. return values;
  71. };
  72. var cachedAnimationSplines = {
  73. };
  74. function getAnimationSplineKey(model, animationName, samplerName) {
  75. return model.cacheKey + '//' + animationName + '/' + samplerName;
  76. }
  77. function ConstantSpline(value) {
  78. this._value = value;
  79. }
  80. ConstantSpline.prototype.evaluate = function(time, result) {
  81. return this._value;
  82. };
  83. ConstantSpline.prototype.wrapTime = function(time) {
  84. return 0.0;
  85. };
  86. ConstantSpline.prototype.clampTime = function(time) {
  87. return 0.0;
  88. };
  89. ModelAnimationCache.getAnimationSpline = function(model, animationName, animation, samplerName, sampler, input, path, output) {
  90. var key = getAnimationSplineKey(model, animationName, samplerName);
  91. var spline = cachedAnimationSplines[key];
  92. if (!defined(spline)) {
  93. var times = input;
  94. var controlPoints = output;
  95. if ((times.length === 1) && (controlPoints.length === 1)) {
  96. spline = new ConstantSpline(controlPoints[0]);
  97. } else if (sampler.interpolation === 'LINEAR') {
  98. if (path === 'translation' || path === 'scale') {
  99. spline = new LinearSpline({
  100. times : times,
  101. points : controlPoints
  102. });
  103. } else if (path === 'rotation') {
  104. spline = new QuaternionSpline({
  105. times : times,
  106. points : controlPoints
  107. });
  108. } else if (path === 'weights') {
  109. spline = new WeightSpline({
  110. times : times,
  111. weights : controlPoints
  112. });
  113. }
  114. // GLTF_SPEC: Support more parameter types when glTF supports targeting materials. https://github.com/KhronosGroup/glTF/issues/142
  115. }
  116. if (defined(model.cacheKey)) {
  117. // Only cache when we can create a unique id
  118. cachedAnimationSplines[key] = spline;
  119. }
  120. }
  121. return spline;
  122. };
  123. var cachedSkinInverseBindMatrices = {
  124. };
  125. ModelAnimationCache.getSkinInverseBindMatrices = function(model, accessor) {
  126. var key = getAccessorKey(model, accessor);
  127. var matrices = cachedSkinInverseBindMatrices[key];
  128. if (!defined(matrices)) {
  129. // Cache miss
  130. var gltf = model.gltf;
  131. var buffers = gltf.buffers;
  132. var bufferViews = gltf.bufferViews;
  133. var bufferViewId = accessor.bufferView;
  134. var bufferView = bufferViews[bufferViewId];
  135. var bufferId = bufferView.buffer;
  136. var buffer = buffers[bufferId];
  137. var source = buffer.extras._pipeline.source;
  138. var componentType = accessor.componentType;
  139. var type = accessor.type;
  140. var count = accessor.count;
  141. var byteStride = getAccessorByteStride(gltf, accessor);
  142. var byteOffset = bufferView.byteOffset + accessor.byteOffset;
  143. var numberOfComponents = numberOfComponentsForType(type);
  144. matrices = new Array(count);
  145. if ((componentType === WebGLConstants.FLOAT) && (type === AttributeType.MAT4)) {
  146. for (var i = 0; i < count; ++i) {
  147. var typedArrayView = ComponentDatatype.createArrayBufferView(componentType, source.buffer, source.byteOffset + byteOffset, numberOfComponents);
  148. matrices[i] = Matrix4.fromArray(typedArrayView);
  149. byteOffset += byteStride;
  150. }
  151. }
  152. cachedSkinInverseBindMatrices[key] = matrices;
  153. }
  154. return matrices;
  155. };
  156. export default ModelAnimationCache;