@aura3d/assets 1.0.6

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 (324) hide show
  1. package/README.md +17 -0
  2. package/dist/AdvancedAssetCorpus.d.ts +124 -0
  3. package/dist/AdvancedAssetCorpus.d.ts.map +1 -0
  4. package/dist/AdvancedAssetCorpus.js +266 -0
  5. package/dist/AdvancedAssetCorpus.js.map +1 -0
  6. package/dist/AssetBundleCacheFixtures.d.ts +62 -0
  7. package/dist/AssetBundleCacheFixtures.d.ts.map +1 -0
  8. package/dist/AssetBundleCacheFixtures.js +222 -0
  9. package/dist/AssetBundleCacheFixtures.js.map +1 -0
  10. package/dist/AssetCache.d.ts +21 -0
  11. package/dist/AssetCache.d.ts.map +1 -0
  12. package/dist/AssetCache.js +54 -0
  13. package/dist/AssetCache.js.map +1 -0
  14. package/dist/AssetCompatibility.d.ts +54 -0
  15. package/dist/AssetCompatibility.d.ts.map +1 -0
  16. package/dist/AssetCompatibility.js +122 -0
  17. package/dist/AssetCompatibility.js.map +1 -0
  18. package/dist/AssetCorpus.d.ts +88 -0
  19. package/dist/AssetCorpus.d.ts.map +1 -0
  20. package/dist/AssetCorpus.js +215 -0
  21. package/dist/AssetCorpus.js.map +1 -0
  22. package/dist/AssetDependencyGraph.d.ts +12 -0
  23. package/dist/AssetDependencyGraph.d.ts.map +1 -0
  24. package/dist/AssetDependencyGraph.js +66 -0
  25. package/dist/AssetDependencyGraph.js.map +1 -0
  26. package/dist/AssetHandle.d.ts +26 -0
  27. package/dist/AssetHandle.d.ts.map +1 -0
  28. package/dist/AssetHandle.js +53 -0
  29. package/dist/AssetHandle.js.map +1 -0
  30. package/dist/AssetImportPreflight.d.ts +43 -0
  31. package/dist/AssetImportPreflight.d.ts.map +1 -0
  32. package/dist/AssetImportPreflight.js +117 -0
  33. package/dist/AssetImportPreflight.js.map +1 -0
  34. package/dist/AssetInspection.d.ts +183 -0
  35. package/dist/AssetInspection.d.ts.map +1 -0
  36. package/dist/AssetInspection.js +397 -0
  37. package/dist/AssetInspection.js.map +1 -0
  38. package/dist/AssetLoader.d.ts +26 -0
  39. package/dist/AssetLoader.d.ts.map +1 -0
  40. package/dist/AssetLoader.js +12 -0
  41. package/dist/AssetLoader.js.map +1 -0
  42. package/dist/AssetManager.d.ts +37 -0
  43. package/dist/AssetManager.d.ts.map +1 -0
  44. package/dist/AssetManager.js +161 -0
  45. package/dist/AssetManager.js.map +1 -0
  46. package/dist/AssetRegistry.d.ts +10 -0
  47. package/dist/AssetRegistry.d.ts.map +1 -0
  48. package/dist/AssetRegistry.js +34 -0
  49. package/dist/AssetRegistry.js.map +1 -0
  50. package/dist/AssetRenderDefaults.d.ts +13 -0
  51. package/dist/AssetRenderDefaults.d.ts.map +1 -0
  52. package/dist/AssetRenderDefaults.js +23 -0
  53. package/dist/AssetRenderDefaults.js.map +1 -0
  54. package/dist/AudioLoader.d.ts +17 -0
  55. package/dist/AudioLoader.d.ts.map +1 -0
  56. package/dist/AudioLoader.js +23 -0
  57. package/dist/AudioLoader.js.map +1 -0
  58. package/dist/BlenderExportValidation.d.ts +64 -0
  59. package/dist/BlenderExportValidation.d.ts.map +1 -0
  60. package/dist/BlenderExportValidation.js +143 -0
  61. package/dist/BlenderExportValidation.js.map +1 -0
  62. package/dist/CarConceptMaterialStability.d.ts +28 -0
  63. package/dist/CarConceptMaterialStability.d.ts.map +1 -0
  64. package/dist/CarConceptMaterialStability.js +1308 -0
  65. package/dist/CarConceptMaterialStability.js.map +1 -0
  66. package/dist/EXRLoader.d.ts +2 -0
  67. package/dist/EXRLoader.d.ts.map +1 -0
  68. package/dist/EXRLoader.js +2 -0
  69. package/dist/EXRLoader.js.map +1 -0
  70. package/dist/ExternalParityGLTFCorpus.d.ts +39 -0
  71. package/dist/ExternalParityGLTFCorpus.d.ts.map +1 -0
  72. package/dist/ExternalParityGLTFCorpus.js +32 -0
  73. package/dist/ExternalParityGLTFCorpus.js.map +1 -0
  74. package/dist/GLTFAnimationRuntime.d.ts +243 -0
  75. package/dist/GLTFAnimationRuntime.d.ts.map +1 -0
  76. package/dist/GLTFAnimationRuntime.js +954 -0
  77. package/dist/GLTFAnimationRuntime.js.map +1 -0
  78. package/dist/GLTFCompressionDecoders.d.ts +42 -0
  79. package/dist/GLTFCompressionDecoders.d.ts.map +1 -0
  80. package/dist/GLTFCompressionDecoders.js +99 -0
  81. package/dist/GLTFCompressionDecoders.js.map +1 -0
  82. package/dist/GLTFExtensionSupport.d.ts +33 -0
  83. package/dist/GLTFExtensionSupport.d.ts.map +1 -0
  84. package/dist/GLTFExtensionSupport.js +85 -0
  85. package/dist/GLTFExtensionSupport.js.map +1 -0
  86. package/dist/GLTFLoader.d.ts +361 -0
  87. package/dist/GLTFLoader.d.ts.map +1 -0
  88. package/dist/GLTFLoader.js +2735 -0
  89. package/dist/GLTFLoader.js.map +1 -0
  90. package/dist/GLTFRenderResources.d.ts +162 -0
  91. package/dist/GLTFRenderResources.d.ts.map +1 -0
  92. package/dist/GLTFRenderResources.js +1684 -0
  93. package/dist/GLTFRenderResources.js.map +1 -0
  94. package/dist/HDRLoader.d.ts +2 -0
  95. package/dist/HDRLoader.d.ts.map +1 -0
  96. package/dist/HDRLoader.js +2 -0
  97. package/dist/HDRLoader.js.map +1 -0
  98. package/dist/ImageLoader.d.ts +15 -0
  99. package/dist/ImageLoader.d.ts.map +1 -0
  100. package/dist/ImageLoader.js +36 -0
  101. package/dist/ImageLoader.js.map +1 -0
  102. package/dist/ImportPipeline.d.ts +39 -0
  103. package/dist/ImportPipeline.d.ts.map +1 -0
  104. package/dist/ImportPipeline.js +105 -0
  105. package/dist/ImportPipeline.js.map +1 -0
  106. package/dist/KTX2BasisTextureTranscoder.d.ts +9 -0
  107. package/dist/KTX2BasisTextureTranscoder.d.ts.map +1 -0
  108. package/dist/KTX2BasisTextureTranscoder.js +178 -0
  109. package/dist/KTX2BasisTextureTranscoder.js.map +1 -0
  110. package/dist/LoadContext.d.ts +20 -0
  111. package/dist/LoadContext.d.ts.map +1 -0
  112. package/dist/LoadContext.js +42 -0
  113. package/dist/LoadContext.js.map +1 -0
  114. package/dist/MaterialLoader.d.ts +17 -0
  115. package/dist/MaterialLoader.d.ts.map +1 -0
  116. package/dist/MaterialLoader.js +138 -0
  117. package/dist/MaterialLoader.js.map +1 -0
  118. package/dist/MeshOptimization.d.ts +20 -0
  119. package/dist/MeshOptimization.d.ts.map +1 -0
  120. package/dist/MeshOptimization.js +65 -0
  121. package/dist/MeshOptimization.js.map +1 -0
  122. package/dist/OBJLoader.d.ts +13 -0
  123. package/dist/OBJLoader.d.ts.map +1 -0
  124. package/dist/OBJLoader.js +492 -0
  125. package/dist/OBJLoader.js.map +1 -0
  126. package/dist/SceneAnalysisFixtures.d.ts +100 -0
  127. package/dist/SceneAnalysisFixtures.d.ts.map +1 -0
  128. package/dist/SceneAnalysisFixtures.js +331 -0
  129. package/dist/SceneAnalysisFixtures.js.map +1 -0
  130. package/dist/SceneLoader.d.ts +27 -0
  131. package/dist/SceneLoader.d.ts.map +1 -0
  132. package/dist/SceneLoader.js +40 -0
  133. package/dist/SceneLoader.js.map +1 -0
  134. package/dist/ShaderLoader.d.ts +12 -0
  135. package/dist/ShaderLoader.d.ts.map +1 -0
  136. package/dist/ShaderLoader.js +18 -0
  137. package/dist/ShaderLoader.js.map +1 -0
  138. package/dist/TextureLoader.d.ts +16 -0
  139. package/dist/TextureLoader.d.ts.map +1 -0
  140. package/dist/TextureLoader.js +17 -0
  141. package/dist/TextureLoader.js.map +1 -0
  142. package/dist/TexturePipeline.d.ts +24 -0
  143. package/dist/TexturePipeline.d.ts.map +1 -0
  144. package/dist/TexturePipeline.js +64 -0
  145. package/dist/TexturePipeline.js.map +1 -0
  146. package/dist/TextureStreaming.d.ts +10 -0
  147. package/dist/TextureStreaming.d.ts.map +1 -0
  148. package/dist/TextureStreaming.js +11 -0
  149. package/dist/TextureStreaming.js.map +1 -0
  150. package/dist/WorkerAssetJobs.d.ts +18 -0
  151. package/dist/WorkerAssetJobs.d.ts.map +1 -0
  152. package/dist/WorkerAssetJobs.js +37 -0
  153. package/dist/WorkerAssetJobs.js.map +1 -0
  154. package/dist/advanced-gallery/index.d.ts +3 -0
  155. package/dist/advanced-gallery/index.d.ts.map +1 -0
  156. package/dist/advanced-gallery/index.js +2 -0
  157. package/dist/advanced-gallery/index.js.map +1 -0
  158. package/dist/asset-corpus/GLTFSceneLoader.d.ts +3 -0
  159. package/dist/asset-corpus/GLTFSceneLoader.d.ts.map +1 -0
  160. package/dist/asset-corpus/GLTFSceneLoader.js +2 -0
  161. package/dist/asset-corpus/GLTFSceneLoader.js.map +1 -0
  162. package/dist/asset-corpus/ProductionAssetCorpus.d.ts +89 -0
  163. package/dist/asset-corpus/ProductionAssetCorpus.d.ts.map +1 -0
  164. package/dist/asset-corpus/ProductionAssetCorpus.js +116 -0
  165. package/dist/asset-corpus/ProductionAssetCorpus.js.map +1 -0
  166. package/dist/asset-corpus/ProductionAssetPipeline.d.ts +3 -0
  167. package/dist/asset-corpus/ProductionAssetPipeline.d.ts.map +1 -0
  168. package/dist/asset-corpus/ProductionAssetPipeline.js +3 -0
  169. package/dist/asset-corpus/ProductionAssetPipeline.js.map +1 -0
  170. package/dist/asset-corpus/ProductionGLTFRenderPipeline.d.ts +65 -0
  171. package/dist/asset-corpus/ProductionGLTFRenderPipeline.d.ts.map +1 -0
  172. package/dist/asset-corpus/ProductionGLTFRenderPipeline.js +110 -0
  173. package/dist/asset-corpus/ProductionGLTFRenderPipeline.js.map +1 -0
  174. package/dist/asset-corpus/ProductionHDRTextureLoader.d.ts +8 -0
  175. package/dist/asset-corpus/ProductionHDRTextureLoader.d.ts.map +1 -0
  176. package/dist/asset-corpus/ProductionHDRTextureLoader.js +2 -0
  177. package/dist/asset-corpus/ProductionHDRTextureLoader.js.map +1 -0
  178. package/dist/asset-corpus/ProductionKTX2TextureLoader.d.ts +7 -0
  179. package/dist/asset-corpus/ProductionKTX2TextureLoader.d.ts.map +1 -0
  180. package/dist/asset-corpus/ProductionKTX2TextureLoader.js +2 -0
  181. package/dist/asset-corpus/ProductionKTX2TextureLoader.js.map +1 -0
  182. package/dist/asset-corpus/ProductionTextureLoader.d.ts +7 -0
  183. package/dist/asset-corpus/ProductionTextureLoader.d.ts.map +1 -0
  184. package/dist/asset-corpus/ProductionTextureLoader.js +2 -0
  185. package/dist/asset-corpus/ProductionTextureLoader.js.map +1 -0
  186. package/dist/asset-corpus/index.d.ts +10 -0
  187. package/dist/asset-corpus/index.d.ts.map +1 -0
  188. package/dist/asset-corpus/index.js +8 -0
  189. package/dist/asset-corpus/index.js.map +1 -0
  190. package/dist/browser-index.d.ts +48 -0
  191. package/dist/browser-index.d.ts.map +1 -0
  192. package/dist/browser-index.js +26 -0
  193. package/dist/browser-index.js.map +1 -0
  194. package/dist/createRenderableScene.d.ts +23 -0
  195. package/dist/createRenderableScene.d.ts.map +1 -0
  196. package/dist/createRenderableScene.js +94 -0
  197. package/dist/createRenderableScene.js.map +1 -0
  198. package/dist/index.d.ts +82 -0
  199. package/dist/index.d.ts.map +1 -0
  200. package/dist/index.js +45 -0
  201. package/dist/index.js.map +1 -0
  202. package/dist/loadRenderableAsset.d.ts +16 -0
  203. package/dist/loadRenderableAsset.d.ts.map +1 -0
  204. package/dist/loadRenderableAsset.js +50 -0
  205. package/dist/loadRenderableAsset.js.map +1 -0
  206. package/dist/loaders/CubeTextureLoader.d.ts +4 -0
  207. package/dist/loaders/CubeTextureLoader.d.ts.map +1 -0
  208. package/dist/loaders/CubeTextureLoader.js +9 -0
  209. package/dist/loaders/CubeTextureLoader.js.map +1 -0
  210. package/dist/loaders/EXRLoader.d.ts +4 -0
  211. package/dist/loaders/EXRLoader.d.ts.map +1 -0
  212. package/dist/loaders/EXRLoader.js +10 -0
  213. package/dist/loaders/EXRLoader.js.map +1 -0
  214. package/dist/loaders/HDRLoader.d.ts +4 -0
  215. package/dist/loaders/HDRLoader.d.ts.map +1 -0
  216. package/dist/loaders/HDRLoader.js +7 -0
  217. package/dist/loaders/HDRLoader.js.map +1 -0
  218. package/dist/loaders/KTX2Loader.d.ts +4 -0
  219. package/dist/loaders/KTX2Loader.d.ts.map +1 -0
  220. package/dist/loaders/KTX2Loader.js +7 -0
  221. package/dist/loaders/KTX2Loader.js.map +1 -0
  222. package/dist/loaders/LoaderDiagnostics.d.ts +18 -0
  223. package/dist/loaders/LoaderDiagnostics.d.ts.map +1 -0
  224. package/dist/loaders/LoaderDiagnostics.js +18 -0
  225. package/dist/loaders/LoaderDiagnostics.js.map +1 -0
  226. package/dist/loaders/MTLLoader.d.ts +10 -0
  227. package/dist/loaders/MTLLoader.d.ts.map +1 -0
  228. package/dist/loaders/MTLLoader.js +14 -0
  229. package/dist/loaders/MTLLoader.js.map +1 -0
  230. package/dist/loaders/OBJLoader.d.ts +12 -0
  231. package/dist/loaders/OBJLoader.d.ts.map +1 -0
  232. package/dist/loaders/OBJLoader.js +16 -0
  233. package/dist/loaders/OBJLoader.js.map +1 -0
  234. package/dist/loaders/TextureLoader.d.ts +6 -0
  235. package/dist/loaders/TextureLoader.d.ts.map +1 -0
  236. package/dist/loaders/TextureLoader.js +11 -0
  237. package/dist/loaders/TextureLoader.js.map +1 -0
  238. package/dist/loaders/ThreeCompatGLTFLoader.d.ts +10 -0
  239. package/dist/loaders/ThreeCompatGLTFLoader.d.ts.map +1 -0
  240. package/dist/loaders/ThreeCompatGLTFLoader.js +13 -0
  241. package/dist/loaders/ThreeCompatGLTFLoader.js.map +1 -0
  242. package/dist/loaders/index.d.ts +15 -0
  243. package/dist/loaders/index.d.ts.map +1 -0
  244. package/dist/loaders/index.js +10 -0
  245. package/dist/loaders/index.js.map +1 -0
  246. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.d.ts +34 -0
  247. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.d.ts.map +1 -0
  248. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.js +16 -0
  249. package/dist/threejs-compatibility/ThreeCompatAssetProvenance.js.map +1 -0
  250. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.d.ts +29 -0
  251. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.d.ts.map +1 -0
  252. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.js +33 -0
  253. package/dist/threejs-compatibility/ThreeCompatAssetRegistry.js.map +1 -0
  254. package/dist/threejs-example-parity/index.d.ts +20 -0
  255. package/dist/threejs-example-parity/index.d.ts.map +1 -0
  256. package/dist/threejs-example-parity/index.js +218 -0
  257. package/dist/threejs-example-parity/index.js.map +1 -0
  258. package/package.json +23 -0
  259. package/src/AdvancedAssetCorpus.ts +454 -0
  260. package/src/AssetBundleCacheFixtures.ts +290 -0
  261. package/src/AssetCache.ts +76 -0
  262. package/src/AssetCompatibility.ts +224 -0
  263. package/src/AssetCorpus.ts +329 -0
  264. package/src/AssetDependencyGraph.ts +83 -0
  265. package/src/AssetHandle.ts +74 -0
  266. package/src/AssetImportPreflight.ts +179 -0
  267. package/src/AssetInspection.ts +706 -0
  268. package/src/AssetLoader.ts +36 -0
  269. package/src/AssetManager.ts +211 -0
  270. package/src/AssetRegistry.ts +44 -0
  271. package/src/AssetRenderDefaults.ts +36 -0
  272. package/src/AudioLoader.ts +41 -0
  273. package/src/BlenderExportValidation.ts +227 -0
  274. package/src/CarConceptMaterialStability.ts +1405 -0
  275. package/src/EXRLoader.ts +1 -0
  276. package/src/ExternalParityGLTFCorpus.ts +65 -0
  277. package/src/GLTFAnimationRuntime.ts +1221 -0
  278. package/src/GLTFCompressionDecoders.ts +190 -0
  279. package/src/GLTFExtensionSupport.ts +138 -0
  280. package/src/GLTFLoader.ts +4001 -0
  281. package/src/GLTFRenderResources.ts +2105 -0
  282. package/src/HDRLoader.ts +1 -0
  283. package/src/ImageLoader.ts +52 -0
  284. package/src/ImportPipeline.ts +148 -0
  285. package/src/KTX2BasisTextureTranscoder.ts +224 -0
  286. package/src/LoadContext.ts +60 -0
  287. package/src/MaterialLoader.ts +166 -0
  288. package/src/MeshOptimization.ts +93 -0
  289. package/src/OBJLoader.ts +551 -0
  290. package/src/SceneAnalysisFixtures.ts +438 -0
  291. package/src/SceneLoader.ts +62 -0
  292. package/src/ShaderLoader.ts +30 -0
  293. package/src/TextureLoader.ts +30 -0
  294. package/src/TexturePipeline.ts +96 -0
  295. package/src/TextureStreaming.ts +20 -0
  296. package/src/WorkerAssetJobs.ts +56 -0
  297. package/src/advanced-gallery/index.ts +18 -0
  298. package/src/asset-corpus/GLTFSceneLoader.ts +9 -0
  299. package/src/asset-corpus/ProductionAssetCorpus.ts +230 -0
  300. package/src/asset-corpus/ProductionAssetPipeline.ts +5 -0
  301. package/src/asset-corpus/ProductionGLTFRenderPipeline.ts +182 -0
  302. package/src/asset-corpus/ProductionHDRTextureLoader.ts +2 -0
  303. package/src/asset-corpus/ProductionKTX2TextureLoader.ts +2 -0
  304. package/src/asset-corpus/ProductionTextureLoader.ts +2 -0
  305. package/src/asset-corpus/index.ts +29 -0
  306. package/src/browser-index.ts +224 -0
  307. package/src/createRenderableScene.ts +128 -0
  308. package/src/index.ts +317 -0
  309. package/src/loadRenderableAsset.ts +67 -0
  310. package/src/loaders/CubeTextureLoader.ts +8 -0
  311. package/src/loaders/EXRLoader.ts +10 -0
  312. package/src/loaders/HDRLoader.ts +7 -0
  313. package/src/loaders/KTX2Loader.ts +7 -0
  314. package/src/loaders/LoaderDiagnostics.ts +36 -0
  315. package/src/loaders/MTLLoader.ts +20 -0
  316. package/src/loaders/OBJLoader.ts +24 -0
  317. package/src/loaders/TextureLoader.ts +14 -0
  318. package/src/loaders/ThreeCompatGLTFLoader.ts +19 -0
  319. package/src/loaders/index.ts +14 -0
  320. package/src/threejs-compatibility/ThreeCompatAssetProvenance.ts +51 -0
  321. package/src/threejs-compatibility/ThreeCompatAssetRegistry.ts +61 -0
  322. package/src/threejs-example-parity/index.ts +262 -0
  323. package/tests/assets.test.ts +311 -0
  324. package/tsconfig.json +7 -0
