@onerjs/serializers 8.23.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (135) hide show
  1. package/OBJ/index.d.ts +1 -0
  2. package/OBJ/index.js +2 -0
  3. package/OBJ/index.js.map +1 -0
  4. package/OBJ/objSerializer.d.ts +21 -0
  5. package/OBJ/objSerializer.js +171 -0
  6. package/OBJ/objSerializer.js.map +1 -0
  7. package/USDZ/index.d.ts +1 -0
  8. package/USDZ/index.js +3 -0
  9. package/USDZ/index.js.map +1 -0
  10. package/USDZ/usdzExporter.d.ts +50 -0
  11. package/USDZ/usdzExporter.js +589 -0
  12. package/USDZ/usdzExporter.js.map +1 -0
  13. package/exportUtils.d.ts +12 -0
  14. package/exportUtils.js +37 -0
  15. package/exportUtils.js.map +1 -0
  16. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.d.ts +24 -0
  17. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.js +61 -0
  18. package/glTF/2.0/Extensions/EXT_materials_diffuse_roughness.js.map +1 -0
  19. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.d.ts +36 -0
  20. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js +109 -0
  21. package/glTF/2.0/Extensions/EXT_mesh_gpu_instancing.js.map +1 -0
  22. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.d.ts +32 -0
  23. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js +135 -0
  24. package/glTF/2.0/Extensions/KHR_draco_mesh_compression.js.map +1 -0
  25. package/glTF/2.0/Extensions/KHR_lights_punctual.d.ts +39 -0
  26. package/glTF/2.0/Extensions/KHR_lights_punctual.js +145 -0
  27. package/glTF/2.0/Extensions/KHR_lights_punctual.js.map +1 -0
  28. package/glTF/2.0/Extensions/KHR_materials_anisotropy.d.ts +24 -0
  29. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js +62 -0
  30. package/glTF/2.0/Extensions/KHR_materials_anisotropy.js.map +1 -0
  31. package/glTF/2.0/Extensions/KHR_materials_clearcoat.d.ts +24 -0
  32. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js +85 -0
  33. package/glTF/2.0/Extensions/KHR_materials_clearcoat.js.map +1 -0
  34. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.d.ts +40 -0
  35. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js +118 -0
  36. package/glTF/2.0/Extensions/KHR_materials_diffuse_transmission.js.map +1 -0
  37. package/glTF/2.0/Extensions/KHR_materials_dispersion.d.ts +31 -0
  38. package/glTF/2.0/Extensions/KHR_materials_dispersion.js +63 -0
  39. package/glTF/2.0/Extensions/KHR_materials_dispersion.js.map +1 -0
  40. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.d.ts +27 -0
  41. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js +54 -0
  42. package/glTF/2.0/Extensions/KHR_materials_emissive_strength.js.map +1 -0
  43. package/glTF/2.0/Extensions/KHR_materials_ior.d.ts +29 -0
  44. package/glTF/2.0/Extensions/KHR_materials_ior.js +55 -0
  45. package/glTF/2.0/Extensions/KHR_materials_ior.js.map +1 -0
  46. package/glTF/2.0/Extensions/KHR_materials_iridescence.d.ts +24 -0
  47. package/glTF/2.0/Extensions/KHR_materials_iridescence.js +69 -0
  48. package/glTF/2.0/Extensions/KHR_materials_iridescence.js.map +1 -0
  49. package/glTF/2.0/Extensions/KHR_materials_sheen.d.ts +24 -0
  50. package/glTF/2.0/Extensions/KHR_materials_sheen.js +66 -0
  51. package/glTF/2.0/Extensions/KHR_materials_sheen.js.map +1 -0
  52. package/glTF/2.0/Extensions/KHR_materials_specular.d.ts +41 -0
  53. package/glTF/2.0/Extensions/KHR_materials_specular.js +94 -0
  54. package/glTF/2.0/Extensions/KHR_materials_specular.js.map +1 -0
  55. package/glTF/2.0/Extensions/KHR_materials_transmission.d.ts +41 -0
  56. package/glTF/2.0/Extensions/KHR_materials_transmission.js +92 -0
  57. package/glTF/2.0/Extensions/KHR_materials_transmission.js.map +1 -0
  58. package/glTF/2.0/Extensions/KHR_materials_unlit.d.ts +20 -0
  59. package/glTF/2.0/Extensions/KHR_materials_unlit.js +46 -0
  60. package/glTF/2.0/Extensions/KHR_materials_unlit.js.map +1 -0
  61. package/glTF/2.0/Extensions/KHR_materials_volume.d.ts +40 -0
  62. package/glTF/2.0/Extensions/KHR_materials_volume.js +96 -0
  63. package/glTF/2.0/Extensions/KHR_materials_volume.js.map +1 -0
  64. package/glTF/2.0/Extensions/KHR_texture_transform.d.ts +21 -0
  65. package/glTF/2.0/Extensions/KHR_texture_transform.js +93 -0
  66. package/glTF/2.0/Extensions/KHR_texture_transform.js.map +1 -0
  67. package/glTF/2.0/Extensions/index.d.ts +17 -0
  68. package/glTF/2.0/Extensions/index.js +18 -0
  69. package/glTF/2.0/Extensions/index.js.map +1 -0
  70. package/glTF/2.0/bufferManager.d.ts +68 -0
  71. package/glTF/2.0/bufferManager.js +154 -0
  72. package/glTF/2.0/bufferManager.js.map +1 -0
  73. package/glTF/2.0/dataWriter.d.ts +20 -0
  74. package/glTF/2.0/dataWriter.js +83 -0
  75. package/glTF/2.0/dataWriter.js.map +1 -0
  76. package/glTF/2.0/glTFAnimation.d.ts +191 -0
  77. package/glTF/2.0/glTFAnimation.js +786 -0
  78. package/glTF/2.0/glTFAnimation.js.map +1 -0
  79. package/glTF/2.0/glTFData.d.ts +21 -0
  80. package/glTF/2.0/glTFData.js +30 -0
  81. package/glTF/2.0/glTFData.js.map +1 -0
  82. package/glTF/2.0/glTFExporter.d.ts +109 -0
  83. package/glTF/2.0/glTFExporter.js +1166 -0
  84. package/glTF/2.0/glTFExporter.js.map +1 -0
  85. package/glTF/2.0/glTFExporterExtension.d.ts +77 -0
  86. package/glTF/2.0/glTFExporterExtension.js +4 -0
  87. package/glTF/2.0/glTFExporterExtension.js.map +1 -0
  88. package/glTF/2.0/glTFMaterialExporter.d.ts +99 -0
  89. package/glTF/2.0/glTFMaterialExporter.js +778 -0
  90. package/glTF/2.0/glTFMaterialExporter.js.map +1 -0
  91. package/glTF/2.0/glTFMorphTargetsUtilities.d.ts +14 -0
  92. package/glTF/2.0/glTFMorphTargetsUtilities.js +149 -0
  93. package/glTF/2.0/glTFMorphTargetsUtilities.js.map +1 -0
  94. package/glTF/2.0/glTFSerializer.d.ts +78 -0
  95. package/glTF/2.0/glTFSerializer.js +39 -0
  96. package/glTF/2.0/glTFSerializer.js.map +1 -0
  97. package/glTF/2.0/glTFUtilities.d.ts +89 -0
  98. package/glTF/2.0/glTFUtilities.js +349 -0
  99. package/glTF/2.0/glTFUtilities.js.map +1 -0
  100. package/glTF/2.0/index.d.ts +4 -0
  101. package/glTF/2.0/index.js +6 -0
  102. package/glTF/2.0/index.js.map +1 -0
  103. package/glTF/glTFFileExporter.d.ts +20 -0
  104. package/glTF/glTFFileExporter.js +4 -0
  105. package/glTF/glTFFileExporter.js.map +1 -0
  106. package/glTF/index.d.ts +2 -0
  107. package/glTF/index.js +4 -0
  108. package/glTF/index.js.map +1 -0
  109. package/index.d.ts +4 -0
  110. package/index.js +6 -0
  111. package/index.js.map +1 -0
  112. package/legacy/legacy-glTF2Serializer.d.ts +2 -0
  113. package/legacy/legacy-glTF2Serializer.js +45 -0
  114. package/legacy/legacy-glTF2Serializer.js.map +1 -0
  115. package/legacy/legacy-objSerializer.d.ts +1 -0
  116. package/legacy/legacy-objSerializer.js +14 -0
  117. package/legacy/legacy-objSerializer.js.map +1 -0
  118. package/legacy/legacy-stlSerializer.d.ts +1 -0
  119. package/legacy/legacy-stlSerializer.js +14 -0
  120. package/legacy/legacy-stlSerializer.js.map +1 -0
  121. package/legacy/legacy-usdzSerializer.d.ts +1 -0
  122. package/legacy/legacy-usdzSerializer.js +14 -0
  123. package/legacy/legacy-usdzSerializer.js.map +1 -0
  124. package/legacy/legacy.d.ts +5 -0
  125. package/legacy/legacy.js +8 -0
  126. package/legacy/legacy.js.map +1 -0
  127. package/license.md +71 -0
  128. package/package.json +49 -0
  129. package/readme.md +29 -0
  130. package/stl/index.d.ts +1 -0
  131. package/stl/index.js +2 -0
  132. package/stl/index.js.map +1 -0
  133. package/stl/stlSerializer.d.ts +20 -0
  134. package/stl/stlSerializer.js +135 -0
  135. package/stl/stlSerializer.js.map +1 -0
