@zephyr3d/scene 0.8.2 → 0.9.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 (241) hide show
  1. package/dist/animation/animationset.js +473 -60
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/cloth/gpu_cloth_system.js +2516 -0
  4. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -0
  5. package/dist/animation/fixed_geometry_cache_track.js +138 -0
  6. package/dist/animation/fixed_geometry_cache_track.js.map +1 -0
  7. package/dist/animation/geometry_cache_utils.js +120 -0
  8. package/dist/animation/geometry_cache_utils.js.map +1 -0
  9. package/dist/animation/ik_modifier.js +9 -1
  10. package/dist/animation/ik_modifier.js.map +1 -1
  11. package/dist/animation/joint_dynamics/collision.js +469 -0
  12. package/dist/animation/joint_dynamics/collision.js.map +1 -0
  13. package/dist/animation/joint_dynamics/constraints.js +329 -0
  14. package/dist/animation/joint_dynamics/constraints.js.map +1 -0
  15. package/dist/animation/joint_dynamics/controller.js +699 -0
  16. package/dist/animation/joint_dynamics/controller.js.map +1 -0
  17. package/dist/animation/joint_dynamics/joint_dynamics_system.js +393 -0
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -0
  19. package/dist/animation/joint_dynamics/solver.js +794 -0
  20. package/dist/animation/joint_dynamics/solver.js.map +1 -0
  21. package/dist/animation/joint_dynamics/types.js +19 -0
  22. package/dist/animation/joint_dynamics/types.js.map +1 -0
  23. package/dist/animation/joint_dynamics/vrm_spring_bone.js +46 -0
  24. package/dist/animation/joint_dynamics/vrm_spring_bone.js.map +1 -0
  25. package/dist/animation/joint_dynamics_modifier.js +51 -0
  26. package/dist/animation/joint_dynamics_modifier.js.map +1 -0
  27. package/dist/animation/pca_geometry_cache_track.js +222 -0
  28. package/dist/animation/pca_geometry_cache_track.js.map +1 -0
  29. package/dist/animation/skeleton.js +2011 -139
  30. package/dist/animation/skeleton.js.map +1 -1
  31. package/dist/animation/skeleton_modifier.js +3 -5
  32. package/dist/animation/skeleton_modifier.js.map +1 -1
  33. package/dist/animation/spring/multi_chain_spring_system.js +2 -0
  34. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  35. package/dist/animation/spring/spring_chain.js +3 -2
  36. package/dist/animation/spring/spring_chain.js.map +1 -1
  37. package/dist/animation/spring/spring_collider.js +35 -5
  38. package/dist/animation/spring/spring_collider.js.map +1 -1
  39. package/dist/animation/spring/spring_particle.js +1 -0
  40. package/dist/animation/spring/spring_particle.js.map +1 -1
  41. package/dist/animation/spring/spring_system.js +325 -28
  42. package/dist/animation/spring/spring_system.js.map +1 -1
  43. package/dist/animation/spring2/collision.js +469 -0
  44. package/dist/animation/spring2/collision.js.map +1 -0
  45. package/dist/animation/spring2/constraints.js +329 -0
  46. package/dist/animation/spring2/constraints.js.map +1 -0
  47. package/dist/animation/spring2/controller.js +434 -0
  48. package/dist/animation/spring2/controller.js.map +1 -0
  49. package/dist/animation/spring2/math.js +16 -0
  50. package/dist/animation/spring2/math.js.map +1 -0
  51. package/dist/animation/spring2/solver.js +624 -0
  52. package/dist/animation/spring2/solver.js.map +1 -0
  53. package/dist/animation/spring2/spring_system.js +118 -0
  54. package/dist/animation/spring2/spring_system.js.map +1 -0
  55. package/dist/animation/spring2/types.js +19 -0
  56. package/dist/animation/spring2/types.js.map +1 -0
  57. package/dist/animation/spring_modifier.js +17 -1
  58. package/dist/animation/spring_modifier.js.map +1 -1
  59. package/dist/app/engine.js +42 -15
  60. package/dist/app/engine.js.map +1 -1
  61. package/dist/app/runtimescript.js +132 -1
  62. package/dist/app/runtimescript.js.map +1 -1
  63. package/dist/app/screen.js +3 -3
  64. package/dist/app/screen.js.map +1 -1
  65. package/dist/app/scriptingsystem.js +69 -37
  66. package/dist/app/scriptingsystem.js.map +1 -1
  67. package/dist/app/scriptregistry.js +14 -3
  68. package/dist/app/scriptregistry.js.map +1 -1
  69. package/dist/asset/assetmanager.js +2 -1
  70. package/dist/asset/assetmanager.js.map +1 -1
  71. package/dist/asset/loaders/zabc/zabc_loader.js +570 -0
  72. package/dist/asset/loaders/zabc/zabc_loader.js.map +1 -0
  73. package/dist/asset/model.js +192 -0
  74. package/dist/asset/model.js.map +1 -1
  75. package/dist/camera/base.js +26 -7
  76. package/dist/camera/base.js.map +1 -1
  77. package/dist/camera/camera.js +146 -24
  78. package/dist/camera/camera.js.map +1 -1
  79. package/dist/camera/fps.js +2 -2
  80. package/dist/camera/fps.js.map +1 -1
  81. package/dist/camera/orbit.js +2 -2
  82. package/dist/camera/orbit.js.map +1 -1
  83. package/dist/index.d.ts +11728 -8535
  84. package/dist/index.js +29 -8
  85. package/dist/index.js.map +1 -1
  86. package/dist/material/lambert.js +1 -1
  87. package/dist/material/lambert.js.map +1 -1
  88. package/dist/material/material.js +9 -3
  89. package/dist/material/material.js.map +1 -1
  90. package/dist/material/meshmaterial.js +54 -7
  91. package/dist/material/meshmaterial.js.map +1 -1
  92. package/dist/material/mixins/lightmodel/blinnphong.js +17 -7
  93. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  94. package/dist/material/mixins/lightmodel/lambert.js +7 -2
  95. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  96. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +108 -16
  97. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  98. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +209 -14
  99. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  100. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +24 -12
  101. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  102. package/dist/material/mixins/lit.js +11 -8
  103. package/dist/material/mixins/lit.js.map +1 -1
  104. package/dist/material/mixins/pbr/common.js +72 -5
  105. package/dist/material/mixins/pbr/common.js.map +1 -1
  106. package/dist/material/pbrblueprint.js +148 -1
  107. package/dist/material/pbrblueprint.js.map +1 -1
  108. package/dist/material/pbrmr.js +115 -2
  109. package/dist/material/pbrmr.js.map +1 -1
  110. package/dist/material/shader/helper.js +10 -4
  111. package/dist/material/shader/helper.js.map +1 -1
  112. package/dist/material/water.js +2 -2
  113. package/dist/material/water.js.map +1 -1
  114. package/dist/posteffect/coloradjust.js +145 -0
  115. package/dist/posteffect/coloradjust.js.map +1 -0
  116. package/dist/posteffect/taa.js +68 -32
  117. package/dist/posteffect/taa.js.map +1 -1
  118. package/dist/render/cluster_light.js +17 -12
  119. package/dist/render/cluster_light.js.map +1 -1
  120. package/dist/render/deferredlightpass.js +510 -0
  121. package/dist/render/deferredlightpass.js.map +1 -0
  122. package/dist/render/deferredshadowlightpass.js +428 -0
  123. package/dist/render/deferredshadowlightpass.js.map +1 -0
  124. package/dist/render/drawable.js.map +1 -1
  125. package/dist/render/drawable_mixin.js +21 -12
  126. package/dist/render/drawable_mixin.js.map +1 -1
  127. package/dist/render/envlight.js +20 -22
  128. package/dist/render/envlight.js.map +1 -1
  129. package/dist/render/gbufferpass.js +50 -0
  130. package/dist/render/gbufferpass.js.map +1 -0
  131. package/dist/render/lightpass.js +1 -2
  132. package/dist/render/lightpass.js.map +1 -1
  133. package/dist/render/primitive.js +1 -1
  134. package/dist/render/primitive.js.map +1 -1
  135. package/dist/render/render_queue.js +3 -2
  136. package/dist/render/render_queue.js.map +1 -1
  137. package/dist/render/renderer.js +5 -358
  138. package/dist/render/renderer.js.map +1 -1
  139. package/dist/render/rendergraph/executor.js +15 -12
  140. package/dist/render/rendergraph/executor.js.map +1 -1
  141. package/dist/render/rendergraph/forward_plus_builder.js +144 -88
  142. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  143. package/dist/render/rendergraph/history_resource_manager.js +178 -0
  144. package/dist/render/rendergraph/history_resource_manager.js.map +1 -0
  145. package/dist/render/rendergraph/rendergraph.js +12 -1
  146. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  147. package/dist/render/rendergraph/types.js +2 -2
  148. package/dist/render/rendergraph/types.js.map +1 -1
  149. package/dist/render/sky.js +26 -9
  150. package/dist/render/sky.js.map +1 -1
  151. package/dist/scene/basesprite.js +4 -3
  152. package/dist/scene/basesprite.js.map +1 -1
  153. package/dist/scene/batchgroup.js +4 -4
  154. package/dist/scene/environment.js +7 -4
  155. package/dist/scene/environment.js.map +1 -1
  156. package/dist/scene/light.js +184 -18
  157. package/dist/scene/light.js.map +1 -1
  158. package/dist/scene/mesh.js +30 -0
  159. package/dist/scene/mesh.js.map +1 -1
  160. package/dist/scene/particlesys.js +3 -2
  161. package/dist/scene/particlesys.js.map +1 -1
  162. package/dist/scene/raycast_visitor.js +29 -3
  163. package/dist/scene/raycast_visitor.js.map +1 -1
  164. package/dist/scene/scene.js +86 -19
  165. package/dist/scene/scene.js.map +1 -1
  166. package/dist/scene/scene_node.js +87 -31
  167. package/dist/scene/scene_node.js.map +1 -1
  168. package/dist/scene/script_attachment.js +59 -0
  169. package/dist/scene/script_attachment.js.map +1 -0
  170. package/dist/scene/terrain-cm/grass.js +3 -2
  171. package/dist/scene/terrain-cm/grass.js.map +1 -1
  172. package/dist/scene/terrain-cm/terrain-cm.js +4 -3
  173. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  174. package/dist/scene/water.js +3 -2
  175. package/dist/scene/water.js.map +1 -1
  176. package/dist/shaders/shadow.js +2 -2
  177. package/dist/shaders/shadow.js.map +1 -1
  178. package/dist/shadow/shadowmapper.js +74 -4
  179. package/dist/shadow/shadowmapper.js.map +1 -1
  180. package/dist/shapes/box.js +163 -0
  181. package/dist/shapes/box.js.map +1 -1
  182. package/dist/shapes/capsule.js +216 -0
  183. package/dist/shapes/capsule.js.map +1 -0
  184. package/dist/shapes/cylinder.js +91 -0
  185. package/dist/shapes/cylinder.js.map +1 -1
  186. package/dist/shapes/plane.js +32 -0
  187. package/dist/shapes/plane.js.map +1 -1
  188. package/dist/shapes/tetrahedron.js +211 -0
  189. package/dist/shapes/tetrahedron.js.map +1 -1
  190. package/dist/shapes/torus.js +173 -0
  191. package/dist/shapes/torus.js.map +1 -1
  192. package/dist/utility/blueprint/common/math.js +111 -1
  193. package/dist/utility/blueprint/common/math.js.map +1 -1
  194. package/dist/utility/blueprint/material/inputs.js +235 -1
  195. package/dist/utility/blueprint/material/inputs.js.map +1 -1
  196. package/dist/utility/blueprint/material/ir.js +154 -10
  197. package/dist/utility/blueprint/material/ir.js.map +1 -1
  198. package/dist/utility/blueprint/material/texture.js +273 -19
  199. package/dist/utility/blueprint/material/texture.js.map +1 -1
  200. package/dist/utility/serialization/json.js +12 -2
  201. package/dist/utility/serialization/json.js.map +1 -1
  202. package/dist/utility/serialization/manager.js +30 -11
  203. package/dist/utility/serialization/manager.js.map +1 -1
  204. package/dist/utility/serialization/scene/animation.js +250 -7
  205. package/dist/utility/serialization/scene/animation.js.map +1 -1
  206. package/dist/utility/serialization/scene/batch.js +4 -2
  207. package/dist/utility/serialization/scene/batch.js.map +1 -1
  208. package/dist/utility/serialization/scene/camera.js +154 -2
  209. package/dist/utility/serialization/scene/camera.js.map +1 -1
  210. package/dist/utility/serialization/scene/cloth_script.js +834 -0
  211. package/dist/utility/serialization/scene/cloth_script.js.map +1 -0
  212. package/dist/utility/serialization/scene/common.js +7 -0
  213. package/dist/utility/serialization/scene/common.js.map +1 -1
  214. package/dist/utility/serialization/scene/light.js +120 -4
  215. package/dist/utility/serialization/scene/light.js.map +1 -1
  216. package/dist/utility/serialization/scene/material.js +453 -1
  217. package/dist/utility/serialization/scene/material.js.map +1 -1
  218. package/dist/utility/serialization/scene/mesh.js +4 -2
  219. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  220. package/dist/utility/serialization/scene/node.js +298 -10
  221. package/dist/utility/serialization/scene/node.js.map +1 -1
  222. package/dist/utility/serialization/scene/particle.js +4 -2
  223. package/dist/utility/serialization/scene/particle.js.map +1 -1
  224. package/dist/utility/serialization/scene/primitive.js +100 -3
  225. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  226. package/dist/utility/serialization/scene/scene.js +130 -3
  227. package/dist/utility/serialization/scene/scene.js.map +1 -1
  228. package/dist/utility/serialization/scene/script.js +66 -0
  229. package/dist/utility/serialization/scene/script.js.map +1 -0
  230. package/dist/utility/serialization/scene/spring_script.js +596 -0
  231. package/dist/utility/serialization/scene/spring_script.js.map +1 -0
  232. package/dist/utility/serialization/scene/sprite.js +5 -3
  233. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  234. package/dist/utility/serialization/scene/terrain.js +4 -2
  235. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  236. package/dist/utility/serialization/scene/water.js +4 -2
  237. package/dist/utility/serialization/scene/water.js.map +1 -1
  238. package/dist/utility/serialization/types.js.map +1 -1
  239. package/dist/values.js +5 -1
  240. package/dist/values.js.map +1 -1
  241. package/package.json +3 -3