@@ -0,0 +1,954 @@
1
+ import { AnimationAction, AnimationClip, AnimationMixer, normalizeQuat, slerpQuat, solveTwoBoneIk } from "@aura3d/animation";
2
+ import { invertMat4, multiplyMat4, Renderable, Scene, transformPoint } from "@aura3d/scene";
3
+ export class GLTFSceneMorphTargetController {
4
+ runtime;
5
+ options;
6
+ labels;
7
+ labelToIndex = new Map();
8
+ clampWeights;
9
+ weights;
10
+ lastApply;
11
+ constructor(runtime, options) {
12
+ this.runtime = runtime;
13
+ this.options = options;
14
+ if (options.target.trim().length === 0) {
15
+ throw new Error("glTF morph target controller target cannot be empty.");
16
+ }
17
+ this.labels = [...(options.labels ?? [])];
18
+ this.labels.forEach((label, index) => {
19
+ if (label.trim().length === 0) {
20
+ throw new Error("glTF morph target controller labels cannot be empty.");
21
+ }
22
+ this.labelToIndex.set(label, index);
23
+ });
24
+ this.clampWeights = options.clamp ?? true;
25
+ this.weights = [...(options.initialWeights ?? new Array(Math.max(1, this.labels.length)).fill(0))].map((weight) => this.normalizeWeight(weight));
26
+ }
27
+ setWeight(indexOrLabel, weight) {
28
+ const index = this.resolveIndex(indexOrLabel);
29
+ this.ensureWeightIndex(index);
30
+ this.weights[index] = this.normalizeWeight(weight);
31
+ return this;
32
+ }
33
+ setWeights(weights) {
34
+ if (weights.length === 0) {
35
+ throw new Error("glTF morph target controller requires at least one morph weight.");
36
+ }
37
+ this.weights = weights.map((weight) => this.normalizeWeight(weight));
38
+ return this;
39
+ }
40
+ getWeights() {
41
+ return [...this.weights];
42
+ }
43
+ apply(time, label = `morph:${this.options.target}`) {
44
+ this.lastApply = this.runtime.applyAnimationValues(label, time, new Map([[this.options.target, [...this.weights]]]));
45
+ return this.lastApply;
46
+ }
47
+ snapshot() {
48
+ return {
49
+ target: this.options.target,
50
+ labels: [...this.labels],
51
+ weights: [...this.weights],
52
+ ...(this.lastApply === undefined ? {} : { lastApply: this.lastApply })
53
+ };
54
+ }
55
+ resolveIndex(indexOrLabel) {
56
+ if (typeof indexOrLabel === "number") {
57
+ if (!Number.isInteger(indexOrLabel) || indexOrLabel < 0) {
58
+ throw new Error("glTF morph target controller index must be a non-negative integer.");
59
+ }
60
+ return indexOrLabel;
61
+ }
62
+ const index = this.labelToIndex.get(indexOrLabel);
63
+ if (index === undefined) {
64
+ throw new Error(`glTF morph target label "${indexOrLabel}" was not found.`);
65
+ }
66
+ return index;
67
+ }
68
+ ensureWeightIndex(index) {
69
+ while (this.weights.length <= index) {
70
+ this.weights.push(0);
71
+ }
72
+ }
73
+ normalizeWeight(weight) {
74
+ if (!Number.isFinite(weight)) {
75
+ throw new Error("glTF morph target controller weights must be finite.");
76
+ }
77
+ if (!this.clampWeights)
78
+ return weight;
79
+ return Math.min(1, Math.max(0, weight));
80
+ }
81
+ }
82
+ export class GLTFSceneAnimationCloneSampler {
83
+ runtime;
84
+ lastResults = [];
85
+ constructor(runtime) {
86
+ this.runtime = runtime;
87
+ }
88
+ sampleClones(samples, onSample) {
89
+ const results = [];
90
+ for (const sample of samples) {
91
+ const applyResult = sample.weight === undefined && sample.additive !== true
92
+ ? this.runtime.applyClipByName(sample.clipName, sample.time)
93
+ : this.runtime.applyClips([{
94
+ clipName: sample.clipName,
95
+ time: sample.time,
96
+ ...(sample.weight === undefined ? {} : { weight: sample.weight }),
97
+ ...(sample.additive === undefined ? {} : { additive: sample.additive })
98
+ }]);
99
+ const result = {
100
+ cloneId: sample.cloneId,
101
+ clipName: sample.clipName,
102
+ time: applyResult.time,
103
+ applyResult
104
+ };
105
+ results.push(result);
106
+ onSample?.(result);
107
+ }
108
+ this.lastResults = results;
109
+ return results;
110
+ }
111
+ snapshot() {
112
+ return {
113
+ cloneCount: new Set(this.lastResults.map((result) => result.cloneId)).size,
114
+ lastSampleCount: this.lastResults.length,
115
+ lastSkinningPalettesUpdated: this.lastResults.reduce((sum, result) => sum + result.applyResult.skinningPalettesUpdated, 0),
116
+ lastResults: this.lastResults.map((result) => ({ ...result }))
117
+ };
118
+ }
119
+ }
120
+ export class GLTFImportedSkeletonIKController {
121
+ runtime;
122
+ options;
123
+ target;
124
+ pole;
125
+ weight;
126
+ allowStretch;
127
+ apply;
128
+ lastResult;
129
+ constructor(runtime, options, initial) {
130
+ this.runtime = runtime;
131
+ this.options = options;
132
+ this.target = initial.target;
133
+ this.pole = initial.pole;
134
+ this.weight = initial.weight;
135
+ this.allowStretch = initial.allowStretch;
136
+ this.apply = initial.apply ?? true;
137
+ }
138
+ setTarget(target) {
139
+ this.target = target;
140
+ return this;
141
+ }
142
+ setPole(pole) {
143
+ this.pole = pole;
144
+ return this;
145
+ }
146
+ setWeight(weight) {
147
+ if (weight !== undefined && (!Number.isFinite(weight) || weight < 0 || weight > 1)) {
148
+ throw new Error("glTF imported skeleton IK controller weight must be between 0 and 1.");
149
+ }
150
+ this.weight = weight;
151
+ return this;
152
+ }
153
+ setAllowStretch(allowStretch) {
154
+ this.allowStretch = allowStretch;
155
+ return this;
156
+ }
157
+ setApply(apply) {
158
+ this.apply = apply;
159
+ return this;
160
+ }
161
+ solve(patch = {}) {
162
+ if (patch.target !== undefined)
163
+ this.setTarget(patch.target);
164
+ if ("pole" in patch)
165
+ this.setPole(patch.pole);
166
+ if ("weight" in patch)
167
+ this.setWeight(patch.weight);
168
+ if ("allowStretch" in patch)
169
+ this.setAllowStretch(patch.allowStretch);
170
+ if (patch.apply !== undefined)
171
+ this.setApply(patch.apply);
172
+ this.lastResult = this.runtime.solveImportedSkeletonTwoBoneIK({
173
+ ...this.options,
174
+ target: this.target,
175
+ ...(this.pole === undefined ? {} : { pole: this.pole }),
176
+ ...(this.weight === undefined ? {} : { weight: this.weight }),
177
+ ...(this.allowStretch === undefined ? {} : { allowStretch: this.allowStretch }),
178
+ apply: this.apply
179
+ });
180
+ return this.lastResult;
181
+ }
182
+ snapshot() {
183
+ return {
184
+ target: this.target,
185
+ ...(this.pole === undefined ? {} : { pole: this.pole }),
186
+ ...(this.weight === undefined ? {} : { weight: this.weight }),
187
+ ...(this.allowStretch === undefined ? {} : { allowStretch: this.allowStretch }),
188
+ apply: this.apply,
189
+ ...(this.options.skinName === undefined ? {} : { skinName: this.options.skinName }),
190
+ ...(this.options.jointNames === undefined ? {} : { jointNames: this.options.jointNames }),
191
+ ...(this.lastResult === undefined ? {} : { lastResult: this.lastResult })
192
+ };
193
+ }
194
+ }
195
+ export class GLTFSceneAnimationRuntime {
196
+ options;
197
+ clipsByName = new Map();
198
+ nodesByName = new Map();
199
+ morphRenderablesByNodeName = new Map();
200
+ skinningBindings = [];
201
+ lastApply;
202
+ constructor(options) {
203
+ this.options = options;
204
+ for (const clip of options.clips) {
205
+ this.clipsByName.set(clip.name, clip);
206
+ }
207
+ this.reindexScene();
208
+ }
209
+ applyClipByName(name, time) {
210
+ const clip = this.clipsByName.get(name);
211
+ if (!clip) {
212
+ throw new Error(`glTF animation clip "${name}" was not found.`);
213
+ }
214
+ return this.applyClip(clip, time);
215
+ }
216
+ applyClip(clip, time) {
217
+ if (!Number.isFinite(time) || time < 0) {
218
+ throw new Error("glTF animation runtime time must be finite and non-negative.");
219
+ }
220
+ const wrappedTime = clip.duration > 0 && time > clip.duration ? time % clip.duration : Math.min(time, clip.duration);
221
+ this.lastApply = this.applySampledTargets(clip.name, wrappedTime, sampleClipTracks(clip, wrappedTime, 1, false));
222
+ return this.lastApply;
223
+ }
224
+ applyClips(samples) {
225
+ if (samples.length === 0) {
226
+ throw new Error("glTF animation runtime blend requires at least one clip sample.");
227
+ }
228
+ const accumulators = new Map();
229
+ const unsupportedTracks = [];
230
+ let maxTime = 0;
231
+ const names = [];
232
+ for (const sample of samples) {
233
+ const clip = this.clipsByName.get(sample.clipName);
234
+ if (!clip) {
235
+ throw new Error(`glTF animation clip "${sample.clipName}" was not found.`);
236
+ }
237
+ if (!Number.isFinite(sample.time) || sample.time < 0) {
238
+ throw new Error("glTF animation runtime blend time must be finite and non-negative.");
239
+ }
240
+ const weight = sample.weight ?? 1;
241
+ if (!Number.isFinite(weight) || weight < 0) {
242
+ throw new Error("glTF animation runtime blend weight must be finite and non-negative.");
243
+ }
244
+ if (weight === 0)
245
+ continue;
246
+ const wrappedTime = clip.duration > 0 && sample.time > clip.duration ? sample.time % clip.duration : Math.min(sample.time, clip.duration);
247
+ maxTime = Math.max(maxTime, wrappedTime);
248
+ names.push(`${clip.name}@${Number(wrappedTime.toFixed(4))}x${Number(weight.toFixed(4))}${sample.additive ? "+add" : ""}`);
249
+ for (const track of clip.tracks) {
250
+ const target = parseAnimationTarget(track.target);
251
+ if (!target) {
252
+ unsupportedTracks.push(track.target);
253
+ continue;
254
+ }
255
+ blendInto(accumulators, track.target, track.valueType, track.sample(wrappedTime), weight, sample.additive === true);
256
+ }
257
+ }
258
+ const sampledTargets = new Map();
259
+ for (const [target, accumulator] of accumulators) {
260
+ sampledTargets.set(target, finalizeTargetBlend(accumulator));
261
+ }
262
+ this.lastApply = this.applySampledTargets(`blend:${names.join(",")}`, maxTime, { sampledTargets, unsupportedTracks }, samples.length);
263
+ return this.lastApply;
264
+ }
265
+ applyAnimationValues(label, time, values, unsupportedTracks = []) {
266
+ if (label.trim().length === 0) {
267
+ throw new Error("glTF animation runtime value application label cannot be empty.");
268
+ }
269
+ if (!Number.isFinite(time) || time < 0) {
270
+ throw new Error("glTF animation runtime value application time must be finite and non-negative.");
271
+ }
272
+ this.lastApply = this.applySampledTargets(label, time, {
273
+ sampledTargets: values,
274
+ unsupportedTracks
275
+ });
276
+ return this.lastApply;
277
+ }
278
+ solveImportedSkeletonTwoBoneIK(options) {
279
+ if (!this.options.asset || this.options.asset.skins.length === 0) {
280
+ throw new Error("glTF imported skeleton IK requires an asset with at least one skin.");
281
+ }
282
+ const skin = resolveIKSkin(this.options.asset.skins, options.skinName);
283
+ const jointNames = options.jointNames ?? firstTwoBoneJointChain(skin);
284
+ const [rootName, midName, endName] = jointNames;
285
+ this.options.scene.updateWorldTransforms();
286
+ const rootNode = this.nodesByName.get(rootName)?.[0];
287
+ const midNode = this.nodesByName.get(midName)?.[0];
288
+ const endNode = this.nodesByName.get(endName)?.[0];
289
+ const missingTargets = [
290
+ ...(!rootNode ? [`${skin.name}.${rootName}`] : []),
291
+ ...(!midNode ? [`${skin.name}.${midName}`] : []),
292
+ ...(!endNode ? [`${skin.name}.${endName}`] : [])
293
+ ];
294
+ if (!rootNode || !midNode || !endNode) {
295
+ return {
296
+ skinName: skin.name,
297
+ jointNames,
298
+ solution: solveTwoBoneIk({
299
+ root: [0, 0, 0],
300
+ mid: [0, 1, 0],
301
+ end: [0, 2, 0],
302
+ target: [0, 2, 0.01],
303
+ allowStretch: true
304
+ }),
305
+ applied: false,
306
+ skinningPalettesUpdated: 0,
307
+ missingTargets
308
+ };
309
+ }
310
+ const solution = solveTwoBoneIk({
311
+ root: worldPosition(rootNode),
312
+ mid: worldPosition(midNode),
313
+ end: worldPosition(endNode),
314
+ target: options.target,
315
+ ...(options.pole ? { pole: options.pole } : {}),
316
+ ...(options.weight !== undefined ? { weight: options.weight } : {}),
317
+ ...(options.allowStretch !== undefined ? { allowStretch: options.allowStretch } : {})
318
+ });
319
+ if (options.apply === false) {
320
+ return {
321
+ skinName: skin.name,
322
+ jointNames,
323
+ solution,
324
+ applied: false,
325
+ skinningPalettesUpdated: 0,
326
+ missingTargets: []
327
+ };
328
+ }
329
+ setWorldPosition(midNode, solution.mid);
330
+ this.options.scene.updateWorldTransforms();
331
+ setWorldPosition(endNode, solution.end);
332
+ this.options.scene.updateWorldTransforms();
333
+ const skinning = this.refreshSkinningPalettes();
334
+ return {
335
+ skinName: skin.name,
336
+ jointNames,
337
+ solution,
338
+ applied: true,
339
+ skinningPalettesUpdated: skinning.updated,
340
+ missingTargets: skinning.missingTargets
341
+ };
342
+ }
343
+ createTwoBoneIKController(options) {
344
+ return new GLTFImportedSkeletonIKController(this, {
345
+ ...(options.skinName === undefined ? {} : { skinName: options.skinName }),
346
+ ...(options.jointNames === undefined ? {} : { jointNames: options.jointNames })
347
+ }, {
348
+ target: options.target,
349
+ ...(options.pole === undefined ? {} : { pole: options.pole }),
350
+ ...(options.weight === undefined ? {} : { weight: options.weight }),
351
+ ...(options.allowStretch === undefined ? {} : { allowStretch: options.allowStretch }),
352
+ ...(options.apply === undefined ? {} : { apply: options.apply })
353
+ });
354
+ }
355
+ createCloneSampler() {
356
+ return new GLTFSceneAnimationCloneSampler(this);
357
+ }
358
+ createMorphTargetController(options) {
359
+ return new GLTFSceneMorphTargetController(this, options);
360
+ }
361
+ snapshot() {
362
+ return {
363
+ clipCount: this.clipsByName.size,
364
+ nodeTargetCount: this.nodesByName.size,
365
+ morphTargetNodeCount: this.morphRenderablesByNodeName.size,
366
+ skinningBindingCount: this.skinningBindings.length,
367
+ clips: [...this.clipsByName.keys()],
368
+ ...(this.lastApply ? { lastApply: this.lastApply } : {})
369
+ };
370
+ }
371
+ inspectClipBindings(name) {
372
+ if (name !== undefined) {
373
+ const clip = this.clipsByName.get(name);
374
+ if (!clip) {
375
+ throw new Error(`glTF animation clip "${name}" was not found.`);
376
+ }
377
+ return [this.inspectClipBinding(clip)];
378
+ }
379
+ return [...this.clipsByName.values()].map((clip) => this.inspectClipBinding(clip));
380
+ }
381
+ reindexScene() {
382
+ this.nodesByName.clear();
383
+ this.morphRenderablesByNodeName.clear();
384
+ this.skinningBindings.length = 0;
385
+ this.options.scene.traverse((node) => {
386
+ const nodes = this.nodesByName.get(node.name) ?? [];
387
+ nodes.push(node);
388
+ this.nodesByName.set(node.name, nodes);
389
+ });
390
+ for (const { node, renderable } of this.options.scene.collectRenderables()) {
391
+ if (renderable.morphWeights.length === 0)
392
+ continue;
393
+ for (const nodeName of new Set([node.name, node.parent?.name].filter((name) => typeof name === "string" && name.length > 0))) {
394
+ const renderables = this.morphRenderablesByNodeName.get(nodeName) ?? [];
395
+ renderables.push(renderable);
396
+ this.morphRenderablesByNodeName.set(nodeName, renderables);
397
+ }
398
+ }
399
+ if (this.options.asset) {
400
+ const meshesByName = new Map(this.options.asset.meshes.map((mesh) => [mesh.name, mesh]));
401
+ for (const { node, renderable } of this.options.scene.collectRenderables()) {
402
+ if (!renderable.skinning)
403
+ continue;
404
+ const mesh = meshesByName.get(renderable.geometry);
405
+ const skin = mesh?.skinIndex === undefined ? undefined : this.options.asset.skins[mesh.skinIndex];
406
+ if (!mesh || !skin || skin.joints.length > 96)
407
+ continue;
408
+ this.skinningBindings.push({ node, renderable, mesh, skin });
409
+ }
410
+ }
411
+ }
412
+ refreshSkinningPalettes() {
413
+ if (this.skinningBindings.length === 0) {
414
+ return { updated: 0, missingTargets: [] };
415
+ }
416
+ let updated = 0;
417
+ const missingTargets = [];
418
+ for (const binding of this.skinningBindings) {
419
+ const matrices = new Float32Array(binding.skin.joints.length * 16);
420
+ const inverseMeshWorld = invertMat4(binding.node.transform.worldMatrix);
421
+ let complete = true;
422
+ for (let index = 0; index < binding.skin.jointNames.length; index += 1) {
423
+ const jointName = binding.skin.jointNames[index];
424
+ const jointNode = this.nodesByName.get(jointName)?.[0];
425
+ const inverseBind = binding.skin.inverseBindMatrices[index];
426
+ if (!jointNode || !inverseBind) {
427
+ missingTargets.push(`${binding.skin.name}.${jointName}`);
428
+ complete = false;
429
+ break;
430
+ }
431
+ const jointMatrix = multiplyMat4(multiplyMat4(inverseMeshWorld, jointNode.transform.worldMatrix), inverseBind);
432
+ matrices.set(jointMatrix, index * 16);
433
+ }
434
+ if (!complete)
435
+ continue;
436
+ binding.renderable.skinning = {
437
+ jointCount: binding.skin.joints.length,
438
+ matrices
439
+ };
440
+ updated += 1;
441
+ }
442
+ return { updated, missingTargets };
443
+ }
444
+ inspectClipBinding(clip) {
445
+ let supportedTrackCount = 0;
446
+ let boundTrackCount = 0;
447
+ let transformTrackCount = 0;
448
+ let morphWeightTrackCount = 0;
449
+ const boundNodeNames = new Set();
450
+ const missingTargets = new Set();
451
+ const unsupportedTracks = new Set();
452
+ for (const track of clip.tracks) {
453
+ const target = parseAnimationTarget(track.target);
454
+ if (!target) {
455
+ unsupportedTracks.add(track.target);
456
+ continue;
457
+ }
458
+ supportedTrackCount += 1;
459
+ if (target.path === "weights") {
460
+ morphWeightTrackCount += 1;
461
+ const renderables = this.morphRenderablesByNodeName.get(target.nodeName) ?? [];
462
+ if (renderables.length === 0) {
463
+ missingTargets.add(track.target);
464
+ continue;
465
+ }
466
+ boundTrackCount += 1;
467
+ boundNodeNames.add(target.nodeName);
468
+ continue;
469
+ }
470
+ transformTrackCount += 1;
471
+ const nodes = this.nodesByName.get(target.nodeName) ?? [];
472
+ if (nodes.length === 0) {
473
+ missingTargets.add(track.target);
474
+ continue;
475
+ }
476
+ boundTrackCount += 1;
477
+ boundNodeNames.add(target.nodeName);
478
+ }
479
+ return {
480
+ clipName: clip.name,
481
+ trackCount: clip.tracks.length,
482
+ supportedTrackCount,
483
+ boundTrackCount,
484
+ transformTrackCount,
485
+ morphWeightTrackCount,
486
+ missingTargetCount: missingTargets.size,
487
+ unsupportedTrackCount: unsupportedTracks.size,
488
+ skinningBindingCount: this.skinningBindings.length,
489
+ boundNodeNames: [...boundNodeNames].sort(),
490
+ missingTargets: [...missingTargets].sort(),
491
+ unsupportedTracks: [...unsupportedTracks].sort(),
492
+ animatesSkeleton: this.skinningBindings.length > 0 && boundTrackCount > 0 && transformTrackCount > 0
493
+ };
494
+ }
495
+ applySampledTargets(clipName, time, sampled, blendedClipCount) {
496
+ let transformTracksApplied = 0;
497
+ let morphWeightTracksApplied = 0;
498
+ const missingTargets = [];
499
+ for (const [trackTarget, value] of sampled.sampledTargets) {
500
+ const target = parseAnimationTarget(trackTarget);
501
+ if (!target) {
502
+ continue;
503
+ }
504
+ if (target.path === "weights") {
505
+ const renderables = this.morphRenderablesByNodeName.get(target.nodeName) ?? [];
506
+ if (renderables.length === 0) {
507
+ missingTargets.push(trackTarget);
508
+ continue;
509
+ }
510
+ const weights = asNumberArray(value);
511
+ for (const renderable of renderables) {
512
+ renderable.morphWeights = weights;
513
+ }
514
+ morphWeightTracksApplied += 1;
515
+ continue;
516
+ }
517
+ const nodes = this.nodesByName.get(target.nodeName) ?? [];
518
+ if (nodes.length === 0) {
519
+ missingTargets.push(trackTarget);
520
+ continue;
521
+ }
522
+ for (const node of nodes) {
523
+ applyTransformValue(node, target.path, value, trackTarget);
524
+ }
525
+ transformTracksApplied += 1;
526
+ }
527
+ this.options.scene.updateWorldTransforms();
528
+ const skinning = this.refreshSkinningPalettes();
529
+ return {
530
+ clipName,
531
+ time,
532
+ ...(blendedClipCount === undefined ? {} : { blendedClipCount }),
533
+ tracksApplied: transformTracksApplied + morphWeightTracksApplied,
534
+ transformTracksApplied,
535
+ morphWeightTracksApplied,
536
+ skinningPalettesUpdated: skinning.updated,
537
+ missingTargets: [...missingTargets, ...skinning.missingTargets],
538
+ unsupportedTracks: sampled.unsupportedTracks
539
+ };
540
+ }
541
+ }
542
+ export function createGLTFSceneAnimationRuntime(options) {
543
+ return new GLTFSceneAnimationRuntime(options);
544
+ }
545
+ export class GLTFSceneAnimationMixerBinding {
546
+ runtime;
547
+ mixer;
548
+ actions;
549
+ pendingValues = new Map();
550
+ elapsedTime = 0;
551
+ lastApply;
552
+ constructor(options) {
553
+ this.runtime = new GLTFSceneAnimationRuntime(options);
554
+ this.mixer = new AnimationMixer({
555
+ setAnimationValue: (target, value) => {
556
+ this.pendingValues.set(target, cloneAnimationValue(value));
557
+ }
558
+ }, options.mixer ?? {});
559
+ const actions = new Map();
560
+ for (const clip of options.clips) {
561
+ const action = new AnimationAction(clip).setWeight(0);
562
+ this.mixer.addAction(action);
563
+ actions.set(clip.name, action);
564
+ }
565
+ const autoPlay = options.autoPlay === false ? undefined : options.autoPlay ?? options.clips[0]?.name;
566
+ if (autoPlay) {
567
+ const action = actions.get(autoPlay);
568
+ if (!action) {
569
+ throw new Error(`glTF animation mixer autoPlay clip "${autoPlay}" was not found.`);
570
+ }
571
+ action.setWeight(1).play();
572
+ }
573
+ this.actions = actions;
574
+ }
575
+ listClips() {
576
+ return [...this.actions.keys()];
577
+ }
578
+ play(name, weight = 1) {
579
+ return this.playClip(name, { weight });
580
+ }
581
+ playClip(name, options = {}) {
582
+ const action = this.requireAction(name);
583
+ this.configureAction(action, options);
584
+ action.play();
585
+ return action;
586
+ }
587
+ playExclusive(name, options = {}) {
588
+ const action = this.requireAction(name);
589
+ const fadeDuration = options.fadeDuration ?? 0;
590
+ for (const [clipName, candidate] of this.actions) {
591
+ if (clipName === name)
592
+ continue;
593
+ if (fadeDuration > 0) {
594
+ candidate.fadeTo(0, fadeDuration);
595
+ }
596
+ else {
597
+ candidate.setWeight(0);
598
+ }
599
+ }
600
+ this.configureAction(action, { ...options, weight: options.weight ?? 1 });
601
+ action.play();
602
+ return action;
603
+ }
604
+ pause(name) {
605
+ for (const action of this.resolveActions(name)) {
606
+ action.pause();
607
+ }
608
+ }
609
+ resume(name) {
610
+ for (const action of this.resolveActions(name)) {
611
+ if (action.weight > 0)
612
+ action.play();
613
+ }
614
+ }
615
+ stop(name) {
616
+ for (const action of this.resolveActions(name)) {
617
+ action.stop().setWeight(0);
618
+ }
619
+ }
620
+ seek(name, time) {
621
+ const action = this.requireAction(name);
622
+ action.seek(time);
623
+ this.elapsedTime = action.time;
624
+ return action;
625
+ }
626
+ setTimeScale(timeScale) {
627
+ if (!Number.isFinite(timeScale) || timeScale < 0) {
628
+ throw new Error("glTF animation mixer timeScale must be finite and non-negative.");
629
+ }
630
+ this.mixer.timeScale = timeScale;
631
+ }
632
+ setActionTimeScale(name, timeScale) {
633
+ return this.requireAction(name).setTimeScale(timeScale);
634
+ }
635
+ setActionWeight(name, weight) {
636
+ return this.requireAction(name).setWeight(weight);
637
+ }
638
+ setActionLoop(name, loopMode) {
639
+ return this.requireAction(name).setLoop(loopMode);
640
+ }
641
+ crossFade(fromName, toName, duration) {
642
+ const from = this.requireAction(fromName);
643
+ const to = this.requireAction(toName);
644
+ if (!to.playing) {
645
+ to.setWeight(0).play();
646
+ }
647
+ this.mixer.crossFade(from, to, duration);
648
+ }
649
+ applyClipSamples(samples) {
650
+ this.pendingValues.clear();
651
+ this.lastApply = this.runtime.applyClips(samples);
652
+ this.elapsedTime = Math.max(this.elapsedTime, this.lastApply.time);
653
+ return { events: [], applyResult: this.lastApply, activeActions: this.actionSnapshots().filter((action) => action.active) };
654
+ }
655
+ update(deltaSeconds) {
656
+ if (!Number.isFinite(deltaSeconds) || deltaSeconds < 0) {
657
+ throw new Error("glTF animation mixer delta must be finite and non-negative.");
658
+ }
659
+ this.pendingValues.clear();
660
+ const events = this.mixer.update(deltaSeconds);
661
+ this.elapsedTime += deltaSeconds;
662
+ this.lastApply = this.runtime.applyAnimationValues("gltf-animation-mixer", this.elapsedTime, this.pendingValues);
663
+ return { events, applyResult: this.lastApply, activeActions: this.actionSnapshots().filter((action) => action.active) };
664
+ }
665
+ getAction(name) {
666
+ return this.actions.get(name);
667
+ }
668
+ snapshot() {
669
+ return {
670
+ ...this.runtime.snapshot(),
671
+ mixerActionCount: this.actions.size,
672
+ pendingValueCount: this.pendingValues.size,
673
+ elapsedTime: this.elapsedTime,
674
+ timeScale: this.mixer.timeScale,
675
+ activeClipNames: this.actionSnapshots().filter((action) => action.active).map((action) => action.clipName),
676
+ actions: this.actionSnapshots(),
677
+ ...(this.lastApply ? { lastApply: this.lastApply } : {})
678
+ };
679
+ }
680
+ configureAction(action, options) {
681
+ if (options.reset === true) {
682
+ action.reset();
683
+ }
684
+ if (options.weight !== undefined) {
685
+ if (options.fadeDuration !== undefined && options.fadeDuration > 0) {
686
+ action.fadeTo(options.weight, options.fadeDuration);
687
+ }
688
+ else {
689
+ action.setWeight(options.weight);
690
+ }
691
+ }
692
+ if (options.timeScale !== undefined) {
693
+ action.setTimeScale(options.timeScale);
694
+ }
695
+ if (options.loopMode !== undefined) {
696
+ action.setLoop(options.loopMode);
697
+ }
698
+ }
699
+ resolveActions(name) {
700
+ return name === undefined ? [...this.actions.values()] : [this.requireAction(name)];
701
+ }
702
+ actionSnapshots() {
703
+ return [...this.actions.values()].map((action) => {
704
+ const snapshot = action.snapshot();
705
+ return {
706
+ ...snapshot,
707
+ active: snapshot.playing && !snapshot.paused && snapshot.weight > 0
708
+ };
709
+ });
710
+ }
711
+ requireAction(name) {
712
+ const action = this.actions.get(name);
713
+ if (!action) {
714
+ throw new Error(`glTF animation action "${name}" was not found.`);
715
+ }
716
+ return action;
717
+ }
718
+ }
719
+ export function createGLTFSceneAnimationMixer(options) {
720
+ return new GLTFSceneAnimationMixerBinding(options);
721
+ }
722
+ function parseAnimationTarget(target) {
723
+ const separator = target.lastIndexOf(".");
724
+ if (separator <= 0 || separator === target.length - 1) {
725
+ return undefined;
726
+ }
727
+ const path = target.slice(separator + 1);
728
+ if (path !== "translation" && path !== "rotation" && path !== "scale" && path !== "weights") {
729
+ return undefined;
730
+ }
731
+ return {
732
+ nodeName: target.slice(0, separator),
733
+ path
734
+ };
735
+ }
736
+ function resolveIKSkin(skins, skinName) {
737
+ if (skinName === undefined) {
738
+ const skin = skins.find((candidate) => candidate.jointNames.length >= 3);
739
+ if (!skin) {
740
+ throw new Error("glTF imported skeleton IK requires a skin with at least three joints.");
741
+ }
742
+ return skin;
743
+ }
744
+ const skin = skins.find((candidate) => candidate.name === skinName);
745
+ if (!skin) {
746
+ throw new Error(`glTF imported skeleton IK skin "${skinName}" was not found.`);
747
+ }
748
+ if (skin.jointNames.length < 3) {
749
+ throw new Error(`glTF imported skeleton IK skin "${skinName}" does not contain a two-bone chain.`);
750
+ }
751
+ return skin;
752
+ }
753
+ function firstTwoBoneJointChain(skin) {
754
+ const root = skin.jointNames[0];
755
+ const mid = skin.jointNames[1];
756
+ const end = skin.jointNames[2];
757
+ if (!root || !mid || !end) {
758
+ throw new Error(`glTF imported skeleton IK skin "${skin.name}" does not contain a two-bone chain.`);
759
+ }
760
+ return [root, mid, end];
761
+ }
762
+ function worldPosition(node) {
763
+ node.updateWorldTransform();
764
+ return [node.transform.worldMatrix[12], node.transform.worldMatrix[13], node.transform.worldMatrix[14]];
765
+ }
766
+ function setWorldPosition(node, position) {
767
+ const local = node.parent
768
+ ? transformPoint(invertMat4(node.parent.transform.worldMatrix), [position[0], position[1], position[2]])
769
+ : [position[0], position[1], position[2]];
770
+ node.transform.setPosition(local[0], local[1], local[2]);
771
+ }
772
+ function applyTransformValue(node, path, value, target) {
773
+ if (path === "translation") {
774
+ const vector = asVec3(value, target);
775
+ node.transform.setPosition(vector[0], vector[1], vector[2]);
776
+ return;
777
+ }
778
+ if (path === "rotation") {
779
+ const quat = asQuat(value, target);
780
+ node.transform.setRotation(quat[0], quat[1], quat[2], quat[3]);
781
+ return;
782
+ }
783
+ const vector = asVec3(value, target);
784
+ node.transform.setScale(vector[0], vector[1], vector[2]);
785
+ }
786
+ function asVec3(value, target) {
787
+ if (!Array.isArray(value) || value.length !== 3 || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
788
+ throw new Error(`glTF animation track "${target}" sampled an invalid vec3.`);
789
+ }
790
+ return [value[0], value[1], value[2]];
791
+ }
792
+ function asQuat(value, target) {
793
+ if (!Array.isArray(value) || value.length !== 4 || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
794
+ throw new Error(`glTF animation track "${target}" sampled an invalid quaternion.`);
795
+ }
796
+ return [value[0], value[1], value[2], value[3]];
797
+ }
798
+ function asNumberArray(value) {
799
+ if (!Array.isArray(value) || value.some((component) => typeof component !== "number" || !Number.isFinite(component))) {
800
+ throw new Error("glTF morph-weight animation sampled an invalid number array.");
801
+ }
802
+ return [...value];
803
+ }
804
+ function sampleClipTracks(clip, time, weight, additive) {
805
+ const accumulators = new Map();
806
+ const unsupportedTracks = [];
807
+ for (const track of clip.tracks) {
808
+ if (!parseAnimationTarget(track.target)) {
809
+ unsupportedTracks.push(track.target);
810
+ continue;
811
+ }
812
+ blendInto(accumulators, track.target, track.valueType, track.sample(time), weight, additive);
813
+ }
814
+ const sampledTargets = new Map();
815
+ for (const [target, accumulator] of accumulators) {
816
+ sampledTargets.set(target, finalizeTargetBlend(accumulator));
817
+ }
818
+ return { sampledTargets, unsupportedTracks };
819
+ }
820
+ function blendInto(accumulators, target, type, value, weight, additive) {
821
+ if (weight <= 0)
822
+ return;
823
+ const current = accumulators.get(target);
824
+ if (!current) {
825
+ const accumulator = { type };
826
+ if (additive) {
827
+ accumulator.additive = additiveContribution(type, value, weight);
828
+ }
829
+ else {
830
+ accumulator.base = { value: cloneAnimationValue(value), weight, type };
831
+ }
832
+ accumulators.set(target, accumulator);
833
+ return;
834
+ }
835
+ if (current.type !== type) {
836
+ throw new Error(`Cannot blend ${type} glTF animation track into existing ${current.type} target ${target}.`);
837
+ }
838
+ if (additive) {
839
+ current.additive = current.additive === undefined
840
+ ? additiveContribution(type, value, weight)
841
+ : combineAdditive(type, current.additive, value, weight);
842
+ return;
843
+ }
844
+ if (!current.base) {
845
+ current.base = { value: cloneAnimationValue(value), weight, type };
846
+ return;
847
+ }
848
+ blendBase(current.base, type, value, weight);
849
+ }
850
+ function blendBase(current, type, value, weight) {
851
+ const total = current.weight + weight;
852
+ const t = weight / total;
853
+ if (type === "scalar") {
854
+ current.value = current.value + (value - current.value) * t;
855
+ }
856
+ else if (type === "vector3") {
857
+ const a = current.value;
858
+ const b = value;
859
+ current.value = [a[0] + (b[0] - a[0]) * t, a[1] + (b[1] - a[1]) * t, a[2] + (b[2] - a[2]) * t];
860
+ }
861
+ else if (type === "quaternion") {
862
+ current.value = slerpQuat(current.value, value, t);
863
+ }
864
+ else if (type === "number-array") {
865
+ const a = current.value;
866
+ const b = value;
867
+ if (a.length !== b.length) {
868
+ throw new Error("Cannot blend glTF morph animation values with different lengths.");
869
+ }
870
+ current.value = a.map((component, index) => component + (b[index] - component) * t);
871
+ }
872
+ else {
873
+ current.value = cloneAnimationValue(value);
874
+ }
875
+ current.weight = total;
876
+ }
877
+ function finalizeTargetBlend(accumulator) {
878
+ const base = accumulator.base
879
+ ? finalizeBaseBlend(accumulator.base)
880
+ : accumulator.additive !== undefined
881
+ ? additiveNeutral(accumulator.type, accumulator.additive)
882
+ : undefined;
883
+ if (base === undefined) {
884
+ throw new Error("glTF animation target accumulator has no sampled value.");
885
+ }
886
+ return accumulator.additive === undefined ? base : applyAdditive(accumulator.type, base, accumulator.additive);
887
+ }
888
+ function finalizeBaseBlend(accumulator) {
889
+ return accumulator.type === "quaternion"
890
+ ? normalizeQuat(accumulator.value)
891
+ : cloneAnimationValue(accumulator.value);
892
+ }
893
+ function additiveContribution(type, value, weight) {
894
+ if (type === "scalar")
895
+ return value * weight;
896
+ if (type === "vector3") {
897
+ const vector = value;
898
+ return [vector[0] * weight, vector[1] * weight, vector[2] * weight];
899
+ }
900
+ if (type === "number-array") {
901
+ return value.map((component) => component * weight);
902
+ }
903
+ if (type === "quaternion") {
904
+ return slerpQuat([0, 0, 0, 1], normalizeQuat(value), weight);
905
+ }
906
+ throw new Error("Additive glTF animation layers require scalar, vector3, quaternion, or number-array tracks.");
907
+ }
908
+ function combineAdditive(type, current, value, weight) {
909
+ return applyAdditive(type, current, additiveContribution(type, value, weight));
910
+ }
911
+ function applyAdditive(type, base, delta) {
912
+ if (type === "scalar")
913
+ return base + delta;
914
+ if (type === "vector3") {
915
+ const a = base;
916
+ const b = delta;
917
+ return [a[0] + b[0], a[1] + b[1], a[2] + b[2]];
918
+ }
919
+ if (type === "number-array") {
920
+ const a = base;
921
+ const b = delta;
922
+ if (a.length !== b.length) {
923
+ throw new Error("Cannot add glTF morph animation values with different lengths.");
924
+ }
925
+ return a.map((component, index) => component + b[index]);
926
+ }
927
+ if (type === "quaternion") {
928
+ return normalizeQuat(multiplyQuat(base, delta));
929
+ }
930
+ throw new Error("Additive glTF animation layers require scalar, vector3, quaternion, or number-array tracks.");
931
+ }
932
+ function additiveNeutral(type, value) {
933
+ if (type === "scalar")
934
+ return 0;
935
+ if (type === "vector3")
936
+ return [0, 0, 0];
937
+ if (type === "number-array")
938
+ return value.map(() => 0);
939
+ if (type === "quaternion")
940
+ return [0, 0, 0, 1];
941
+ throw new Error("Additive glTF animation layers require scalar, vector3, quaternion, or number-array tracks.");
942
+ }
943
+ function cloneAnimationValue(value) {
944
+ return Array.isArray(value) ? [...value] : value;
945
+ }
946
+ function multiplyQuat(a, b) {
947
+ return [
948
+ a[3] * b[0] + a[0] * b[3] + a[1] * b[2] - a[2] * b[1],
949
+ a[3] * b[1] - a[0] * b[2] + a[1] * b[3] + a[2] * b[0],
950
+ a[3] * b[2] + a[0] * b[1] - a[1] * b[0] + a[2] * b[3],
951
+ a[3] * b[3] - a[0] * b[0] - a[1] * b[1] - a[2] * b[2]
952
+ ];
953
+ }
954
+ //# sourceMappingURL=GLTFAnimationRuntime.js.map