@zephyr3d/scene 0.9.25 → 0.9.27

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 (299) hide show
  1. package/dist/animation/animationset.js +92 -30
  2. package/dist/animation/animationset.js.map +1 -1
  3. package/dist/animation/hair/gpu_hair_simulation.js +1090 -0
  4. package/dist/animation/hair/gpu_hair_simulation.js.map +1 -0
  5. package/dist/animation/joint_dynamics/controller.js +7 -5
  6. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  7. package/dist/animation/joint_dynamics/convex_collider.js +320 -0
  8. package/dist/animation/joint_dynamics/convex_collider.js.map +1 -0
  9. package/dist/animation/joint_dynamics/joint_dynamics_system.js +81 -5
  10. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  11. package/dist/animation/morphtrack.js +3 -4
  12. package/dist/animation/morphtrack.js.map +1 -1
  13. package/dist/animation/skeleton.js +79 -25
  14. package/dist/animation/skeleton.js.map +1 -1
  15. package/dist/animation/spring/multi_chain_spring_system.js +577 -179
  16. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  17. package/dist/animation/spring/spring_collider.js +4 -3
  18. package/dist/animation/spring/spring_collider.js.map +1 -1
  19. package/dist/animation/spring/spring_node_pose_tracker.js +40 -0
  20. package/dist/animation/spring/spring_node_pose_tracker.js.map +1 -0
  21. package/dist/animation/spring/spring_particle.js +2 -0
  22. package/dist/animation/spring/spring_particle.js.map +1 -1
  23. package/dist/animation/spring/spring_system.js +11 -3
  24. package/dist/animation/spring/spring_system.js.map +1 -1
  25. package/dist/animation/spring_modifier.js +10 -0
  26. package/dist/animation/spring_modifier.js.map +1 -1
  27. package/dist/app/engine.js +53 -43
  28. package/dist/app/engine.js.map +1 -1
  29. package/dist/app/scriptingsystem.js +119 -6
  30. package/dist/app/scriptingsystem.js.map +1 -1
  31. package/dist/app/scriptregistry.js +3 -2
  32. package/dist/app/scriptregistry.js.map +1 -1
  33. package/dist/asset/assetmanager.js +284 -67
  34. package/dist/asset/assetmanager.js.map +1 -1
  35. package/dist/asset/loaders/zhair/zhair_format.js +288 -0
  36. package/dist/asset/loaders/zhair/zhair_format.js.map +1 -0
  37. package/dist/asset/loaders/zhair/zhair_loader.js +221 -0
  38. package/dist/asset/loaders/zhair/zhair_loader.js.map +1 -0
  39. package/dist/asset/model.js +184 -69
  40. package/dist/asset/model.js.map +1 -1
  41. package/dist/camera/camera.js +268 -44
  42. package/dist/camera/camera.js.map +1 -1
  43. package/dist/camera/perspectivecamera.js +3 -1
  44. package/dist/camera/perspectivecamera.js.map +1 -1
  45. package/dist/index.d.ts +9044 -5139
  46. package/dist/index.js +17 -6
  47. package/dist/index.js.map +1 -1
  48. package/dist/material/eye.js +932 -0
  49. package/dist/material/eye.js.map +1 -0
  50. package/dist/material/hair.js +917 -0
  51. package/dist/material/hair.js.map +1 -0
  52. package/dist/material/hairstrand.js +842 -0
  53. package/dist/material/hairstrand.js.map +1 -0
  54. package/dist/material/hairstrand_data.js +162 -0
  55. package/dist/material/hairstrand_data.js.map +1 -0
  56. package/dist/material/lambert.js +5 -2
  57. package/dist/material/lambert.js.map +1 -1
  58. package/dist/material/material.js +48 -10
  59. package/dist/material/material.js.map +1 -1
  60. package/dist/material/meshmaterial.js +120 -19
  61. package/dist/material/meshmaterial.js.map +1 -1
  62. package/dist/material/mixins/albedocolor.js +1 -1
  63. package/dist/material/mixins/albedocolor.js.map +1 -1
  64. package/dist/material/mixins/lightmodel/blinnphong.js +5 -3
  65. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  66. package/dist/material/mixins/lightmodel/lambert.js +5 -4
  67. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  68. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +3 -3
  69. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  70. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +5 -5
  71. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  72. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +3 -3
  73. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  74. package/dist/material/mixins/lit.js +106 -19
  75. package/dist/material/mixins/lit.js.map +1 -1
  76. package/dist/material/mixins/pbr/common.js +4 -4
  77. package/dist/material/mixins/pbr/common.js.map +1 -1
  78. package/dist/material/mixins/texture.js +48 -11
  79. package/dist/material/mixins/texture.js.map +1 -1
  80. package/dist/material/mtoon.js +6 -5
  81. package/dist/material/mtoon.js.map +1 -1
  82. package/dist/material/pbrblueprint.js +146 -28
  83. package/dist/material/pbrblueprint.js.map +1 -1
  84. package/dist/material/pbrblueprint_instance.js +501 -0
  85. package/dist/material/pbrblueprint_instance.js.map +1 -0
  86. package/dist/material/pbrmr.js +15 -16
  87. package/dist/material/pbrmr.js.map +1 -1
  88. package/dist/material/shader/helper.js +734 -23
  89. package/dist/material/shader/helper.js.map +1 -1
  90. package/dist/material/shader/terrain_blend.js +55 -0
  91. package/dist/material/shader/terrain_blend.js.map +1 -0
  92. package/dist/material/skin.js +192 -32
  93. package/dist/material/skin.js.map +1 -1
  94. package/dist/material/spriteblueprint.js +16 -1
  95. package/dist/material/spriteblueprint.js.map +1 -1
  96. package/dist/material/subsurfaceprofile.js +86 -23
  97. package/dist/material/subsurfaceprofile.js.map +1 -1
  98. package/dist/material/water.js +2059 -72
  99. package/dist/material/water.js.map +1 -1
  100. package/dist/posteffect/bloom.js +167 -7
  101. package/dist/posteffect/bloom.js.map +1 -1
  102. package/dist/posteffect/coloradjust.js +2 -1
  103. package/dist/posteffect/coloradjust.js.map +1 -1
  104. package/dist/posteffect/compositor.js.map +1 -1
  105. package/dist/posteffect/fxaa.js +2 -1
  106. package/dist/posteffect/fxaa.js.map +1 -1
  107. package/dist/posteffect/grayscale.js +3 -1
  108. package/dist/posteffect/grayscale.js.map +1 -1
  109. package/dist/posteffect/motionblur.js +664 -56
  110. package/dist/posteffect/motionblur.js.map +1 -1
  111. package/dist/posteffect/posteffect.js +12 -1
  112. package/dist/posteffect/posteffect.js.map +1 -1
  113. package/dist/posteffect/sao.js +46 -44
  114. package/dist/posteffect/sao.js.map +1 -1
  115. package/dist/posteffect/skinsss.js +368 -69
  116. package/dist/posteffect/skinsss.js.map +1 -1
  117. package/dist/posteffect/ssgi.js +16 -9
  118. package/dist/posteffect/ssgi.js.map +1 -1
  119. package/dist/posteffect/ssr.js +3 -0
  120. package/dist/posteffect/ssr.js.map +1 -1
  121. package/dist/posteffect/sss.js +121 -36
  122. package/dist/posteffect/sss.js.map +1 -1
  123. package/dist/posteffect/taa.js.map +1 -1
  124. package/dist/posteffect/tonemap.js +44 -1
  125. package/dist/posteffect/tonemap.js.map +1 -1
  126. package/dist/render/abuffer_oit.js +8 -2
  127. package/dist/render/abuffer_oit.js.map +1 -1
  128. package/dist/render/clipmap.js +156 -5
  129. package/dist/render/clipmap.js.map +1 -1
  130. package/dist/render/cull_visitor.js +20 -0
  131. package/dist/render/cull_visitor.js.map +1 -1
  132. package/dist/render/depthpass.js +36 -2
  133. package/dist/render/depthpass.js.map +1 -1
  134. package/dist/render/drawable_mixin.js +26 -1
  135. package/dist/render/drawable_mixin.js.map +1 -1
  136. package/dist/render/dualdepthpeeling_oit.js +3 -2
  137. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  138. package/dist/render/envlight.js +1 -1
  139. package/dist/render/envlight.js.map +1 -1
  140. package/dist/render/fbm_wavegenerator.js +6 -3
  141. package/dist/render/fbm_wavegenerator.js.map +1 -1
  142. package/dist/render/fft_wavegenerator.js +57 -15
  143. package/dist/render/fft_wavegenerator.js.map +1 -1
  144. package/dist/render/gerstner_wavegenerator.js +130 -20
  145. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  146. package/dist/render/globalbindgroup_allocator.js +3 -0
  147. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  148. package/dist/render/hzb.js +80 -22
  149. package/dist/render/hzb.js.map +1 -1
  150. package/dist/render/lightpass.js +6 -3
  151. package/dist/render/lightpass.js.map +1 -1
  152. package/dist/render/oit.js +29 -0
  153. package/dist/render/oit.js.map +1 -0
  154. package/dist/render/render_queue.js +39 -0
  155. package/dist/render/render_queue.js.map +1 -1
  156. package/dist/render/renderer.js +4 -0
  157. package/dist/render/renderer.js.map +1 -1
  158. package/dist/render/rendergraph/blackboard.js +1 -0
  159. package/dist/render/rendergraph/blackboard.js.map +1 -1
  160. package/dist/render/rendergraph/device_pool_allocator.js.map +1 -1
  161. package/dist/render/rendergraph/executor.js +2 -0
  162. package/dist/render/rendergraph/executor.js.map +1 -1
  163. package/dist/render/rendergraph/forward_plus_builder.js +379 -10
  164. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  165. package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
  166. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
  167. package/dist/render/rendergraph/history_resources.js +8 -1
  168. package/dist/render/rendergraph/history_resources.js.map +1 -1
  169. package/dist/render/rendergraph/rendergraph.js.map +1 -1
  170. package/dist/render/rendergraph/texture_affinity_cache.js +1 -1
  171. package/dist/render/rendergraph/texture_affinity_cache.js.map +1 -1
  172. package/dist/render/rendergraph/types.js.map +1 -1
  173. package/dist/render/shadow_mask_pass.js +73 -8
  174. package/dist/render/shadow_mask_pass.js.map +1 -1
  175. package/dist/render/sky.js +166 -126
  176. package/dist/render/sky.js.map +1 -1
  177. package/dist/render/underwater.js +624 -0
  178. package/dist/render/underwater.js.map +1 -0
  179. package/dist/render/water_caustics.js +1380 -0
  180. package/dist/render/water_caustics.js.map +1 -0
  181. package/dist/render/weightedblended_oit.js +3 -2
  182. package/dist/render/weightedblended_oit.js.map +1 -1
  183. package/dist/scene/basesprite.js +8 -0
  184. package/dist/scene/basesprite.js.map +1 -1
  185. package/dist/scene/batchgroup.js +3 -0
  186. package/dist/scene/batchgroup.js.map +1 -1
  187. package/dist/scene/environment.js +4 -1
  188. package/dist/scene/environment.js.map +1 -1
  189. package/dist/scene/hair.js +963 -0
  190. package/dist/scene/hair.js.map +1 -0
  191. package/dist/scene/light.js +5 -1
  192. package/dist/scene/light.js.map +1 -1
  193. package/dist/scene/mesh.js +481 -47
  194. package/dist/scene/mesh.js.map +1 -1
  195. package/dist/scene/meshdrawable.js +6 -0
  196. package/dist/scene/meshdrawable.js.map +1 -1
  197. package/dist/scene/msdftext.js +3 -0
  198. package/dist/scene/msdftext.js.map +1 -1
  199. package/dist/scene/msdftextsprite.js +3 -0
  200. package/dist/scene/msdftextsprite.js.map +1 -1
  201. package/dist/scene/particlesys.js +6 -0
  202. package/dist/scene/particlesys.js.map +1 -1
  203. package/dist/scene/scene.js +3 -0
  204. package/dist/scene/scene.js.map +1 -1
  205. package/dist/scene/scene_node.js +6 -1
  206. package/dist/scene/scene_node.js.map +1 -1
  207. package/dist/scene/terrain-cm/grass.js +3 -0
  208. package/dist/scene/terrain-cm/grass.js.map +1 -1
  209. package/dist/scene/terrain-cm/grassmaterial.js +3 -0
  210. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  211. package/dist/scene/terrain-cm/terrain-cm.js +6 -0
  212. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  213. package/dist/scene/terrain-cm/texture_cache.js +309 -0
  214. package/dist/scene/terrain-cm/texture_cache.js.map +1 -0
  215. package/dist/scene/water.js +546 -4
  216. package/dist/scene/water.js.map +1 -1
  217. package/dist/shaders/atmosphere.js.map +1 -1
  218. package/dist/shaders/diffusion.js +54 -0
  219. package/dist/shaders/diffusion.js.map +1 -0
  220. package/dist/shaders/shadow.js +33 -21
  221. package/dist/shaders/shadow.js.map +1 -1
  222. package/dist/shaders/temporal.js +71 -33
  223. package/dist/shaders/temporal.js.map +1 -1
  224. package/dist/shaders/water.js +22 -19
  225. package/dist/shaders/water.js.map +1 -1
  226. package/dist/shaders/water_medium.js +56 -0
  227. package/dist/shaders/water_medium.js.map +1 -0
  228. package/dist/shadow/dom.js +546 -0
  229. package/dist/shadow/dom.js.map +1 -0
  230. package/dist/shadow/pcf_opt.js +3 -5
  231. package/dist/shadow/pcf_opt.js.map +1 -1
  232. package/dist/shadow/pcf_pd.js +1 -1
  233. package/dist/shadow/pcf_pd.js.map +1 -1
  234. package/dist/shadow/receiver_bias.js +41 -0
  235. package/dist/shadow/receiver_bias.js.map +1 -0
  236. package/dist/shadow/shader.js +20 -60
  237. package/dist/shadow/shader.js.map +1 -1
  238. package/dist/shadow/shadow_impl.js +89 -0
  239. package/dist/shadow/shadow_impl.js.map +1 -1
  240. package/dist/shadow/shadow_region.js +1 -1
  241. package/dist/shadow/shadow_region.js.map +1 -1
  242. package/dist/shadow/shadowmapper.js +150 -37
  243. package/dist/shadow/shadowmapper.js.map +1 -1
  244. package/dist/shapes/shape.js +11 -2
  245. package/dist/shapes/shape.js.map +1 -1
  246. package/dist/shapes/sphere.js +50 -9
  247. package/dist/shapes/sphere.js.map +1 -1
  248. package/dist/utility/blueprint/common/constants.js +112 -2
  249. package/dist/utility/blueprint/common/constants.js.map +1 -1
  250. package/dist/utility/blueprint/material/func.js +142 -49
  251. package/dist/utility/blueprint/material/func.js.map +1 -1
  252. package/dist/utility/blueprint/material/ir.js +490 -25
  253. package/dist/utility/blueprint/material/ir.js.map +1 -1
  254. package/dist/utility/blueprint/material/texture.js +898 -4
  255. package/dist/utility/blueprint/material/texture.js.map +1 -1
  256. package/dist/utility/serialization/manager.js +434 -101
  257. package/dist/utility/serialization/manager.js.map +1 -1
  258. package/dist/utility/serialization/scene/animation.js +401 -5
  259. package/dist/utility/serialization/scene/animation.js.map +1 -1
  260. package/dist/utility/serialization/scene/batch.js +4 -0
  261. package/dist/utility/serialization/scene/batch.js.map +1 -1
  262. package/dist/utility/serialization/scene/camera.js +186 -26
  263. package/dist/utility/serialization/scene/camera.js.map +1 -1
  264. package/dist/utility/serialization/scene/common.js +26 -5
  265. package/dist/utility/serialization/scene/common.js.map +1 -1
  266. package/dist/utility/serialization/scene/hair.js +1141 -0
  267. package/dist/utility/serialization/scene/hair.js.map +1 -0
  268. package/dist/utility/serialization/scene/light.js +84 -4
  269. package/dist/utility/serialization/scene/light.js.map +1 -1
  270. package/dist/utility/serialization/scene/material.js +1867 -166
  271. package/dist/utility/serialization/scene/material.js.map +1 -1
  272. package/dist/utility/serialization/scene/mesh.js +231 -14
  273. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  274. package/dist/utility/serialization/scene/node.js +141 -7
  275. package/dist/utility/serialization/scene/node.js.map +1 -1
  276. package/dist/utility/serialization/scene/particle.js +4 -0
  277. package/dist/utility/serialization/scene/particle.js.map +1 -1
  278. package/dist/utility/serialization/scene/primitive.js +18 -0
  279. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  280. package/dist/utility/serialization/scene/sprite.js +4 -0
  281. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  282. package/dist/utility/serialization/scene/terrain.js +4 -0
  283. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  284. package/dist/utility/serialization/scene/text.js +4 -0
  285. package/dist/utility/serialization/scene/text.js.map +1 -1
  286. package/dist/utility/serialization/scene/water.js +1105 -21
  287. package/dist/utility/serialization/scene/water.js.map +1 -1
  288. package/dist/utility/serialization/types.js.map +1 -1
  289. package/dist/utility/shprojector.js +9 -8
  290. package/dist/utility/shprojector.js.map +1 -1
  291. package/dist/values.js +49 -2
  292. package/dist/values.js.map +1 -1
  293. package/package.json +3 -3
  294. package/dist/render/rendergraph/frame_graph_context.js +0 -41
  295. package/dist/render/rendergraph/frame_graph_context.js.map +0 -1
  296. package/dist/shaders/ssgi.js +0 -63
  297. package/dist/shaders/ssgi.js.map +0 -1
  298. package/dist/shaders/ssgi_reprojection.js +0 -118
  299. package/dist/shaders/ssgi_reprojection.js.map +0 -1