@@ -0,0 +1,570 @@
1
+ import { base64ToUint8Array, Vector3 } from '@zephyr3d/base';
2
+ import { FixedGeometryCacheTrack } from '../../../animation/fixed_geometry_cache_track.js';
3
+ import { PCAGeometryCacheTrack } from '../../../animation/pca_geometry_cache_track.js';
4
+ import { BoundingBox } from '../../../utility/bounding_volume.js';
5
+
6
+ async function parseZABCBlob(data) {
7
+ const arrayBuffer = await data.arrayBuffer();
8
+ if (isBinaryZABC(arrayBuffer)) {
9
+ return parseBinaryZABC(arrayBuffer);
10
+ }
11
+ return parseLegacyZABC(arrayBuffer);
12
+ }
13
+ async function attachZABCAnimationsToSceneNode(node, parsed, options) {
14
+ if (options?.replaceAnimationNames) {
15
+ for (const name of options.replaceAnimationNames){
16
+ node.animationSet.deleteAnimation(name);
17
+ }
18
+ }
19
+ const addedAnimationNames = [];
20
+ for (const animation of parsed.content.animations ?? []){
21
+ const animationName = buildAnimationName(options?.sourcePath, animation.name ?? 'GeometryCache');
22
+ node.animationSet.deleteAnimation(animationName);
23
+ const clip = node.animationSet.createAnimation(animationName, true);
24
+ if (!clip) {
25
+ continue;
26
+ }
27
+ clip.autoPlay = !!options?.autoPlay;
28
+ for (const track of animation.tracks ?? []){
29
+ const targetNode = findTargetNode(node, track);
30
+ if (!targetNode) {
31
+ console.error(`zabc track target not found: node=${track.node}, nodePath=${track.nodePath}, nodeName=${track.nodeName}`);
32
+ continue;
33
+ }
34
+ const targetMesh = await getTargetMesh(targetNode, track, parsed);
35
+ if (!targetMesh) {
36
+ const subMeshLabel = typeof track.subMeshIndex === 'number' && track.subMeshIndex >= 0 ? `${track.subMeshIndex}` : 'auto';
37
+ console.error(`zabc target mesh not found: node=${targetNode.name}, subMeshIndex=${subMeshLabel}`);
38
+ continue;
39
+ }
40
+ const assetSubMesh = getTargetAssetSubMesh(node, track);
41
+ if (track.codec === 'pca') {
42
+ const remapped = assetSubMesh ? remapPCAGeometryCacheData(assetSubMesh, toPCATrackData(track, parsed)) : await remapPCAGeometryCacheDataForMesh(targetMesh, toPCATrackData(track, parsed));
43
+ clip.addTrack(targetMesh, new PCAGeometryCacheTrack(remapped, true));
44
+ } else {
45
+ const frames = assetSubMesh ? remapGeometryCacheFrames(assetSubMesh, track.positionFrames.map((positionsRef, index)=>({
46
+ positions: decodeFloat32Array(positionsRef, parsed),
47
+ normals: track.normalFrames?.[index] ? decodeFloat32Array(track.normalFrames[index], parsed) : null,
48
+ boundingBox: decodeBoundingBox(track.bounds[index])
49
+ }))) : await remapGeometryCacheFramesForMesh(targetMesh, track.positionFrames.map((positionsRef, index)=>({
50
+ positions: decodeFloat32Array(positionsRef, parsed),
51
+ normals: track.normalFrames?.[index] ? decodeFloat32Array(track.normalFrames[index], parsed) : null,
52
+ boundingBox: decodeBoundingBox(track.bounds[index])
53
+ })));
54
+ clip.addTrack(targetMesh, new FixedGeometryCacheTrack(decodeTimes(track, parsed), frames, true));
55
+ }
56
+ }
57
+ if (clip.tracks.size > 0) {
58
+ addedAnimationNames.push(animationName);
59
+ } else {
60
+ node.animationSet.deleteAnimation(animationName);
61
+ }
62
+ }
63
+ if (options?.autoPlay) {
64
+ for (const animationName of addedAnimationNames){
65
+ node.animationSet.playAnimation(animationName, {
66
+ repeat: 0
67
+ });
68
+ }
69
+ }
70
+ return {
71
+ animationNames: addedAnimationNames
72
+ };
73
+ }
74
+ function buildAnimationName(sourcePath, animationName) {
75
+ const fileName = sourcePath ? sourcePath.replace(/\\/g, '/').split('/').filter(Boolean).pop() ?? 'cache' : 'cache';
76
+ return `Cache:${fileName}:${animationName}`;
77
+ }
78
+ async function getTargetMesh(node, track, parsed) {
79
+ const directMeshes = collectMeshChildren(node, false);
80
+ const candidateMeshes = directMeshes.length > 0 ? directMeshes : collectMeshChildren(node, true);
81
+ if (candidateMeshes.length === 0) {
82
+ return null;
83
+ }
84
+ if (typeof track.subMeshIndex === 'number' && track.subMeshIndex >= 0) {
85
+ return candidateMeshes[track.subMeshIndex] ?? null;
86
+ }
87
+ if (candidateMeshes.length === 1) {
88
+ return candidateMeshes[0];
89
+ }
90
+ const sourceVertexCount = getTrackSourceVertexCount(track, parsed);
91
+ if (sourceVertexCount > 0) {
92
+ const matched = [];
93
+ for (const mesh of candidateMeshes){
94
+ const rawPositions = await getMeshRawPositions(mesh);
95
+ const targetVertexCount = rawPositions ? rawPositions.length / 3 >> 0 : -1;
96
+ if (targetVertexCount === sourceVertexCount) {
97
+ matched.push(mesh);
98
+ }
99
+ }
100
+ if (matched.length === 1) {
101
+ return matched[0];
102
+ }
103
+ if (matched.length > 1) {
104
+ console.warn(`zabc subMesh auto-match is ambiguous under node=${node.name}, matched=${matched.length}, fallback=first`);
105
+ }
106
+ }
107
+ return candidateMeshes[0];
108
+ }
109
+ function collectMeshChildren(root, recursive) {
110
+ const meshes = [];
111
+ if (recursive) {
112
+ root.iterate((child)=>{
113
+ if (child !== root && child.isMesh()) {
114
+ meshes.push(child);
115
+ }
116
+ return false;
117
+ });
118
+ return meshes;
119
+ }
120
+ for (const child of root.children){
121
+ const sceneNode = child;
122
+ if (sceneNode?.isMesh()) {
123
+ meshes.push(sceneNode);
124
+ }
125
+ }
126
+ return meshes;
127
+ }
128
+ function getTrackSourceVertexCount(track, parsed) {
129
+ try {
130
+ const first = track.positionFrames?.[0];
131
+ if (!first) {
132
+ return -1;
133
+ }
134
+ return decodeFloat32Array(first, parsed).length / 3 >> 0;
135
+ } catch {
136
+ return -1;
137
+ }
138
+ }
139
+ function getTargetAssetSubMesh(node, track) {
140
+ const sharedModel = node.sharedModel;
141
+ if (!sharedModel) {
142
+ return null;
143
+ }
144
+ if (typeof track.subMeshIndex !== 'number' || track.subMeshIndex < 0) {
145
+ return null;
146
+ }
147
+ const assetNode = findTargetAssetNode(node, track);
148
+ return assetNode?.mesh?.subMeshes?.[track.subMeshIndex] ?? null;
149
+ }
150
+ function findTargetAssetNode(root, track) {
151
+ const sharedModel = root.sharedModel;
152
+ if (!sharedModel) {
153
+ return null;
154
+ }
155
+ if (track.nodePath) {
156
+ for (const candidatePath of getNodePathCandidates(track.nodePath)){
157
+ for (const scene of sharedModel.scenes){
158
+ for (const rootNode of scene.rootNodes){
159
+ const found = findAssetNodeByPath(rootNode, candidatePath);
160
+ if (found) {
161
+ return found;
162
+ }
163
+ }
164
+ }
165
+ }
166
+ }
167
+ if (track.nodeName) {
168
+ for (const candidateName of getNodeNameCandidates(track.nodeName)){
169
+ const found = sharedModel.nodes.find((item)=>item?.name === candidateName);
170
+ if (found) {
171
+ return found;
172
+ }
173
+ }
174
+ }
175
+ return null;
176
+ }
177
+ function findAssetNodeByPath(node, normalizedTrackPath, currentPath = '') {
178
+ if (!node) {
179
+ return null;
180
+ }
181
+ const path = currentPath ? `${currentPath}/${node.name || ''}` : node.name || '';
182
+ const normalizedCurrent = normalizeNodePath(path);
183
+ if (normalizedCurrent === normalizedTrackPath) {
184
+ return node;
185
+ }
186
+ for (const child of node.children){
187
+ const found = findAssetNodeByPath(child, normalizedTrackPath, path);
188
+ if (found) {
189
+ return found;
190
+ }
191
+ }
192
+ return null;
193
+ }
194
+ function findTargetNode(root, track) {
195
+ const hasExplicitTarget = !!track.nodePath || !!track.nodeName;
196
+ if (track.nodePath) {
197
+ for (const candidatePath of getNodePathCandidates(track.nodePath)){
198
+ for (const child of root.children){
199
+ const found = findSceneNodeByPath(child, candidatePath);
200
+ if (found) {
201
+ return found;
202
+ }
203
+ }
204
+ }
205
+ }
206
+ if (track.nodeName) {
207
+ for (const candidateName of getNodeNameCandidates(track.nodeName)){
208
+ const found = root.findNodeByName(candidateName);
209
+ if (found) {
210
+ return found;
211
+ }
212
+ }
213
+ }
214
+ if (hasExplicitTarget) {
215
+ console.warn(`zabc track target fallback to attached node: nodePath=${track.nodePath ?? ''}, nodeName=${track.nodeName ?? ''}`);
216
+ }
217
+ return root;
218
+ }
219
+ function findSceneNodeByPath(node, normalizedTrackPath, currentPath = '') {
220
+ if (!node || node.isMesh()) {
221
+ return null;
222
+ }
223
+ const path = currentPath ? `${currentPath}/${node.name || ''}` : node.name || '';
224
+ const normalizedCurrent = normalizeNodePath(path);
225
+ if (normalizedCurrent === normalizedTrackPath) {
226
+ return node;
227
+ }
228
+ for (const child of node.children){
229
+ const found = findSceneNodeByPath(child, normalizedTrackPath, path);
230
+ if (found) {
231
+ return found;
232
+ }
233
+ }
234
+ return null;
235
+ }
236
+ function getNodePathCandidates(path) {
237
+ const normalized = normalizeNodePath(path);
238
+ const candidates = [
239
+ normalized
240
+ ];
241
+ if (normalized.endsWith('Shape')) {
242
+ candidates.push(normalized.slice(0, -'Shape'.length));
243
+ }
244
+ const parts = normalized.split('/');
245
+ const last = parts.length > 0 ? parts[parts.length - 1] : '';
246
+ if (last.endsWith('Shape') && parts.length > 1) {
247
+ parts[parts.length - 1] = last.slice(0, -'Shape'.length);
248
+ candidates.push(parts.join('/'));
249
+ parts.pop();
250
+ candidates.push(parts.join('/'));
251
+ }
252
+ return candidates.filter((value, index, array)=>!!value && array.indexOf(value) === index);
253
+ }
254
+ function getNodeNameCandidates(name) {
255
+ const candidates = [
256
+ name
257
+ ];
258
+ if (name.endsWith('Shape')) {
259
+ candidates.push(name.slice(0, -'Shape'.length));
260
+ }
261
+ return candidates.filter((value, index, array)=>!!value && array.indexOf(value) === index);
262
+ }
263
+ function normalizeNodePath(path) {
264
+ return path.replace(/\\/g, '/').split('/').filter(Boolean).join('/');
265
+ }
266
+ function decodeFloat32Array(data, parsed) {
267
+ if (typeof data === 'string') {
268
+ const bytes = base64ToUint8Array(data);
269
+ return new Float32Array(bytes.buffer.slice(bytes.byteOffset, bytes.byteOffset + bytes.byteLength));
270
+ }
271
+ if (!parsed.binaryPayload) {
272
+ throw new Error('Invalid binary zabc file: missing payload');
273
+ }
274
+ const start = parsed.payloadOffset + data.offset;
275
+ const end = start + data.length;
276
+ return new Float32Array(parsed.binaryPayload.slice(start, end));
277
+ }
278
+ function decodeTimes(track, parsed) {
279
+ if (track.times) {
280
+ return decodeFloat32Array(track.times, parsed);
281
+ }
282
+ const sampleRate = track.sampleRate && track.sampleRate > 0 ? track.sampleRate : 30;
283
+ const times = new Float32Array(track.positionFrames.length);
284
+ for(let i = 0; i < times.length; i++){
285
+ times[i] = i / sampleRate;
286
+ }
287
+ return times;
288
+ }
289
+ function decodeBoundingBox(values) {
290
+ return new BoundingBox(new Vector3(values[0], values[1], values[2]), new Vector3(values[3], values[4], values[5]));
291
+ }
292
+ function decodePCAFrames(data, rows, columns, parsed) {
293
+ const values = decodeFloat32Array(data, parsed);
294
+ const result = [];
295
+ if (rows <= 0 || columns <= 0) {
296
+ return result;
297
+ }
298
+ for(let i = 0; i < rows; i++){
299
+ result.push(values.slice(i * columns, i * columns + columns));
300
+ }
301
+ return result;
302
+ }
303
+ function toPCATrackData(track, parsed) {
304
+ return {
305
+ times: decodeTimes(track, parsed),
306
+ bounds: track.bounds ?? [],
307
+ positionReference: track.positionReference ? decodeFloat32Array(track.positionReference, parsed) : null,
308
+ positionMean: decodeFloat32Array(track.positionMean, parsed),
309
+ positionBases: decodePCAFrames(track.positionBases, track.positionComponents ?? 0, track.vectorLength ?? 0, parsed),
310
+ positionCoefficients: decodePCAFrames(track.positionCoefficients, track.bounds?.length ?? 0, track.positionComponents ?? 0, parsed),
311
+ normalMean: track.normalMean ? decodeFloat32Array(track.normalMean, parsed) : null,
312
+ normalBases: track.normalBases && track.normalComponents ? decodePCAFrames(track.normalBases, track.normalComponents, track.vectorLength ?? 0, parsed) : null,
313
+ normalCoefficients: track.normalCoefficients && track.normalComponents ? decodePCAFrames(track.normalCoefficients, track.bounds?.length ?? 0, track.normalComponents, parsed) : null
314
+ };
315
+ }
316
+ function parseLegacyZABC(arrayBuffer) {
317
+ const text = new TextDecoder().decode(arrayBuffer);
318
+ return {
319
+ content: JSON.parse(text),
320
+ binaryPayload: null,
321
+ payloadOffset: 0
322
+ };
323
+ }
324
+ function parseBinaryZABC(arrayBuffer) {
325
+ const view = new DataView(arrayBuffer);
326
+ const version = view.getUint32(4, true);
327
+ if (version !== 2 && version !== 3) {
328
+ throw new Error(`Unsupported binary zabc version: ${version}`);
329
+ }
330
+ const manifestLength = view.getUint32(8, true);
331
+ const manifestOffset = 12;
332
+ const payloadOffset = manifestOffset + manifestLength;
333
+ const manifestText = new TextDecoder().decode(arrayBuffer.slice(manifestOffset, payloadOffset));
334
+ return {
335
+ content: JSON.parse(manifestText),
336
+ binaryPayload: arrayBuffer,
337
+ payloadOffset
338
+ };
339
+ }
340
+ function isBinaryZABC(arrayBuffer) {
341
+ if (arrayBuffer.byteLength < 12) {
342
+ return false;
343
+ }
344
+ const magic = new Uint8Array(arrayBuffer, 0, 4);
345
+ return magic[0] === 0x5a && magic[1] === 0x41 && magic[2] === 0x42 && magic[3] === 0x43;
346
+ }
347
+ function remapGeometryCacheFrames(subMesh, frames) {
348
+ if (!subMesh.rawPositions || frames.length === 0) {
349
+ return frames;
350
+ }
351
+ const sourcePositions = frames[0].positions;
352
+ const sourceVertexCount = sourcePositions.length / 3 >> 0;
353
+ const targetVertexCount = subMesh.rawPositions.length / 3 >> 0;
354
+ if (sourceVertexCount === targetVertexCount) {
355
+ return frames;
356
+ }
357
+ const remap = buildGeometryCacheRemap(subMesh.rawPositions, sourcePositions);
358
+ if (!remap) {
359
+ console.error(`Geometry cache vertex layout mismatch: source=${sourceVertexCount}, target=${targetVertexCount}. ` + `Export the base glb and zabc from the same final mesh layout.`);
360
+ return frames;
361
+ }
362
+ return frames.map((frame)=>({
363
+ positions: expandGeometryCacheData(frame.positions, remap),
364
+ normals: frame.normals && frame.normals.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(frame.normals, remap) : null,
365
+ boundingBox: frame.boundingBox
366
+ }));
367
+ }
368
+ async function remapGeometryCacheFramesForMesh(mesh, frames) {
369
+ const rawPositions = await getMeshRawPositions(mesh);
370
+ if (!rawPositions || frames.length === 0) {
371
+ return frames;
372
+ }
373
+ const sourcePositions = frames[0].positions;
374
+ const sourceVertexCount = sourcePositions.length / 3 >> 0;
375
+ const targetVertexCount = rawPositions.length / 3 >> 0;
376
+ if (sourceVertexCount === targetVertexCount) {
377
+ return frames;
378
+ }
379
+ const remap = buildGeometryCacheRemap(rawPositions, sourcePositions);
380
+ if (!remap) {
381
+ console.error(`Geometry cache vertex layout mismatch: source=${sourceVertexCount}, target=${targetVertexCount}. ` + `Export the base glb and zabc from the same final mesh layout.`);
382
+ return frames;
383
+ }
384
+ return frames.map((frame)=>({
385
+ positions: expandGeometryCacheData(frame.positions, remap),
386
+ normals: frame.normals && frame.normals.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(frame.normals, remap) : null,
387
+ boundingBox: frame.boundingBox
388
+ }));
389
+ }
390
+ function remapPCAGeometryCacheData(subMesh, track) {
391
+ const remapReference = track.positionReference ?? reconstructPCAGeometryCacheReference(track);
392
+ if (!subMesh.rawPositions || remapReference.length === 0) {
393
+ return track;
394
+ }
395
+ const sourceVertexCount = remapReference.length / 3 >> 0;
396
+ const targetVertexCount = subMesh.rawPositions.length / 3 >> 0;
397
+ if (sourceVertexCount === targetVertexCount) {
398
+ return track;
399
+ }
400
+ const remap = buildGeometryCacheRemap(subMesh.rawPositions, remapReference);
401
+ if (!remap) {
402
+ console.error(`Geometry cache vertex layout mismatch: source=${sourceVertexCount}, target=${targetVertexCount}. ` + `Export the base glb and zabc from the same final mesh layout.`);
403
+ return track;
404
+ }
405
+ return {
406
+ times: track.times,
407
+ bounds: track.bounds,
408
+ positionReference: expandGeometryCacheData(remapReference, remap),
409
+ positionMean: expandGeometryCacheData(track.positionMean, remap),
410
+ positionBases: track.positionBases.map((basis)=>expandGeometryCacheData(basis, remap)),
411
+ positionCoefficients: track.positionCoefficients,
412
+ normalMean: track.normalMean && track.normalMean.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(track.normalMean, remap) : null,
413
+ normalBases: track.normalBases?.map((basis)=>basis.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(basis, remap) : basis) ?? null,
414
+ normalCoefficients: track.normalCoefficients ?? null
415
+ };
416
+ }
417
+ async function remapPCAGeometryCacheDataForMesh(mesh, track) {
418
+ const rawPositions = await getMeshRawPositions(mesh);
419
+ const remapReference = track.positionReference ?? reconstructPCAGeometryCacheReference(track);
420
+ if (!rawPositions || remapReference.length === 0) {
421
+ return track;
422
+ }
423
+ const sourceVertexCount = remapReference.length / 3 >> 0;
424
+ const targetVertexCount = rawPositions.length / 3 >> 0;
425
+ if (sourceVertexCount === targetVertexCount) {
426
+ return track;
427
+ }
428
+ const remap = buildGeometryCacheRemap(rawPositions, remapReference);
429
+ if (!remap) {
430
+ console.error(`Geometry cache vertex layout mismatch: source=${sourceVertexCount}, target=${targetVertexCount}. ` + `Export the base glb and zabc from the same final mesh layout.`);
431
+ return track;
432
+ }
433
+ return {
434
+ times: track.times,
435
+ bounds: track.bounds,
436
+ positionReference: expandGeometryCacheData(remapReference, remap),
437
+ positionMean: expandGeometryCacheData(track.positionMean, remap),
438
+ positionBases: track.positionBases.map((basis)=>expandGeometryCacheData(basis, remap)),
439
+ positionCoefficients: track.positionCoefficients,
440
+ normalMean: track.normalMean && track.normalMean.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(track.normalMean, remap) : null,
441
+ normalBases: track.normalBases?.map((basis)=>basis.length / 3 >> 0 === sourceVertexCount ? expandGeometryCacheData(basis, remap) : basis) ?? null,
442
+ normalCoefficients: track.normalCoefficients ?? null
443
+ };
444
+ }
445
+ async function getMeshRawPositions(mesh) {
446
+ const primitive = mesh.primitive;
447
+ const info = primitive?.getVertexBufferInfo('position');
448
+ if (!primitive || !info) {
449
+ return null;
450
+ }
451
+ const bytes = await info.buffer.getBufferSubData();
452
+ return extractPositionArray(bytes, info);
453
+ }
454
+ function extractPositionArray(bytes, info) {
455
+ const componentSize = (info.type.getSize?.() ?? 0) / Math.max(1, info.type.cols);
456
+ if (componentSize !== 4) {
457
+ return null;
458
+ }
459
+ const drawOffset = info.drawOffset ?? 0;
460
+ const byteOffset = bytes.byteOffset + drawOffset;
461
+ const byteLength = bytes.byteLength - drawOffset;
462
+ const vertexCount = Math.max(0, Math.floor(byteLength / info.stride));
463
+ const positions = new Float32Array(vertexCount * 3);
464
+ for(let i = 0; i < vertexCount; i++){
465
+ const base = byteOffset + i * info.stride + info.offset;
466
+ const values = new Float32Array(bytes.buffer, base, Math.max(3, info.type.cols));
467
+ positions[i * 3] = values[0] ?? 0;
468
+ positions[i * 3 + 1] = values[1] ?? 0;
469
+ positions[i * 3 + 2] = values[2] ?? 0;
470
+ }
471
+ return positions;
472
+ }
473
+ function reconstructPCAGeometryCacheReference(track) {
474
+ const reference = new Float32Array(track.positionMean);
475
+ const coefficients = track.positionCoefficients[0];
476
+ if (!coefficients) {
477
+ return reference;
478
+ }
479
+ const componentCount = Math.min(track.positionBases.length, coefficients.length);
480
+ for(let component = 0; component < componentCount; component++){
481
+ const basis = track.positionBases[component];
482
+ const coefficient = coefficients[component];
483
+ if (!basis || coefficient === 0) {
484
+ continue;
485
+ }
486
+ const count = Math.min(reference.length, basis.length);
487
+ for(let i = 0; i < count; i++){
488
+ reference[i] += basis[i] * coefficient;
489
+ }
490
+ }
491
+ return reference;
492
+ }
493
+ function buildGeometryCacheRemap(targetPositions, sourcePositions) {
494
+ const sourceCount = sourcePositions.length / 3 >> 0;
495
+ const targetCount = targetPositions.length / 3 >> 0;
496
+ const buckets = new Map();
497
+ for(let i = 0; i < sourceCount; i++){
498
+ const key = geometryCachePositionKey(sourcePositions[i * 3], sourcePositions[i * 3 + 1], sourcePositions[i * 3 + 2]);
499
+ const bucket = buckets.get(key);
500
+ if (bucket) {
501
+ bucket.push(i);
502
+ } else {
503
+ buckets.set(key, [
504
+ i
505
+ ]);
506
+ }
507
+ }
508
+ const remap = new Uint32Array(targetCount);
509
+ for(let i = 0; i < targetCount; i++){
510
+ const x = targetPositions[i * 3];
511
+ const y = targetPositions[i * 3 + 1];
512
+ const z = targetPositions[i * 3 + 2];
513
+ let sourceIndex = findGeometryCacheSourceIndex(sourcePositions, buckets, x, y, z);
514
+ if (sourceIndex < 0) {
515
+ sourceIndex = findNearestGeometryCacheSourceIndex(sourcePositions, x, y, z);
516
+ }
517
+ if (sourceIndex < 0) {
518
+ return null;
519
+ }
520
+ remap[i] = sourceIndex;
521
+ }
522
+ return remap;
523
+ }
524
+ function expandGeometryCacheData(source, remap) {
525
+ const expanded = new Float32Array(remap.length * 3);
526
+ for(let i = 0; i < remap.length; i++){
527
+ const sourceOffset = remap[i] * 3;
528
+ const targetOffset = i * 3;
529
+ expanded[targetOffset] = source[sourceOffset];
530
+ expanded[targetOffset + 1] = source[sourceOffset + 1];
531
+ expanded[targetOffset + 2] = source[sourceOffset + 2];
532
+ }
533
+ return expanded;
534
+ }
535
+ function findGeometryCacheSourceIndex(sourcePositions, buckets, x, y, z) {
536
+ const bucket = buckets.get(geometryCachePositionKey(x, y, z));
537
+ if (!bucket) {
538
+ return -1;
539
+ }
540
+ const epsilon = 1e-5;
541
+ for (const index of bucket){
542
+ const offset = index * 3;
543
+ if (Math.abs(sourcePositions[offset] - x) <= epsilon && Math.abs(sourcePositions[offset + 1] - y) <= epsilon && Math.abs(sourcePositions[offset + 2] - z) <= epsilon) {
544
+ return index;
545
+ }
546
+ }
547
+ return -1;
548
+ }
549
+ function findNearestGeometryCacheSourceIndex(sourcePositions, x, y, z) {
550
+ const epsilonSquared = 1e-8;
551
+ let bestIndex = -1;
552
+ let bestDistance = Number.POSITIVE_INFINITY;
553
+ for(let i = 0; i < sourcePositions.length; i += 3){
554
+ const dx = sourcePositions[i] - x;
555
+ const dy = sourcePositions[i + 1] - y;
556
+ const dz = sourcePositions[i + 2] - z;
557
+ const distance = dx * dx + dy * dy + dz * dz;
558
+ if (distance < bestDistance) {
559
+ bestDistance = distance;
560
+ bestIndex = i / 3;
561
+ }
562
+ }
563
+ return bestDistance <= epsilonSquared ? bestIndex : -1;
564
+ }
565
+ function geometryCachePositionKey(x, y, z) {
566
+ return `${Math.round(x * 100000)}|${Math.round(y * 100000)}|${Math.round(z * 100000)}`;
567
+ }
568
+
569
+ export { attachZABCAnimationsToSceneNode, parseZABCBlob };
570
+ //# sourceMappingURL=zabc_loader.js.map