@@ -0,0 +1,786 @@
1
+ import { Vector3, Quaternion } from "@babylonjs/core/Maths/math.vector.js";
2
+ import { Tools } from "@babylonjs/core/Misc/tools.js";
3
+ import { Animation } from "@babylonjs/core/Animations/animation.js";
4
+ import { TransformNode } from "@babylonjs/core/Meshes/transformNode.js";
5
+ import { MorphTarget } from "@babylonjs/core/Morph/morphTarget.js";
6
+ import { Mesh } from "@babylonjs/core/Meshes/mesh.js";
7
+ import { Camera } from "@babylonjs/core/Cameras/camera.js";
8
+ import { Light } from "@babylonjs/core/Lights/light.js";
9
+ import { GetAccessorElementCount, ConvertToRightHandedPosition, Rotate180Y, ConvertToRightHandedRotation } from "./glTFUtilities.js";
10
+ /**
11
+ * @internal
12
+ * Enum for handling in tangent and out tangent.
13
+ */
14
+ // eslint-disable-next-line @typescript-eslint/naming-convention
15
+ var _TangentType;
16
+ (function (_TangentType) {
17
+ /**
18
+ * Specifies that input tangents are used.
19
+ */
20
+ _TangentType[_TangentType["INTANGENT"] = 0] = "INTANGENT";
21
+ /**
22
+ * Specifies that output tangents are used.
23
+ */
24
+ _TangentType[_TangentType["OUTTANGENT"] = 1] = "OUTTANGENT";
25
+ })(_TangentType || (_TangentType = {}));
26
+ /**
27
+ * @internal
28
+ * Utility class for generating glTF animation data from BabylonJS.
29
+ */
30
+ export class _GLTFAnimation {
31
+ /**
32
+ * Determine if a node is transformable - ie has properties it should be part of animation of transformation.
33
+ * @param babylonNode the node to test
34
+ * @returns true if can be animated, false otherwise. False if the parameter is null or undefined.
35
+ */
36
+ static _IsTransformable(babylonNode) {
37
+ return babylonNode && (babylonNode instanceof TransformNode || babylonNode instanceof Camera || babylonNode instanceof Light);
38
+ }
39
+ /**
40
+ * @ignore
41
+ *
42
+ * Creates glTF channel animation from BabylonJS animation.
43
+ * @param babylonTransformNode - BabylonJS mesh.
44
+ * @param animation - animation.
45
+ * @param animationChannelTargetPath - The target animation channel.
46
+ * @param useQuaternion - Specifies if quaternions are used.
47
+ * @returns nullable IAnimationData
48
+ */
49
+ static _CreateNodeAnimation(babylonTransformNode, animation, animationChannelTargetPath, useQuaternion, animationSampleRate) {
50
+ if (this._IsTransformable(babylonTransformNode)) {
51
+ const inputs = [];
52
+ const outputs = [];
53
+ const keyFrames = animation.getKeys();
54
+ const minMaxKeyFrames = _GLTFAnimation._CalculateMinMaxKeyFrames(keyFrames);
55
+ const interpolationOrBake = _GLTFAnimation._DeduceInterpolation(keyFrames, animationChannelTargetPath, useQuaternion);
56
+ const interpolation = interpolationOrBake.interpolationType;
57
+ const shouldBakeAnimation = interpolationOrBake.shouldBakeAnimation;
58
+ if (shouldBakeAnimation) {
59
+ _GLTFAnimation._CreateBakedAnimation(babylonTransformNode, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, useQuaternion);
60
+ }
61
+ else {
62
+ if (interpolation === "LINEAR" /* AnimationSamplerInterpolation.LINEAR */ || interpolation === "STEP" /* AnimationSamplerInterpolation.STEP */) {
63
+ _GLTFAnimation._CreateLinearOrStepAnimation(babylonTransformNode, animation, animationChannelTargetPath, inputs, outputs, useQuaternion);
64
+ }
65
+ else if (interpolation === "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */) {
66
+ _GLTFAnimation._CreateCubicSplineAnimation(babylonTransformNode, animation, animationChannelTargetPath, inputs, outputs, useQuaternion);
67
+ }
68
+ else {
69
+ _GLTFAnimation._CreateBakedAnimation(babylonTransformNode, animation, animationChannelTargetPath, minMaxKeyFrames.min, minMaxKeyFrames.max, animation.framePerSecond, animationSampleRate, inputs, outputs, minMaxKeyFrames, useQuaternion);
70
+ }
71
+ }
72
+ if (inputs.length && outputs.length) {
73
+ const result = {
74
+ inputs: inputs,
75
+ outputs: outputs,
76
+ samplerInterpolation: interpolation,
77
+ inputsMin: shouldBakeAnimation ? minMaxKeyFrames.min : Tools.FloatRound(minMaxKeyFrames.min / animation.framePerSecond),
78
+ inputsMax: shouldBakeAnimation ? minMaxKeyFrames.max : Tools.FloatRound(minMaxKeyFrames.max / animation.framePerSecond),
79
+ };
80
+ return result;
81
+ }
82
+ }
83
+ return null;
84
+ }
85
+ static _DeduceAnimationInfo(animation) {
86
+ let animationChannelTargetPath = null;
87
+ let dataAccessorType = "VEC3" /* AccessorType.VEC3 */;
88
+ let useQuaternion = false;
89
+ const property = animation.targetProperty.split(".");
90
+ switch (property[0]) {
91
+ case "scaling": {
92
+ animationChannelTargetPath = "scale" /* AnimationChannelTargetPath.SCALE */;
93
+ break;
94
+ }
95
+ case "position": {
96
+ animationChannelTargetPath = "translation" /* AnimationChannelTargetPath.TRANSLATION */;
97
+ break;
98
+ }
99
+ case "rotation": {
100
+ dataAccessorType = "VEC4" /* AccessorType.VEC4 */;
101
+ animationChannelTargetPath = "rotation" /* AnimationChannelTargetPath.ROTATION */;
102
+ break;
103
+ }
104
+ case "rotationQuaternion": {
105
+ dataAccessorType = "VEC4" /* AccessorType.VEC4 */;
106
+ useQuaternion = true;
107
+ animationChannelTargetPath = "rotation" /* AnimationChannelTargetPath.ROTATION */;
108
+ break;
109
+ }
110
+ case "influence": {
111
+ dataAccessorType = "SCALAR" /* AccessorType.SCALAR */;
112
+ animationChannelTargetPath = "weights" /* AnimationChannelTargetPath.WEIGHTS */;
113
+ break;
114
+ }
115
+ default: {
116
+ Tools.Error(`Unsupported animatable property ${property[0]}`);
117
+ }
118
+ }
119
+ if (animationChannelTargetPath) {
120
+ return { animationChannelTargetPath: animationChannelTargetPath, dataAccessorType: dataAccessorType, useQuaternion: useQuaternion };
121
+ }
122
+ else {
123
+ Tools.Error("animation channel target path and data accessor type could be deduced");
124
+ }
125
+ return null;
126
+ }
127
+ /**
128
+ * @ignore
129
+ * Create node animations from the transform node animations
130
+ * @param babylonNode
131
+ * @param runtimeGLTFAnimation
132
+ * @param idleGLTFAnimations
133
+ * @param nodeMap
134
+ * @param nodes
135
+ * @param bufferManager
136
+ * @param bufferViews
137
+ * @param accessors
138
+ * @param animationSampleRate
139
+ */
140
+ static _CreateNodeAnimationFromNodeAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, nodeMap, nodes, bufferManager, bufferViews, accessors, animationSampleRate, useRightHanded, shouldExportAnimation) {
141
+ let glTFAnimation;
142
+ if (_GLTFAnimation._IsTransformable(babylonNode)) {
143
+ if (babylonNode.animations) {
144
+ for (const animation of babylonNode.animations) {
145
+ if (shouldExportAnimation && !shouldExportAnimation(animation)) {
146
+ continue;
147
+ }
148
+ const animationInfo = _GLTFAnimation._DeduceAnimationInfo(animation);
149
+ if (animationInfo) {
150
+ glTFAnimation = {
151
+ name: animation.name,
152
+ samplers: [],
153
+ channels: [],
154
+ };
155
+ _GLTFAnimation._AddAnimation(`${animation.name}`, animation.hasRunningRuntimeAnimations ? runtimeGLTFAnimation : glTFAnimation, babylonNode, animation, animationInfo.dataAccessorType, animationInfo.animationChannelTargetPath, nodeMap, bufferManager, bufferViews, accessors, animationInfo.useQuaternion, animationSampleRate, useRightHanded);
156
+ if (glTFAnimation.samplers.length && glTFAnimation.channels.length) {
157
+ idleGLTFAnimations.push(glTFAnimation);
158
+ }
159
+ }
160
+ }
161
+ }
162
+ }
163
+ }
164
+ /**
165
+ * @ignore
166
+ * Create individual morph animations from the mesh's morph target animation tracks
167
+ * @param babylonNode
168
+ * @param runtimeGLTFAnimation
169
+ * @param idleGLTFAnimations
170
+ * @param nodeMap
171
+ * @param nodes
172
+ * @param bufferManager
173
+ * @param bufferViews
174
+ * @param accessors
175
+ * @param animationSampleRate
176
+ */
177
+ static _CreateMorphTargetAnimationFromMorphTargetAnimations(babylonNode, runtimeGLTFAnimation, idleGLTFAnimations, nodeMap, nodes, bufferManager, bufferViews, accessors, animationSampleRate, useRightHanded, shouldExportAnimation) {
178
+ let glTFAnimation;
179
+ if (babylonNode instanceof Mesh) {
180
+ const morphTargetManager = babylonNode.morphTargetManager;
181
+ if (morphTargetManager) {
182
+ for (let i = 0; i < morphTargetManager.numTargets; ++i) {
183
+ const morphTarget = morphTargetManager.getTarget(i);
184
+ for (const animation of morphTarget.animations) {
185
+ if (shouldExportAnimation && !shouldExportAnimation(animation)) {
186
+ continue;
187
+ }
188
+ const combinedAnimation = new Animation(`${animation.name}`, "influence", animation.framePerSecond, animation.dataType, animation.loopMode, animation.enableBlending);
189
+ const combinedAnimationKeys = [];
190
+ const animationKeys = animation.getKeys();
191
+ for (let j = 0; j < animationKeys.length; ++j) {
192
+ const animationKey = animationKeys[j];
193
+ for (let k = 0; k < morphTargetManager.numTargets; ++k) {
194
+ if (k == i) {
195
+ combinedAnimationKeys.push(animationKey);
196
+ }
197
+ else {
198
+ combinedAnimationKeys.push({ frame: animationKey.frame, value: 0 });
199
+ }
200
+ }
201
+ }
202
+ combinedAnimation.setKeys(combinedAnimationKeys);
203
+ const animationInfo = _GLTFAnimation._DeduceAnimationInfo(combinedAnimation);
204
+ if (animationInfo) {
205
+ glTFAnimation = {
206
+ name: combinedAnimation.name,
207
+ samplers: [],
208
+ channels: [],
209
+ };
210
+ _GLTFAnimation._AddAnimation(animation.name, animation.hasRunningRuntimeAnimations ? runtimeGLTFAnimation : glTFAnimation, babylonNode, combinedAnimation, animationInfo.dataAccessorType, animationInfo.animationChannelTargetPath, nodeMap, bufferManager, bufferViews, accessors, animationInfo.useQuaternion, animationSampleRate, useRightHanded, morphTargetManager.numTargets);
211
+ if (glTFAnimation.samplers.length && glTFAnimation.channels.length) {
212
+ idleGLTFAnimations.push(glTFAnimation);
213
+ }
214
+ }
215
+ }
216
+ }
217
+ }
218
+ }
219
+ }
220
+ /**
221
+ * @internal
222
+ * Create node and morph animations from the animation groups
223
+ * @param babylonScene
224
+ * @param glTFAnimations
225
+ * @param nodeMap
226
+ * @param nodes
227
+ * @param bufferManager
228
+ * @param bufferViews
229
+ * @param accessors
230
+ * @param animationSampleRate
231
+ */
232
+ static _CreateNodeAndMorphAnimationFromAnimationGroups(babylonScene, glTFAnimations, nodeMap, bufferManager, bufferViews, accessors, animationSampleRate, leftHandedNodes, shouldExportAnimation) {
233
+ let glTFAnimation;
234
+ if (babylonScene.animationGroups) {
235
+ const animationGroups = babylonScene.animationGroups;
236
+ for (const animationGroup of animationGroups) {
237
+ const morphAnimations = new Map();
238
+ const sampleAnimations = new Map();
239
+ const morphAnimationMeshes = new Set();
240
+ const animationGroupFrameDiff = animationGroup.to - animationGroup.from;
241
+ glTFAnimation = {
242
+ name: animationGroup.name,
243
+ channels: [],
244
+ samplers: [],
245
+ };
246
+ for (let i = 0; i < animationGroup.targetedAnimations.length; ++i) {
247
+ const targetAnimation = animationGroup.targetedAnimations[i];
248
+ const target = targetAnimation.target;
249
+ const animation = targetAnimation.animation;
250
+ if (shouldExportAnimation && !shouldExportAnimation(animation)) {
251
+ continue;
252
+ }
253
+ const convertToRightHanded = leftHandedNodes.has(target);
254
+ if (this._IsTransformable(target) || (target.length === 1 && this._IsTransformable(target[0]))) {
255
+ const animationInfo = _GLTFAnimation._DeduceAnimationInfo(targetAnimation.animation);
256
+ if (animationInfo) {
257
+ const babylonTransformNode = this._IsTransformable(target) ? target : this._IsTransformable(target[0]) ? target[0] : null;
258
+ if (babylonTransformNode) {
259
+ _GLTFAnimation._AddAnimation(`${animation.name}`, glTFAnimation, babylonTransformNode, animation, animationInfo.dataAccessorType, animationInfo.animationChannelTargetPath, nodeMap, bufferManager, bufferViews, accessors, animationInfo.useQuaternion, animationSampleRate, convertToRightHanded);
260
+ }
261
+ }
262
+ }
263
+ else if (target instanceof MorphTarget || (target.length === 1 && target[0] instanceof MorphTarget)) {
264
+ const animationInfo = _GLTFAnimation._DeduceAnimationInfo(targetAnimation.animation);
265
+ if (animationInfo) {
266
+ const babylonMorphTarget = target instanceof MorphTarget ? target : target[0];
267
+ if (babylonMorphTarget) {
268
+ const babylonMorphTargetManager = babylonScene.morphTargetManagers.find((morphTargetManager) => {
269
+ for (let j = 0; j < morphTargetManager.numTargets; ++j) {
270
+ if (morphTargetManager.getTarget(j) === babylonMorphTarget) {
271
+ return true;
272
+ }
273
+ }
274
+ return false;
275
+ });
276
+ if (babylonMorphTargetManager) {
277
+ const babylonMesh = babylonScene.meshes.find((mesh) => {
278
+ return mesh.morphTargetManager === babylonMorphTargetManager;
279
+ });
280
+ if (babylonMesh) {
281
+ if (!morphAnimations.has(babylonMesh)) {
282
+ morphAnimations.set(babylonMesh, new Map());
283
+ }
284
+ morphAnimations.get(babylonMesh)?.set(babylonMorphTarget, animation);
285
+ morphAnimationMeshes.add(babylonMesh);
286
+ sampleAnimations.set(babylonMesh, animation);
287
+ }
288
+ }
289
+ }
290
+ }
291
+ }
292
+ else {
293
+ // this is the place for the KHR_animation_pointer.
294
+ }
295
+ }
296
+ morphAnimationMeshes.forEach((mesh) => {
297
+ const morphTargetManager = mesh.morphTargetManager;
298
+ let combinedAnimationGroup = null;
299
+ const animationKeys = [];
300
+ const sampleAnimation = sampleAnimations.get(mesh);
301
+ const sampleAnimationKeys = sampleAnimation.getKeys();
302
+ const numAnimationKeys = sampleAnimationKeys.length;
303
+ /*
304
+ Due to how glTF expects morph target animation data to be formatted, we need to rearrange the individual morph target animation tracks,
305
+ such that we have a single animation, where a given keyframe input value has successive output values for each morph target belonging to the manager.
306
+ See: https://github.com/KhronosGroup/glTF/tree/master/specification/2.0#animations
307
+
308
+ We do this via constructing a new Animation track, and interleaving the frames of each morph target animation track in the current Animation Group
309
+ We reuse the Babylon Animation data structure for ease of handling export of cubic spline animation keys, and to reuse the
310
+ existing _GLTFAnimation.AddAnimation codepath with minimal modification, however the constructed Babylon Animation is NOT intended for use in-engine.
311
+ */
312
+ for (let i = 0; i < numAnimationKeys; ++i) {
313
+ for (let j = 0; j < morphTargetManager.numTargets; ++j) {
314
+ const morphTarget = morphTargetManager.getTarget(j);
315
+ const animationsByMorphTarget = morphAnimations.get(mesh);
316
+ if (animationsByMorphTarget) {
317
+ const morphTargetAnimation = animationsByMorphTarget.get(morphTarget);
318
+ if (morphTargetAnimation) {
319
+ if (!combinedAnimationGroup) {
320
+ combinedAnimationGroup = new Animation(`${animationGroup.name}_${mesh.name}_MorphWeightAnimation`, "influence", morphTargetAnimation.framePerSecond, Animation.ANIMATIONTYPE_FLOAT, morphTargetAnimation.loopMode, morphTargetAnimation.enableBlending);
321
+ }
322
+ animationKeys.push(morphTargetAnimation.getKeys()[i]);
323
+ }
324
+ else {
325
+ animationKeys.push({
326
+ frame: animationGroup.from + (animationGroupFrameDiff / numAnimationKeys) * i,
327
+ value: morphTarget.influence,
328
+ inTangent: sampleAnimationKeys[0].inTangent ? 0 : undefined,
329
+ outTangent: sampleAnimationKeys[0].outTangent ? 0 : undefined,
330
+ });
331
+ }
332
+ }
333
+ }
334
+ }
335
+ combinedAnimationGroup.setKeys(animationKeys);
336
+ const animationInfo = _GLTFAnimation._DeduceAnimationInfo(combinedAnimationGroup);
337
+ if (animationInfo) {
338
+ _GLTFAnimation._AddAnimation(`${animationGroup.name}_${mesh.name}_MorphWeightAnimation`, glTFAnimation, mesh, combinedAnimationGroup, animationInfo.dataAccessorType, animationInfo.animationChannelTargetPath, nodeMap, bufferManager, bufferViews, accessors, animationInfo.useQuaternion, animationSampleRate, false, morphTargetManager?.numTargets);
339
+ }
340
+ });
341
+ if (glTFAnimation.channels.length && glTFAnimation.samplers.length) {
342
+ glTFAnimations.push(glTFAnimation);
343
+ }
344
+ }
345
+ }
346
+ }
347
+ static _AddAnimation(name, glTFAnimation, babylonTransformNode, animation, dataAccessorType, animationChannelTargetPath, nodeMap, bufferManager, bufferViews, accessors, useQuaternion, animationSampleRate, convertToRightHanded, morphAnimationChannels) {
348
+ const animationData = _GLTFAnimation._CreateNodeAnimation(babylonTransformNode, animation, animationChannelTargetPath, useQuaternion, animationSampleRate);
349
+ let bufferView;
350
+ let accessor;
351
+ let keyframeAccessorIndex;
352
+ let dataAccessorIndex;
353
+ let animationSampler;
354
+ let animationChannel;
355
+ if (animationData) {
356
+ /*
357
+ * Now that we have the glTF converted morph target animation data,
358
+ * we can remove redundant input data so that we have n input frames,
359
+ * and morphAnimationChannels * n output frames
360
+ */
361
+ if (morphAnimationChannels) {
362
+ let index = 0;
363
+ let currentInput = 0;
364
+ const newInputs = [];
365
+ while (animationData.inputs.length > 0) {
366
+ currentInput = animationData.inputs.shift();
367
+ if (index % morphAnimationChannels == 0) {
368
+ newInputs.push(currentInput);
369
+ }
370
+ index++;
371
+ }
372
+ animationData.inputs = newInputs;
373
+ }
374
+ const nodeIndex = nodeMap.get(babylonTransformNode);
375
+ // Create buffer view and accessor for key frames.
376
+ const inputData = new Float32Array(animationData.inputs);
377
+ bufferView = bufferManager.createBufferView(inputData);
378
+ accessor = bufferManager.createAccessor(bufferView, "SCALAR" /* AccessorType.SCALAR */, 5126 /* AccessorComponentType.FLOAT */, animationData.inputs.length, undefined, {
379
+ min: [animationData.inputsMin],
380
+ max: [animationData.inputsMax],
381
+ });
382
+ accessors.push(accessor);
383
+ keyframeAccessorIndex = accessors.length - 1;
384
+ // Perform conversions on keyed values while also building their buffer.
385
+ const rotationQuaternion = new Quaternion();
386
+ const eulerVec3 = new Vector3();
387
+ const position = new Vector3();
388
+ const isCamera = babylonTransformNode instanceof Camera;
389
+ const elementCount = GetAccessorElementCount(dataAccessorType);
390
+ const outputData = new Float32Array(animationData.outputs.length * elementCount);
391
+ animationData.outputs.forEach(function (output, index) {
392
+ let outputToWrite = output;
393
+ switch (animationChannelTargetPath) {
394
+ case "translation" /* AnimationChannelTargetPath.TRANSLATION */:
395
+ if (convertToRightHanded) {
396
+ Vector3.FromArrayToRef(output, 0, position);
397
+ ConvertToRightHandedPosition(position);
398
+ position.toArray(outputToWrite);
399
+ }
400
+ break;
401
+ case "rotation" /* AnimationChannelTargetPath.ROTATION */:
402
+ if (output.length === 4) {
403
+ Quaternion.FromArrayToRef(output, 0, rotationQuaternion);
404
+ }
405
+ else {
406
+ outputToWrite = new Array(4); // Will need 4, not 3, for a quaternion
407
+ Vector3.FromArrayToRef(output, 0, eulerVec3);
408
+ Quaternion.FromEulerVectorToRef(eulerVec3, rotationQuaternion);
409
+ }
410
+ if (convertToRightHanded) {
411
+ ConvertToRightHandedRotation(rotationQuaternion);
412
+ if (isCamera) {
413
+ Rotate180Y(rotationQuaternion);
414
+ }
415
+ }
416
+ rotationQuaternion.toArray(outputToWrite);
417
+ break;
418
+ }
419
+ outputData.set(outputToWrite, index * elementCount);
420
+ });
421
+ // Create buffer view and accessor for keyed values.
422
+ bufferView = bufferManager.createBufferView(outputData);
423
+ accessor = bufferManager.createAccessor(bufferView, dataAccessorType, 5126 /* AccessorComponentType.FLOAT */, animationData.outputs.length);
424
+ accessors.push(accessor);
425
+ dataAccessorIndex = accessors.length - 1;
426
+ // create sampler
427
+ animationSampler = {
428
+ interpolation: animationData.samplerInterpolation,
429
+ input: keyframeAccessorIndex,
430
+ output: dataAccessorIndex,
431
+ };
432
+ glTFAnimation.samplers.push(animationSampler);
433
+ // create channel
434
+ animationChannel = {
435
+ sampler: glTFAnimation.samplers.length - 1,
436
+ target: {
437
+ node: nodeIndex,
438
+ path: animationChannelTargetPath,
439
+ },
440
+ };
441
+ glTFAnimation.channels.push(animationChannel);
442
+ }
443
+ }
444
+ /**
445
+ * Create a baked animation
446
+ * @param babylonTransformNode BabylonJS mesh
447
+ * @param animation BabylonJS animation corresponding to the BabylonJS mesh
448
+ * @param animationChannelTargetPath animation target channel
449
+ * @param minFrame minimum animation frame
450
+ * @param maxFrame maximum animation frame
451
+ * @param fps frames per second of the animation
452
+ * @param sampleRate
453
+ * @param inputs input key frames of the animation
454
+ * @param outputs output key frame data of the animation
455
+ * @param minMaxFrames
456
+ * @param minMaxFrames.min
457
+ * @param minMaxFrames.max
458
+ * @param useQuaternion specifies if quaternions should be used
459
+ */
460
+ static _CreateBakedAnimation(babylonTransformNode, animation, animationChannelTargetPath, minFrame, maxFrame, fps, sampleRate, inputs, outputs, minMaxFrames, useQuaternion) {
461
+ let value;
462
+ const quaternionCache = Quaternion.Identity();
463
+ let previousTime = null;
464
+ let time;
465
+ let maxUsedFrame = null;
466
+ let currKeyFrame = null;
467
+ let nextKeyFrame = null;
468
+ let prevKeyFrame = null;
469
+ let endFrame = null;
470
+ minMaxFrames.min = Tools.FloatRound(minFrame / fps);
471
+ const keyFrames = animation.getKeys();
472
+ for (let i = 0, length = keyFrames.length; i < length; ++i) {
473
+ endFrame = null;
474
+ currKeyFrame = keyFrames[i];
475
+ if (i + 1 < length) {
476
+ nextKeyFrame = keyFrames[i + 1];
477
+ if ((currKeyFrame.value.equals && currKeyFrame.value.equals(nextKeyFrame.value)) || currKeyFrame.value === nextKeyFrame.value) {
478
+ if (i === 0) {
479
+ // set the first frame to itself
480
+ endFrame = currKeyFrame.frame;
481
+ }
482
+ else {
483
+ continue;
484
+ }
485
+ }
486
+ else {
487
+ endFrame = nextKeyFrame.frame;
488
+ }
489
+ }
490
+ else {
491
+ // at the last key frame
492
+ prevKeyFrame = keyFrames[i - 1];
493
+ if ((currKeyFrame.value.equals && currKeyFrame.value.equals(prevKeyFrame.value)) || currKeyFrame.value === prevKeyFrame.value) {
494
+ continue;
495
+ }
496
+ else {
497
+ endFrame = maxFrame;
498
+ }
499
+ }
500
+ if (endFrame) {
501
+ for (let f = currKeyFrame.frame; f <= endFrame; f += sampleRate) {
502
+ time = Tools.FloatRound(f / fps);
503
+ if (time === previousTime) {
504
+ continue;
505
+ }
506
+ previousTime = time;
507
+ maxUsedFrame = time;
508
+ const state = {
509
+ key: 0,
510
+ repeatCount: 0,
511
+ loopMode: animation.loopMode,
512
+ };
513
+ value = animation._interpolate(f, state);
514
+ _GLTFAnimation._SetInterpolatedValue(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, useQuaternion);
515
+ }
516
+ }
517
+ }
518
+ if (maxUsedFrame) {
519
+ minMaxFrames.max = maxUsedFrame;
520
+ }
521
+ }
522
+ static _ConvertFactorToVector3OrQuaternion(factor, babylonTransformNode, animation, animationChannelTargetPath, useQuaternion) {
523
+ const basePositionRotationOrScale = _GLTFAnimation._GetBasePositionRotationOrScale(babylonTransformNode, animationChannelTargetPath, useQuaternion);
524
+ // handles single component x, y, z or w component animation by using a base property and animating over a component.
525
+ const property = animation.targetProperty.split(".");
526
+ const componentName = property ? property[1] : ""; // x, y, z, or w component
527
+ const value = useQuaternion ? Quaternion.FromArray(basePositionRotationOrScale).normalize() : Vector3.FromArray(basePositionRotationOrScale);
528
+ switch (componentName) {
529
+ case "x":
530
+ case "y":
531
+ case "z": {
532
+ value[componentName] = factor;
533
+ break;
534
+ }
535
+ case "w": {
536
+ value.w = factor;
537
+ break;
538
+ }
539
+ default: {
540
+ Tools.Error(`glTFAnimation: Unsupported component name "${componentName}"!`);
541
+ }
542
+ }
543
+ return value;
544
+ }
545
+ static _SetInterpolatedValue(babylonTransformNode, value, time, animation, animationChannelTargetPath, quaternionCache, inputs, outputs, useQuaternion) {
546
+ let cacheValue;
547
+ inputs.push(time);
548
+ if (animationChannelTargetPath === "weights" /* AnimationChannelTargetPath.WEIGHTS */) {
549
+ outputs.push([value]);
550
+ return;
551
+ }
552
+ if (animation.dataType === Animation.ANIMATIONTYPE_FLOAT) {
553
+ value = this._ConvertFactorToVector3OrQuaternion(value, babylonTransformNode, animation, animationChannelTargetPath, useQuaternion);
554
+ }
555
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */) {
556
+ if (useQuaternion) {
557
+ quaternionCache = value;
558
+ }
559
+ else {
560
+ cacheValue = value;
561
+ Quaternion.RotationYawPitchRollToRef(cacheValue.y, cacheValue.x, cacheValue.z, quaternionCache);
562
+ }
563
+ outputs.push(quaternionCache.asArray());
564
+ }
565
+ else {
566
+ // scaling and position animation
567
+ cacheValue = value;
568
+ outputs.push(cacheValue.asArray());
569
+ }
570
+ }
571
+ /**
572
+ * Creates linear animation from the animation key frames
573
+ * @param babylonTransformNode BabylonJS mesh
574
+ * @param animation BabylonJS animation
575
+ * @param animationChannelTargetPath The target animation channel
576
+ * @param inputs Array to store the key frame times
577
+ * @param outputs Array to store the key frame data
578
+ * @param useQuaternion Specifies if quaternions are used in the animation
579
+ */
580
+ static _CreateLinearOrStepAnimation(babylonTransformNode, animation, animationChannelTargetPath, inputs, outputs, useQuaternion) {
581
+ for (const keyFrame of animation.getKeys()) {
582
+ inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
583
+ _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, useQuaternion);
584
+ }
585
+ }
586
+ /**
587
+ * Creates cubic spline animation from the animation key frames
588
+ * @param babylonTransformNode BabylonJS mesh
589
+ * @param animation BabylonJS animation
590
+ * @param animationChannelTargetPath The target animation channel
591
+ * @param inputs Array to store the key frame times
592
+ * @param outputs Array to store the key frame data
593
+ * @param useQuaternion Specifies if quaternions are used in the animation
594
+ */
595
+ static _CreateCubicSplineAnimation(babylonTransformNode, animation, animationChannelTargetPath, inputs, outputs, useQuaternion) {
596
+ animation.getKeys().forEach(function (keyFrame) {
597
+ inputs.push(keyFrame.frame / animation.framePerSecond); // keyframes in seconds.
598
+ _GLTFAnimation._AddSplineTangent(_TangentType.INTANGENT, outputs, animationChannelTargetPath, "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */, keyFrame, useQuaternion);
599
+ _GLTFAnimation._AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, useQuaternion);
600
+ _GLTFAnimation._AddSplineTangent(_TangentType.OUTTANGENT, outputs, animationChannelTargetPath, "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */, keyFrame, useQuaternion);
601
+ });
602
+ }
603
+ static _GetBasePositionRotationOrScale(babylonTransformNode, animationChannelTargetPath, useQuaternion) {
604
+ let basePositionRotationOrScale;
605
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */) {
606
+ if (useQuaternion) {
607
+ const q = babylonTransformNode.rotationQuaternion;
608
+ basePositionRotationOrScale = (q ?? Quaternion.Identity()).asArray();
609
+ }
610
+ else {
611
+ const r = babylonTransformNode.rotation;
612
+ basePositionRotationOrScale = (r ?? Vector3.Zero()).asArray();
613
+ }
614
+ }
615
+ else if (animationChannelTargetPath === "translation" /* AnimationChannelTargetPath.TRANSLATION */) {
616
+ const p = babylonTransformNode.position;
617
+ basePositionRotationOrScale = (p ?? Vector3.Zero()).asArray();
618
+ }
619
+ else {
620
+ // scale
621
+ const s = babylonTransformNode.scaling;
622
+ basePositionRotationOrScale = (s ?? Vector3.One()).asArray();
623
+ }
624
+ return basePositionRotationOrScale;
625
+ }
626
+ /**
627
+ * Adds a key frame value
628
+ * @param keyFrame
629
+ * @param animation
630
+ * @param outputs
631
+ * @param animationChannelTargetPath
632
+ * @param babylonTransformNode
633
+ * @param useQuaternion
634
+ */
635
+ static _AddKeyframeValue(keyFrame, animation, outputs, animationChannelTargetPath, babylonTransformNode, useQuaternion) {
636
+ let newPositionRotationOrScale;
637
+ const animationType = animation.dataType;
638
+ if (animationType === Animation.ANIMATIONTYPE_VECTOR3) {
639
+ let value = keyFrame.value.asArray();
640
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */) {
641
+ const array = Vector3.FromArray(value);
642
+ const rotationQuaternion = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z);
643
+ value = rotationQuaternion.asArray();
644
+ }
645
+ outputs.push(value); // scale vector.
646
+ }
647
+ else if (animationType === Animation.ANIMATIONTYPE_FLOAT) {
648
+ if (animationChannelTargetPath === "weights" /* AnimationChannelTargetPath.WEIGHTS */) {
649
+ outputs.push([keyFrame.value]);
650
+ }
651
+ else {
652
+ // handles single component x, y, z or w component animation by using a base property and animating over a component.
653
+ newPositionRotationOrScale = this._ConvertFactorToVector3OrQuaternion(keyFrame.value, babylonTransformNode, animation, animationChannelTargetPath, useQuaternion);
654
+ if (newPositionRotationOrScale) {
655
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */) {
656
+ const posRotScale = useQuaternion
657
+ ? newPositionRotationOrScale
658
+ : Quaternion.RotationYawPitchRoll(newPositionRotationOrScale.y, newPositionRotationOrScale.x, newPositionRotationOrScale.z).normalize();
659
+ outputs.push(posRotScale.asArray());
660
+ }
661
+ outputs.push(newPositionRotationOrScale.asArray());
662
+ }
663
+ }
664
+ }
665
+ else if (animationType === Animation.ANIMATIONTYPE_QUATERNION) {
666
+ outputs.push(keyFrame.value.normalize().asArray());
667
+ }
668
+ else {
669
+ Tools.Error("glTFAnimation: Unsupported key frame values for animation!");
670
+ }
671
+ }
672
+ /**
673
+ * @internal
674
+ * Determine the interpolation based on the key frames
675
+ * @param keyFrames
676
+ * @param animationChannelTargetPath
677
+ * @param useQuaternion
678
+ */
679
+ static _DeduceInterpolation(keyFrames, animationChannelTargetPath, useQuaternion) {
680
+ let interpolationType;
681
+ let shouldBakeAnimation = false;
682
+ let key;
683
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */ && !useQuaternion) {
684
+ return { interpolationType: "LINEAR" /* AnimationSamplerInterpolation.LINEAR */, shouldBakeAnimation: true };
685
+ }
686
+ for (let i = 0, length = keyFrames.length; i < length; ++i) {
687
+ key = keyFrames[i];
688
+ if (key.inTangent || key.outTangent) {
689
+ if (interpolationType) {
690
+ if (interpolationType !== "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */) {
691
+ interpolationType = "LINEAR" /* AnimationSamplerInterpolation.LINEAR */;
692
+ shouldBakeAnimation = true;
693
+ break;
694
+ }
695
+ }
696
+ else {
697
+ interpolationType = "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */;
698
+ }
699
+ }
700
+ else {
701
+ if (interpolationType) {
702
+ if (interpolationType === "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */ ||
703
+ (key.interpolation && key.interpolation === 1 /* AnimationKeyInterpolation.STEP */ && interpolationType !== "STEP" /* AnimationSamplerInterpolation.STEP */)) {
704
+ interpolationType = "LINEAR" /* AnimationSamplerInterpolation.LINEAR */;
705
+ shouldBakeAnimation = true;
706
+ break;
707
+ }
708
+ }
709
+ else {
710
+ if (key.interpolation && key.interpolation === 1 /* AnimationKeyInterpolation.STEP */) {
711
+ interpolationType = "STEP" /* AnimationSamplerInterpolation.STEP */;
712
+ }
713
+ else {
714
+ interpolationType = "LINEAR" /* AnimationSamplerInterpolation.LINEAR */;
715
+ }
716
+ }
717
+ }
718
+ }
719
+ if (!interpolationType) {
720
+ interpolationType = "LINEAR" /* AnimationSamplerInterpolation.LINEAR */;
721
+ }
722
+ return { interpolationType: interpolationType, shouldBakeAnimation: shouldBakeAnimation };
723
+ }
724
+ /**
725
+ * Adds an input tangent or output tangent to the output data
726
+ * If an input tangent or output tangent is missing, it uses the zero vector or zero quaternion
727
+ * @param tangentType Specifies which type of tangent to handle (inTangent or outTangent)
728
+ * @param outputs The animation data by keyframe
729
+ * @param animationChannelTargetPath The target animation channel
730
+ * @param interpolation The interpolation type
731
+ * @param keyFrame The key frame with the animation data
732
+ * @param useQuaternion Specifies if quaternions are used
733
+ */
734
+ static _AddSplineTangent(tangentType, outputs, animationChannelTargetPath, interpolation, keyFrame, useQuaternion) {
735
+ let tangent;
736
+ const tangentValue = tangentType === _TangentType.INTANGENT ? keyFrame.inTangent : keyFrame.outTangent;
737
+ if (interpolation === "CUBICSPLINE" /* AnimationSamplerInterpolation.CUBICSPLINE */) {
738
+ if (animationChannelTargetPath === "rotation" /* AnimationChannelTargetPath.ROTATION */) {
739
+ if (tangentValue) {
740
+ if (useQuaternion) {
741
+ tangent = tangentValue.asArray();
742
+ }
743
+ else {
744
+ const array = tangentValue;
745
+ tangent = Quaternion.RotationYawPitchRoll(array.y, array.x, array.z).asArray();
746
+ }
747
+ }
748
+ else {
749
+ tangent = [0, 0, 0, 0];
750
+ }
751
+ }
752
+ else if (animationChannelTargetPath === "weights" /* AnimationChannelTargetPath.WEIGHTS */) {
753
+ if (tangentValue) {
754
+ tangent = [tangentValue];
755
+ }
756
+ else {
757
+ tangent = [0];
758
+ }
759
+ }
760
+ else {
761
+ if (tangentValue) {
762
+ tangent = tangentValue.asArray();
763
+ }
764
+ else {
765
+ tangent = [0, 0, 0];
766
+ }
767
+ }
768
+ outputs.push(tangent);
769
+ }
770
+ }
771
+ /**
772
+ * Get the minimum and maximum key frames' frame values
773
+ * @param keyFrames animation key frames
774
+ * @returns the minimum and maximum key frame value
775
+ */
776
+ static _CalculateMinMaxKeyFrames(keyFrames) {
777
+ let min = Infinity;
778
+ let max = -Infinity;
779
+ keyFrames.forEach(function (keyFrame) {
780
+ min = Math.min(min, keyFrame.frame);
781
+ max = Math.max(max, keyFrame.frame);
782
+ });
783
+ return { min: min, max: max };
784
+ }
785
+ }
786
+ //# sourceMappingURL=glTFAnimation.js.map