@@ -18,7 +18,7 @@ import '../animation/joint_dynamics/collision.js';
18
18
  import '../animation/joint_dynamics/solver.js';
19
19
  import { createTransformAccess, JointDynamicsSystem } from '../animation/joint_dynamics/joint_dynamics_system.js';
20
20
  import { JointDynamicsModifier } from '../animation/joint_dynamics_modifier.js';
21
- import { MAX_MORPH_TARGETS, MAX_MORPH_ATTRIBUTES } from '../values.js';
21
+ import { MAX_MORPH_ATTRIBUTES, MAX_MORPH_TARGETS, getMorphTargetLimit, MAX_SKIN_INFLUENCES } from '../values.js';
22
22
  import { Primitive } from '../render/primitive.js';
23
23
  import { UnlitMaterial } from '../material/unlit.js';
24
24
  import { PBRSpecularGlossinessMaterial } from '../material/pbrsg.js';
@@ -37,6 +37,30 @@ import { MToonMaterial } from '../material/mtoon.js';
37
37
  this.name = name;
38
38
  }
39
39
  }
40
+ function normalizeAssetNodePath(path) {
41
+ return path.replace(/\\/g, '/').split('/').filter(Boolean).join('/');
42
+ }
43
+ function getSkinBindingKey(rig, joints, inverseBindMatrices) {
44
+ const matrixKey = inverseBindMatrices.map((matrix)=>{
45
+ const elements = [];
46
+ for(let i = 0; i < 16; i++){
47
+ elements.push(matrix[i]);
48
+ }
49
+ return elements.join(',');
50
+ }).join('|');
51
+ return `${rig.persistentId}|${joints.map((joint)=>joint.persistentId).join('|')}|${matrixKey}`;
52
+ }
53
+ function getAssetNodePath(node) {
54
+ const segments = [];
55
+ let current = node;
56
+ while(current){
57
+ if (current.name) {
58
+ segments.push(current.name);
59
+ }
60
+ current = current.parent;
61
+ }
62
+ return normalizeAssetNodePath(segments.reverse().join('/'));
63
+ }
40
64
  /**
41
65
  * Heirarchical node interface for model loading
42
66
  * @public
@@ -184,6 +208,7 @@ import { MToonMaterial } from '../material/mtoon.js';
184
208
  /** Joints of the skeleton */ joints;
185
209
  /** Inverse of the binding matrices of the joints */ inverseBindMatrices;
186
210
  /** Binding pose matrices of the joints */ bindPose;
211
+ /** Optional humanoid retarget reference pose, ordered like `joints`. */ retargetPose;
187
212
  /** Explicit humanoid joint mapping, when supplied by the source asset. */ humanoidJointMapping;
188
213
  /**
189
214
  * Creates an instance of AssetSkeleton
@@ -195,6 +220,7 @@ import { MToonMaterial } from '../material/mtoon.js';
195
220
  this.joints = [];
196
221
  this.inverseBindMatrices = [];
197
222
  this.bindPose = [];
223
+ this.retargetPose = null;
198
224
  this.humanoidJointMapping = null;
199
225
  }
200
226
  /**
@@ -665,18 +691,25 @@ import { MToonMaterial } from '../material/mtoon.js';
665
691
  ASSERT(!!ext, `Unknown image mime type: ${mimeType}`);
666
692
  const baseName = this.sanitizeResourceName(this.getImageBaseName(img, i, destName), `${destName}_texture_${i}`);
667
693
  const path = await this.tryReuseExactResourcePath(dstVFS, destPath, baseName, ext, usedPaths, `${destName}_texture_${i}`) ?? this.consumeReusableResourcePath(reusableResourcePools, baseName, ext, usedPaths) ?? await this.createUniqueResourcePath(dstVFS, destPath, baseName, ext, usedPaths, `${destName}_texture_${i}`);
668
- if (img.uri) {
669
- img.data = new Uint8Array(await srcVFS.readFile(img.uri, {
670
- encoding: 'binary'
671
- }));
694
+ try {
695
+ if (img.uri) {
696
+ img.data = new Uint8Array(await srcVFS.readFile(img.uri, {
697
+ encoding: 'binary'
698
+ }));
699
+ }
700
+ await dstVFS.writeFile(path, img.data.buffer.slice(img.data.byteOffset, img.data.byteOffset + img.data.byteLength), {
701
+ encoding: 'binary',
702
+ create: true
703
+ });
704
+ img.uri = path;
705
+ img.data = undefined;
706
+ img.mimeType = '';
707
+ } catch (err) {
708
+ console.warn(`Skip missing or unreadable texture during import: ${img.uri || img.name || `${destName}_texture_${i}`}: ${String(err)}`);
709
+ img.uri = undefined;
710
+ img.data = undefined;
711
+ img.mimeType = '';
672
712
  }
673
- await dstVFS.writeFile(path, img.data.buffer.slice(img.data.byteOffset, img.data.byteOffset + img.data.byteLength), {
674
- encoding: 'binary',
675
- create: true
676
- });
677
- img.uri = path;
678
- img.data = undefined;
679
- img.mimeType = '';
680
713
  }
681
714
  }
682
715
  const materialKeys = Object.keys(this._materialList);
@@ -900,6 +933,7 @@ import { MToonMaterial } from '../material/mtoon.js';
900
933
  }
901
934
  }
902
935
  const rigMap = new Map();
936
+ const bindingMap = new Map();
903
937
  for (const v of skeletonMeshMap){
904
938
  const sk = v[0];
905
939
  const joints = sk.joints.map((val)=>{
@@ -916,14 +950,22 @@ import { MToonMaterial } from '../material/mtoon.js';
916
950
  const humanoidJointMapping = this.remapHumanoidJointMapping(sk.humanoidJointMapping, nodeMap);
917
951
  rig = new SkeletonRig(joints, sk.bindPose, humanoidJointMapping ? {
918
952
  rootJoint,
919
- humanoidJointMapping
953
+ humanoidJointMapping,
954
+ retargetPose: sk.retargetPose
920
955
  } : {
921
- rootJoint
956
+ rootJoint,
957
+ retargetPose: sk.retargetPose
922
958
  });
923
959
  rigMap.set(rigKey, rig);
924
960
  group.animationSet.rigs.push(new DRef(rig));
925
961
  }
926
- const binding = new SkinBinding(rig, sk.inverseBindMatrices, joints);
962
+ const bindingKey = getSkinBindingKey(rig, joints, sk.inverseBindMatrices);
963
+ let binding = bindingMap.get(bindingKey);
964
+ if (!binding) {
965
+ binding = new SkinBinding(rig, sk.inverseBindMatrices, joints);
966
+ bindingMap.set(bindingKey, binding);
967
+ group.animationSet.skeletons.push(new DRef(binding));
968
+ }
927
969
  const nodes = skeletonMeshMap.get(sk);
928
970
  if (nodes) {
929
971
  if (!nodes.binding) {
@@ -933,14 +975,14 @@ import { MToonMaterial } from '../material/mtoon.js';
933
975
  const v = {
934
976
  positions: nodes.bounding[i].rawPositions,
935
977
  blendIndices: nodes.bounding[i].rawBlendIndices,
936
- weights: nodes.bounding[i].rawJointWeights
978
+ weights: nodes.bounding[i].rawJointWeights,
979
+ influenceCount: nodes.bounding[i].rawSkinInfluenceCount ?? 4
937
980
  };
938
981
  mesh.setSkinnedBoundingInfo(nodes.binding.getBoundingInfo(v));
939
982
  mesh.skeletonName = nodes.binding.persistentId;
940
983
  }
941
984
  }
942
985
  }
943
- group.animationSet.skeletons.push(new DRef(nodes.binding));
944
986
  }
945
987
  }
946
988
  if (saveAnimations) {
@@ -979,8 +1021,9 @@ import { MToonMaterial } from '../material/mtoon.js';
979
1021
  } else if (track.type === 'weights') {
980
1022
  for (const m of track.node.mesh.subMeshes){
981
1023
  const mesh = meshMap.get(m);
982
- if (track.interpolator.stride > MAX_MORPH_TARGETS) {
983
- console.error(`Morph target too large: ${track.interpolator.stride}, the maximum is ${MAX_MORPH_TARGETS}`);
1024
+ const morphTargetLimit = getMorphTargetLimit();
1025
+ if (track.interpolator.stride > morphTargetLimit) {
1026
+ console.error(`Morph target too large: ${track.interpolator.stride}, the project limit is ${morphTargetLimit}`);
984
1027
  } else {
985
1028
  const morphTrack = new MorphTargetTrack(track.interpolator, track.defaultMorphWeights, m.targetBox, mesh.getBoundingVolume().toAABB(), true);
986
1029
  animation.addTrack(mesh, morphTrack);
@@ -1214,6 +1257,7 @@ import { MToonMaterial } from '../material/mtoon.js';
1214
1257
  node.rotation.set(assetNode.rotation);
1215
1258
  node.scale.set(assetNode.scaling);
1216
1259
  if (saveMeshes && assetNode.mesh) {
1260
+ const sourceMorphReferenceAssetPath = this._preprocessOptions?.sourceMorphReferenceAssetPath ?? null;
1217
1261
  const meshData = assetNode.mesh;
1218
1262
  const skeleton = saveSkeletons ? assetNode.skeleton : null;
1219
1263
  for (const subMesh of meshData.subMeshes){
@@ -1229,7 +1273,7 @@ import { MToonMaterial } from '../material/mtoon.js';
1229
1273
  meshNode.position = instance.t;
1230
1274
  meshNode.scale = instance.s;
1231
1275
  meshNode.rotation = instance.r;
1232
- meshNode.name = subMesh.name;
1276
+ meshNode.name = subMesh.primitive?.name?.trim() || subMesh.name;
1233
1277
  meshNode.clipTestEnabled = true;
1234
1278
  meshNode.showState = 'inherit';
1235
1279
  if (!this._primitiveMap.get(subMesh.primitive)) {
@@ -1250,7 +1294,20 @@ import { MToonMaterial } from '../material/mtoon.js';
1250
1294
  mesh: meshData,
1251
1295
  subMesh
1252
1296
  });
1253
- processMorphData(subMesh, meshNode, assetNode.weights ?? meshData.morphWeights, meshData.morphNames);
1297
+ const morphSource = sourceMorphReferenceAssetPath && subMesh.numTargets > 0 ? (()=>{
1298
+ const nodePath = getAssetNodePath(assetNode);
1299
+ const subMeshName = subMesh.name;
1300
+ if (!nodePath || !subMeshName) {
1301
+ return null;
1302
+ }
1303
+ return {
1304
+ sourcePath: sourceMorphReferenceAssetPath,
1305
+ nodePath,
1306
+ subMeshName
1307
+ };
1308
+ })() : null;
1309
+ processMorphData(subMesh, meshNode, assetNode.weights ?? meshData.morphWeights, meshData.morphNames, morphSource);
1310
+ applyMeshSkinInfluenceData(subMesh, meshNode);
1254
1311
  if (skeleton) {
1255
1312
  if (!skeletonMeshMap.has(skeleton)) {
1256
1313
  skeletonMeshMap.set(skeleton, {
@@ -1762,30 +1819,28 @@ import { MToonMaterial } from '../material/mtoon.js';
1762
1819
  return null;
1763
1820
  }
1764
1821
  }
1765
- /** @internal */ function processMorphData(subMesh, mesh, morphWeights, morphNames) {
1766
- const device = getDevice();
1822
+ function applyMeshMorphMetadata(subMesh, mesh, morphWeights, morphNames) {
1767
1823
  const numTargets = subMesh.numTargets;
1768
- if (numTargets === 0) {
1824
+ if (numTargets === 0 || !subMesh.targets || !subMesh.targetBox) {
1769
1825
  return;
1770
1826
  }
1827
+ const supportedNumTargets = Math.min(numTargets, getMorphTargetLimit());
1828
+ if (supportedNumTargets !== numTargets) {
1829
+ console.warn(`Morph target count truncated from ${numTargets} to ${supportedNumTargets} for mesh "${subMesh.name ?? mesh.name ?? ''}"`);
1830
+ }
1771
1831
  const attributes = Object.getOwnPropertyNames(subMesh.targets);
1772
1832
  const positionInfo = subMesh.primitive.vertices['position'];
1773
1833
  const numVertices = positionInfo ? positionInfo.data.length / getVertexFormatComponentCount(positionInfo.format) >> 0 : 0;
1774
1834
  const weightsAndOffsets = new Float32Array(4 + MAX_MORPH_TARGETS + MAX_MORPH_ATTRIBUTES);
1775
- for(let i = 0; i < numTargets; i++){
1835
+ for(let i = 0; i < supportedNumTargets; i++){
1776
1836
  weightsAndOffsets[4 + i] = morphWeights?.[i] ?? 0;
1777
1837
  }
1778
1838
  const textureSize = Math.ceil(Math.sqrt(numVertices * attributes.length * numTargets));
1779
- if (textureSize > device.getDeviceCaps().textureCaps.maxTextureSize) {
1780
- // TODO: reduce morph attributes
1781
- throw new Error(`Morph target data too large`);
1782
- }
1783
1839
  weightsAndOffsets[0] = textureSize;
1784
1840
  weightsAndOffsets[1] = textureSize;
1785
1841
  weightsAndOffsets[2] = numVertices;
1786
- weightsAndOffsets[3] = numTargets;
1842
+ weightsAndOffsets[3] = supportedNumTargets;
1787
1843
  let offset = 0;
1788
- const textureData = new Float32Array(textureSize * textureSize * 4);
1789
1844
  for(let attrib = 0; attrib < MAX_MORPH_ATTRIBUTES; attrib++){
1790
1845
  const index = attributes.indexOf(String(attrib));
1791
1846
  if (index < 0) {
@@ -1798,64 +1853,124 @@ import { MToonMaterial } from '../material/mtoon.js';
1798
1853
  console.error(`Invalid morph target data`);
1799
1854
  return;
1800
1855
  }
1801
- for(let t = 0; t < numTargets; t++){
1802
- const data = info.data[t];
1803
- for(let i = 0; i < numVertices; i++){
1804
- for(let j = 0; j < 4; j++){
1805
- textureData[offset++] = j < info.numComponents ? data[i * info.numComponents + j] : 1;
1806
- }
1807
- }
1808
- }
1856
+ offset += numVertices * 4 * numTargets;
1809
1857
  }
1810
- const morphBoundingBox = new BoundingBox();
1811
- calculateMorphBoundingBox(morphBoundingBox, subMesh.targetBox, weightsAndOffsets.subarray(4, 4 + MAX_MORPH_TARGETS), numTargets);
1812
- const meshAABB = mesh.getBoundingVolume().toAABB();
1813
- morphBoundingBox.minPoint.addBy(meshAABB.minPoint);
1814
- morphBoundingBox.maxPoint.addBy(meshAABB.maxPoint);
1815
1858
  const names = {};
1816
- for(let i = 0; i < numTargets; i++){
1859
+ for(let i = 0; i < supportedNumTargets; i++){
1817
1860
  const name = morphNames?.[i] ?? `Target${i}`;
1818
1861
  names[name] = i;
1819
1862
  }
1820
- mesh.setMorphData({
1821
- width: textureSize,
1822
- height: textureSize,
1823
- data: textureData
1824
- });
1825
1863
  mesh.setMorphInfo({
1826
1864
  data: weightsAndOffsets,
1827
1865
  names
1828
1866
  });
1829
1867
  mesh.setMorphBoundingInfo({
1830
- targetBoxes: subMesh.targetBox,
1831
- originBox: new BoundingBox(meshAABB)
1868
+ targetBoxes: subMesh.targetBox.slice(0, supportedNumTargets),
1869
+ originBox: new BoundingBox(mesh.getBoundingVolume().toAABB())
1832
1870
  });
1833
- mesh.setAnimatedBoundingBox(morphBoundingBox);
1871
+ }
1872
+ function createMorphSourceDataFromSubMesh(subMesh) {
1873
+ const numTargets = Math.min(subMesh.numTargets, getMorphTargetLimit());
1874
+ if (numTargets === 0 || !subMesh.targets) {
1875
+ return null;
1876
+ }
1877
+ const positionInfo = subMesh.primitive.vertices['position'];
1878
+ const numVertices = positionInfo ? positionInfo.data.length / getVertexFormatComponentCount(positionInfo.format) >> 0 : 0;
1879
+ const targets = {};
1880
+ for (const [attribKey, info] of Object.entries(subMesh.targets)){
1881
+ const attrib = Number(attribKey);
1882
+ if (!info || !Number.isInteger(attrib) || attrib < 0) {
1883
+ continue;
1884
+ }
1885
+ if (info.data.length < numTargets) {
1886
+ console.error(`Invalid morph target data`);
1887
+ return null;
1888
+ }
1889
+ targets[attrib] = {
1890
+ numComponents: info.numComponents,
1891
+ data: info.data.slice(0, numTargets),
1892
+ indices: info.indices?.slice(0, numTargets)
1893
+ };
1894
+ }
1895
+ return {
1896
+ numTargets,
1897
+ numVertices,
1898
+ targets
1899
+ };
1900
+ }
1901
+ function applyMeshMorphData(subMesh, mesh) {
1902
+ const sourceData = createMorphSourceDataFromSubMesh(subMesh);
1903
+ if (!sourceData) {
1904
+ mesh.setMorphData(null);
1905
+ mesh.setMorphSourceData(null);
1906
+ return;
1907
+ }
1908
+ mesh.setMorphSourceData(sourceData);
1909
+ }
1910
+ function createSkinInfluenceDataFromSubMesh(subMesh) {
1911
+ // Preserve the influence count captured at import time so runtime settings do not silently
1912
+ // degrade already-imported assets when a project lowers the import limit later on.
1913
+ const influenceCount = Math.max(0, Math.min(subMesh.rawSkinInfluenceCount ?? 4, MAX_SKIN_INFLUENCES, Math.floor((subMesh.rawJointWeights?.length ?? 0) / Math.max(1, (subMesh.rawPositions?.length ?? 0) / 3))));
1914
+ if (influenceCount <= 4 || !subMesh.rawPositions || !subMesh.rawBlendIndices || !subMesh.rawJointWeights || subMesh.rawPositions.length < 3) {
1915
+ return null;
1916
+ }
1917
+ const numVertices = Math.floor(subMesh.rawPositions.length / 3);
1918
+ if (numVertices <= 0) {
1919
+ return null;
1920
+ }
1921
+ const extraInfluenceCount = influenceCount - 4;
1922
+ const pairCount = Math.ceil(extraInfluenceCount / 2);
1923
+ const textureSize = Math.ceil(Math.sqrt(numVertices * pairCount));
1924
+ const textureData = new Float32Array(textureSize * textureSize * 4);
1925
+ for(let vertexIndex = 0; vertexIndex < numVertices; vertexIndex++){
1926
+ const baseOffset = vertexIndex * influenceCount + 4;
1927
+ for(let pairIndex = 0; pairIndex < pairCount; pairIndex++){
1928
+ const influenceIndex = 4 + pairIndex * 2;
1929
+ const sourceIndex = baseOffset + pairIndex * 2;
1930
+ const texelOffset = (vertexIndex * pairCount + pairIndex) * 4;
1931
+ textureData[texelOffset] = Number(subMesh.rawBlendIndices[sourceIndex] ?? 0);
1932
+ textureData[texelOffset + 1] = Number(subMesh.rawJointWeights[sourceIndex] ?? 0);
1933
+ // Odd influence counts leave the second half of the final texel empty.
1934
+ // Do not read it from the next vertex's first influence.
1935
+ if (influenceIndex + 1 < influenceCount) {
1936
+ textureData[texelOffset + 2] = Number(subMesh.rawBlendIndices[sourceIndex + 1] ?? 0);
1937
+ textureData[texelOffset + 3] = Number(subMesh.rawJointWeights[sourceIndex + 1] ?? 0);
1938
+ }
1939
+ }
1940
+ }
1941
+ return {
1942
+ width: textureSize,
1943
+ height: textureSize,
1944
+ influenceCount,
1945
+ data: textureData
1946
+ };
1947
+ }
1948
+ function applyMeshSkinInfluenceData(subMesh, mesh) {
1949
+ mesh.setSkinInfluenceData(createSkinInfluenceDataFromSubMesh(subMesh));
1950
+ }
1951
+ /** @internal */ function processMorphData(subMesh, mesh, morphWeights, morphNames, morphSource) {
1952
+ if (subMesh.numTargets === 0) {
1953
+ return;
1954
+ }
1955
+ applyMeshMorphMetadata(subMesh, mesh, morphWeights, morphNames);
1956
+ mesh.setMorphSource(morphSource ?? null);
1957
+ if (morphSource) {
1958
+ mesh.setMorphSourceData(null);
1959
+ mesh.setMorphData(null);
1960
+ } else {
1961
+ applyMeshMorphData(subMesh, mesh);
1962
+ }
1834
1963
  }
1835
1964
  /** @internal */ function getAssetMeshMorphTargetCount(mesh) {
1836
1965
  let count = 0;
1837
1966
  for (const subMesh of mesh.subMeshes){
1838
1967
  count = Math.max(count, subMesh.numTargets);
1839
1968
  }
1840
- return count;
1969
+ return Math.min(count, getMorphTargetLimit());
1841
1970
  }
1842
1971
  /** @internal */ function getAssetMeshMorphTargetName(mesh, index) {
1843
1972
  return mesh.morphNames?.[index] ?? `Target${index}`;
1844
1973
  }
1845
- /** @internal */ function calculateMorphBoundingBox(morphBoundingBox, keyframeBoundingBox, weights, numTargets) {
1846
- morphBoundingBox.minPoint.setXYZ(0, 0, 0);
1847
- morphBoundingBox.maxPoint.setXYZ(0, 0, 0);
1848
- for(let i = 0; i < numTargets; i++){
1849
- const weight = weights[i];
1850
- const keyframeBox = keyframeBoundingBox[i];
1851
- morphBoundingBox.minPoint.x += keyframeBox.minPoint.x * weight;
1852
- morphBoundingBox.minPoint.y += keyframeBox.minPoint.y * weight;
1853
- morphBoundingBox.minPoint.z += keyframeBox.minPoint.z * weight;
1854
- morphBoundingBox.maxPoint.x += keyframeBox.maxPoint.x * weight;
1855
- morphBoundingBox.maxPoint.y += keyframeBox.maxPoint.y * weight;
1856
- morphBoundingBox.maxPoint.z += keyframeBox.maxPoint.z * weight;
1857
- }
1858
- }
1859
1974
 
1860
- export { AssetHierarchyNode, AssetScene, AssetSkeleton, NamedObject, SharedModel };
1975
+ export { AssetHierarchyNode, AssetScene, AssetSkeleton, NamedObject, SharedModel, applyMeshMorphData, applyMeshMorphMetadata, applyMeshSkinInfluenceData, createMorphSourceDataFromSubMesh };
1861
1976
  //# sourceMappingURL=model.js.map