@zephyr3d/scene 0.9.26 → 0.10.0

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 (506) hide show
  1. package/README.md +60 -27
  2. package/dist/animation/animation_bank.js +634 -0
  3. package/dist/animation/animation_bank.js.map +1 -0
  4. package/dist/animation/animation_bank_gpu.js +256 -0
  5. package/dist/animation/animation_bank_gpu.js.map +1 -0
  6. package/dist/animation/animationset.js +146 -30
  7. package/dist/animation/animationset.js.map +1 -1
  8. package/dist/animation/cloth/gpu_cloth_component.js +406 -0
  9. package/dist/animation/cloth/gpu_cloth_component.js.map +1 -0
  10. package/dist/animation/cloth/gpu_cloth_system.js +332 -202
  11. package/dist/animation/cloth/gpu_cloth_system.js.map +1 -1
  12. package/dist/animation/gpu_animation_driver.js +289 -0
  13. package/dist/animation/gpu_animation_driver.js.map +1 -0
  14. package/dist/animation/joint_dynamics/collision.js +112 -1
  15. package/dist/animation/joint_dynamics/collision.js.map +1 -1
  16. package/dist/animation/joint_dynamics/controller.js +6 -0
  17. package/dist/animation/joint_dynamics/controller.js.map +1 -1
  18. package/dist/animation/joint_dynamics/joint_dynamics_system.js +11 -0
  19. package/dist/animation/joint_dynamics/joint_dynamics_system.js.map +1 -1
  20. package/dist/animation/joint_dynamics/solver.js +50 -12
  21. package/dist/animation/joint_dynamics/solver.js.map +1 -1
  22. package/dist/animation/joint_dynamics/types.js.map +1 -1
  23. package/dist/animation/skeleton.js +300 -56
  24. package/dist/animation/skeleton.js.map +1 -1
  25. package/dist/animation/skin_palette_atlas.js +252 -0
  26. package/dist/animation/skin_palette_atlas.js.map +1 -0
  27. package/dist/animation/spring/multi_chain_spring_system.js +298 -38
  28. package/dist/animation/spring/multi_chain_spring_system.js.map +1 -1
  29. package/dist/animation/spring/spring_chain.js +2 -0
  30. package/dist/animation/spring/spring_chain.js.map +1 -1
  31. package/dist/animation/spring/spring_collider.js +159 -21
  32. package/dist/animation/spring/spring_collider.js.map +1 -1
  33. package/dist/animation/spring/spring_particle.js +1 -0
  34. package/dist/animation/spring/spring_particle.js.map +1 -1
  35. package/dist/animation/spring/spring_solver.js +173 -0
  36. package/dist/animation/spring/spring_solver.js.map +1 -0
  37. package/dist/animation/spring/spring_system.js +249 -24
  38. package/dist/animation/spring/spring_system.js.map +1 -1
  39. package/dist/animation/spring_modifier.js +32 -1
  40. package/dist/animation/spring_modifier.js.map +1 -1
  41. package/dist/app/app.js +26 -0
  42. package/dist/app/app.js.map +1 -1
  43. package/dist/app/engine.js +86 -15
  44. package/dist/app/engine.js.map +1 -1
  45. package/dist/app/gamepad.js +191 -0
  46. package/dist/app/gamepad.js.map +1 -0
  47. package/dist/app/inputactions.js +271 -0
  48. package/dist/app/inputactions.js.map +1 -0
  49. package/dist/app/inputmgr.js +331 -22
  50. package/dist/app/inputmgr.js.map +1 -1
  51. package/dist/app/loading.js +138 -0
  52. package/dist/app/loading.js.map +1 -0
  53. package/dist/app/pipelinecache.js +209 -0
  54. package/dist/app/pipelinecache.js.map +1 -0
  55. package/dist/app/runtimescript.js +25 -0
  56. package/dist/app/runtimescript.js.map +1 -1
  57. package/dist/app/scriptingsystem.js +54 -0
  58. package/dist/app/scriptingsystem.js.map +1 -1
  59. package/dist/app/scriptregistry.js +7 -2
  60. package/dist/app/scriptregistry.js.map +1 -1
  61. package/dist/asset/asset_manifest.js +59 -0
  62. package/dist/asset/asset_manifest.js.map +1 -0
  63. package/dist/asset/asset_preload.js +258 -0
  64. package/dist/asset/asset_preload.js.map +1 -0
  65. package/dist/asset/assetmanager.js +117 -65
  66. package/dist/asset/assetmanager.js.map +1 -1
  67. package/dist/asset/loaders/ktx2/basis/LICENSE +201 -0
  68. package/dist/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  69. package/dist/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  70. package/dist/asset/loaders/ktx2/basis_location.js +17 -0
  71. package/dist/asset/loaders/ktx2/basis_location.js.map +1 -0
  72. package/dist/asset/loaders/ktx2/ktx2_loader.js +88 -0
  73. package/dist/asset/loaders/ktx2/ktx2_loader.js.map +1 -0
  74. package/dist/asset/loaders/ktx2/ktx2_targets.js +118 -0
  75. package/dist/asset/loaders/ktx2/ktx2_targets.js.map +1 -0
  76. package/dist/asset/loaders/ktx2/transcoder_pool.js +259 -0
  77. package/dist/asset/loaders/ktx2/transcoder_pool.js.map +1 -0
  78. package/dist/asset/mesh_lod_builder.js +104 -0
  79. package/dist/asset/mesh_lod_builder.js.map +1 -0
  80. package/dist/asset/mesh_settings.js +111 -0
  81. package/dist/asset/mesh_settings.js.map +1 -0
  82. package/dist/asset/meshopt_decoder.js +18 -0
  83. package/dist/asset/meshopt_decoder.js.map +1 -0
  84. package/dist/asset/meshopt_simplifier.js +26 -0
  85. package/dist/asset/meshopt_simplifier.js.map +1 -0
  86. package/dist/asset/model.js +177 -3
  87. package/dist/asset/model.js.map +1 -1
  88. package/dist/asset/texture_settings.js +231 -0
  89. package/dist/asset/texture_settings.js.map +1 -0
  90. package/dist/asset/zmsh_binary.js +131 -0
  91. package/dist/asset/zmsh_binary.js.map +1 -0
  92. package/dist/asset/zsdf_binary.js +111 -0
  93. package/dist/asset/zsdf_binary.js.map +1 -0
  94. package/dist/blitter/bilateralblur.js +1 -2
  95. package/dist/blitter/bilateralblur.js.map +1 -1
  96. package/dist/blitter/gaussianblur.js +1 -6
  97. package/dist/blitter/gaussianblur.js.map +1 -1
  98. package/dist/camera/base.js +31 -10
  99. package/dist/camera/base.js.map +1 -1
  100. package/dist/camera/camera.js +178 -200
  101. package/dist/camera/camera.js.map +1 -1
  102. package/dist/camera/follow.js +342 -0
  103. package/dist/camera/follow.js.map +1 -0
  104. package/dist/camera/fps.js +9 -7
  105. package/dist/camera/fps.js.map +1 -1
  106. package/dist/camera/orbit.js +46 -19
  107. package/dist/camera/orbit.js.map +1 -1
  108. package/dist/index.d.ts +30475 -19865
  109. package/dist/index.js +67 -12
  110. package/dist/index.js.map +1 -1
  111. package/dist/material/blinn.js +3 -0
  112. package/dist/material/blinn.js.map +1 -1
  113. package/dist/material/eye.js +1 -1
  114. package/dist/material/eye.js.map +1 -1
  115. package/dist/material/hair.js +2 -3
  116. package/dist/material/hair.js.map +1 -1
  117. package/dist/material/hairstrand.js +235 -235
  118. package/dist/material/hairstrand.js.map +1 -1
  119. package/dist/material/lambert.js +4 -1
  120. package/dist/material/lambert.js.map +1 -1
  121. package/dist/material/material.js +362 -300
  122. package/dist/material/material.js.map +1 -1
  123. package/dist/material/meshmaterial.js +118 -45
  124. package/dist/material/meshmaterial.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  126. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  128. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  130. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  132. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  133. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  134. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  135. package/dist/material/mixins/lit.js +223 -83
  136. package/dist/material/mixins/lit.js.map +1 -1
  137. package/dist/material/mixins/pbr/common.js +31 -206
  138. package/dist/material/mixins/pbr/common.js.map +1 -1
  139. package/dist/material/mtoon.js +1 -1
  140. package/dist/material/mtoon.js.map +1 -1
  141. package/dist/material/pbrmr.js +3 -0
  142. package/dist/material/pbrmr.js.map +1 -1
  143. package/dist/material/pbrsg.js +3 -0
  144. package/dist/material/pbrsg.js.map +1 -1
  145. package/dist/material/sdf_debug.js +78 -0
  146. package/dist/material/sdf_debug.js.map +1 -0
  147. package/dist/material/shader/helper.js +733 -190
  148. package/dist/material/shader/helper.js.map +1 -1
  149. package/dist/material/shader/terrain_blend.js +204 -43
  150. package/dist/material/shader/terrain_blend.js.map +1 -1
  151. package/dist/material/skin.js +331 -297
  152. package/dist/material/skin.js.map +1 -1
  153. package/dist/material/skinprofile.js +1058 -0
  154. package/dist/material/skinprofile.js.map +1 -0
  155. package/dist/material/sss.js +353 -0
  156. package/dist/material/sss.js.map +1 -0
  157. package/dist/material/sss_kernel.js +265 -0
  158. package/dist/material/sss_kernel.js.map +1 -0
  159. package/dist/material/sssprofile.js +879 -0
  160. package/dist/material/sssprofile.js.map +1 -0
  161. package/dist/material/subsurfaceprofile.js +4 -8
  162. package/dist/material/subsurfaceprofile.js.map +1 -1
  163. package/dist/material/terrain-cm.js +464 -188
  164. package/dist/material/terrain-cm.js.map +1 -1
  165. package/dist/material/unlit.js +3 -0
  166. package/dist/material/unlit.js.map +1 -1
  167. package/dist/material/water.js +2009 -201
  168. package/dist/material/water.js.map +1 -1
  169. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  172. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  173. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  174. package/dist/physics/character.js +226 -0
  175. package/dist/physics/character.js.map +1 -0
  176. package/dist/physics/collider.js +209 -0
  177. package/dist/physics/collider.js.map +1 -0
  178. package/dist/physics/events.js +79 -0
  179. package/dist/physics/events.js.map +1 -0
  180. package/dist/physics/joint.js +272 -0
  181. package/dist/physics/joint.js.map +1 -0
  182. package/dist/physics/node_physics.js +234 -0
  183. package/dist/physics/node_physics.js.map +1 -0
  184. package/dist/physics/part.js +91 -0
  185. package/dist/physics/part.js.map +1 -0
  186. package/dist/physics/rigid_body.js +379 -0
  187. package/dist/physics/rigid_body.js.map +1 -0
  188. package/dist/physics/vehicle.js +335 -0
  189. package/dist/physics/vehicle.js.map +1 -0
  190. package/dist/physics/world.js +25 -0
  191. package/dist/physics/world.js.map +1 -0
  192. package/dist/posteffect/bloom.js +49 -14
  193. package/dist/posteffect/bloom.js.map +1 -1
  194. package/dist/posteffect/motionblur.js +668 -63
  195. package/dist/posteffect/motionblur.js.map +1 -1
  196. package/dist/posteffect/posteffect.js +12 -1
  197. package/dist/posteffect/posteffect.js.map +1 -1
  198. package/dist/posteffect/postsss.js +572 -0
  199. package/dist/posteffect/postsss.js.map +1 -0
  200. package/dist/posteffect/sao.js +48 -50
  201. package/dist/posteffect/sao.js.map +1 -1
  202. package/dist/posteffect/skinsss.js +605 -355
  203. package/dist/posteffect/skinsss.js.map +1 -1
  204. package/dist/posteffect/ssgi.js +91 -162
  205. package/dist/posteffect/ssgi.js.map +1 -1
  206. package/dist/posteffect/ssr.js +3 -11
  207. package/dist/posteffect/ssr.js.map +1 -1
  208. package/dist/posteffect/sss.js +34 -15
  209. package/dist/posteffect/sss.js.map +1 -1
  210. package/dist/posteffect/taa.js +1 -0
  211. package/dist/posteffect/taa.js.map +1 -1
  212. package/dist/render/abuffer_oit.js +40 -39
  213. package/dist/render/abuffer_oit.js.map +1 -1
  214. package/dist/render/clipmap.js +328 -62
  215. package/dist/render/clipmap.js.map +1 -1
  216. package/dist/render/cluster_light.js +958 -224
  217. package/dist/render/cluster_light.js.map +1 -1
  218. package/dist/render/cull_visitor.js +26 -5
  219. package/dist/render/cull_visitor.js.map +1 -1
  220. package/dist/render/debug_views.js +37 -0
  221. package/dist/render/debug_views.js.map +1 -0
  222. package/dist/render/depthpass.js +5 -1
  223. package/dist/render/depthpass.js.map +1 -1
  224. package/dist/render/drawable_mixin.js +53 -6
  225. package/dist/render/drawable_mixin.js.map +1 -1
  226. package/dist/render/dualdepthpeeling_oit.js +53 -53
  227. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  228. package/dist/render/envlight.js +196 -113
  229. package/dist/render/envlight.js.map +1 -1
  230. package/dist/render/fbm_wavegenerator.js +8 -13
  231. package/dist/render/fbm_wavegenerator.js.map +1 -1
  232. package/dist/render/fft_wavegenerator.js +268 -136
  233. package/dist/render/fft_wavegenerator.js.map +1 -1
  234. package/dist/render/gerstner_wavegenerator.js +113 -28
  235. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  236. package/dist/render/gi/probe_volume.js +1334 -0
  237. package/dist/render/gi/probe_volume.js.map +1 -0
  238. package/dist/render/gi/scene_gi.js +282 -0
  239. package/dist/render/gi/scene_gi.js.map +1 -0
  240. package/dist/render/gi/voxel_atlas.js +198 -0
  241. package/dist/render/gi/voxel_atlas.js.map +1 -0
  242. package/dist/render/gi/voxel_lighting.js +652 -0
  243. package/dist/render/gi/voxel_lighting.js.map +1 -0
  244. package/dist/render/gi/voxel_scene.js +642 -0
  245. package/dist/render/gi/voxel_scene.js.map +1 -0
  246. package/dist/render/gi/voxelize_pass.js +223 -0
  247. package/dist/render/gi/voxelize_pass.js.map +1 -0
  248. package/dist/render/globalbindgroup_allocator.js +3 -2
  249. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  250. package/dist/render/gpu_picking.js +9 -36
  251. package/dist/render/gpu_picking.js.map +1 -1
  252. package/dist/render/hzb.js +80 -22
  253. package/dist/render/hzb.js.map +1 -1
  254. package/dist/render/instance_culling.js +499 -0
  255. package/dist/render/instance_culling.js.map +1 -0
  256. package/dist/render/lightpass.js +23 -9
  257. package/dist/render/lightpass.js.map +1 -1
  258. package/dist/render/lod.js +46 -0
  259. package/dist/render/lod.js.map +1 -0
  260. package/dist/render/oit.js +11 -11
  261. package/dist/render/oit.js.map +1 -1
  262. package/dist/render/primitive.js +301 -9
  263. package/dist/render/primitive.js.map +1 -1
  264. package/dist/render/primitive_readback.js +209 -0
  265. package/dist/render/primitive_readback.js.map +1 -0
  266. package/dist/render/render_queue.js +198 -11
  267. package/dist/render/render_queue.js.map +1 -1
  268. package/dist/render/renderer.js +14 -7
  269. package/dist/render/renderer.js.map +1 -1
  270. package/dist/render/rendergraph/blackboard.js +15 -1
  271. package/dist/render/rendergraph/blackboard.js.map +1 -1
  272. package/dist/render/rendergraph/executor.js +136 -0
  273. package/dist/render/rendergraph/executor.js.map +1 -1
  274. package/dist/render/rendergraph/forward_plus_builder.js +585 -59
  275. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  276. package/dist/render/rendergraph/frame_resource_requirements.js +1 -0
  277. package/dist/render/rendergraph/frame_resource_requirements.js.map +1 -1
  278. package/dist/render/rendergraph/history_resources.js +8 -1
  279. package/dist/render/rendergraph/history_resources.js.map +1 -1
  280. package/dist/render/rendergraph/scene_render_context.js +31 -2
  281. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  282. package/dist/render/rendergraph/types.js.map +1 -1
  283. package/dist/render/renderpass.js +28 -5
  284. package/dist/render/renderpass.js.map +1 -1
  285. package/dist/render/sdf/box_allocator.js +98 -0
  286. package/dist/render/sdf/box_allocator.js.map +1 -0
  287. package/dist/render/sdf/global_sdf.js +865 -0
  288. package/dist/render/sdf/global_sdf.js.map +1 -0
  289. package/dist/render/sdf/scene_sdf.js +562 -0
  290. package/dist/render/sdf/scene_sdf.js.map +1 -0
  291. package/dist/render/sdf/sdf_atlas.js +227 -0
  292. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  293. package/dist/render/sdf/sdf_programs.js +42 -0
  294. package/dist/render/sdf/sdf_programs.js.map +1 -0
  295. package/dist/render/sdf/sdf_view.js +199 -0
  296. package/dist/render/sdf/sdf_view.js.map +1 -0
  297. package/dist/render/sdf/waterline.js +610 -0
  298. package/dist/render/sdf/waterline.js.map +1 -0
  299. package/dist/render/shadow_mask_pass.js +142 -25
  300. package/dist/render/shadow_mask_pass.js.map +1 -1
  301. package/dist/render/shore_wave_generator.js +1193 -0
  302. package/dist/render/shore_wave_generator.js.map +1 -0
  303. package/dist/render/sky.js +516 -86
  304. package/dist/render/sky.js.map +1 -1
  305. package/dist/render/transmission_thickness_pass.js +477 -0
  306. package/dist/render/transmission_thickness_pass.js.map +1 -0
  307. package/dist/render/underwater.js +524 -0
  308. package/dist/render/underwater.js.map +1 -0
  309. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  310. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  311. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  312. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  313. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  314. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  315. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  316. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  317. package/dist/render/volumetric_cloud/resources.js +380 -0
  318. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  319. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  320. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  321. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  322. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  323. package/dist/render/water_caustics.js +1195 -0
  324. package/dist/render/water_caustics.js.map +1 -0
  325. package/dist/render/water_foam.js +627 -0
  326. package/dist/render/water_foam.js.map +1 -0
  327. package/dist/render/water_interaction.js +1795 -0
  328. package/dist/render/water_interaction.js.map +1 -0
  329. package/dist/render/weightedblended_oit.js +36 -36
  330. package/dist/render/weightedblended_oit.js.map +1 -1
  331. package/dist/scene/basesprite.js +9 -4
  332. package/dist/scene/basesprite.js.map +1 -1
  333. package/dist/scene/batchgroup.js +108 -12
  334. package/dist/scene/batchgroup.js.map +1 -1
  335. package/dist/scene/environment.js +28 -7
  336. package/dist/scene/environment.js.map +1 -1
  337. package/dist/scene/foliage.js +1020 -0
  338. package/dist/scene/foliage.js.map +1 -0
  339. package/dist/scene/foliage_buckets.js +147 -0
  340. package/dist/scene/foliage_buckets.js.map +1 -0
  341. package/dist/scene/foliage_mask.js +358 -0
  342. package/dist/scene/foliage_mask.js.map +1 -0
  343. package/dist/scene/hair.js +15 -4
  344. package/dist/scene/hair.js.map +1 -1
  345. package/dist/scene/light.js +179 -13
  346. package/dist/scene/light.js.map +1 -1
  347. package/dist/scene/mesh.js +327 -45
  348. package/dist/scene/mesh.js.map +1 -1
  349. package/dist/scene/meshdrawable.js +6 -0
  350. package/dist/scene/meshdrawable.js.map +1 -1
  351. package/dist/scene/msdftext.js +9 -3
  352. package/dist/scene/msdftext.js.map +1 -1
  353. package/dist/scene/msdftextsprite.js +9 -3
  354. package/dist/scene/msdftextsprite.js.map +1 -1
  355. package/dist/scene/particlesys.js +8 -2
  356. package/dist/scene/particlesys.js.map +1 -1
  357. package/dist/scene/physics_settings.js +157 -0
  358. package/dist/scene/physics_settings.js.map +1 -0
  359. package/dist/scene/scene.js +190 -44
  360. package/dist/scene/scene.js.map +1 -1
  361. package/dist/scene/scene_node.js +147 -6
  362. package/dist/scene/scene_node.js.map +1 -1
  363. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  364. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  365. package/dist/scene/terrain-cm/grass.js +881 -42
  366. package/dist/scene/terrain-cm/grass.js.map +1 -1
  367. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  368. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  369. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  370. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  371. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  372. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  373. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  374. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  375. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  376. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  377. package/dist/scene/update_queue.js +54 -0
  378. package/dist/scene/update_queue.js.map +1 -0
  379. package/dist/scene/water.js +997 -96
  380. package/dist/scene/water.js.map +1 -1
  381. package/dist/scene/water_surface_sampler.js +324 -0
  382. package/dist/scene/water_surface_sampler.js.map +1 -0
  383. package/dist/scene/wind.js +317 -0
  384. package/dist/scene/wind.js.map +1 -0
  385. package/dist/shaders/atmosphere.js +388 -166
  386. package/dist/shaders/atmosphere.js.map +1 -1
  387. package/dist/shaders/fog.js +100 -32
  388. package/dist/shaders/fog.js.map +1 -1
  389. package/dist/shaders/gi.js +365 -0
  390. package/dist/shaders/gi.js.map +1 -0
  391. package/dist/shaders/ltc_rect.js +202 -0
  392. package/dist/shaders/ltc_rect.js.map +1 -0
  393. package/dist/shaders/misc.js +1 -10
  394. package/dist/shaders/misc.js.map +1 -1
  395. package/dist/shaders/noise.js +5 -1
  396. package/dist/shaders/noise.js.map +1 -1
  397. package/dist/shaders/probes.js +309 -0
  398. package/dist/shaders/probes.js.map +1 -0
  399. package/dist/shaders/sdf.js +537 -0
  400. package/dist/shaders/sdf.js.map +1 -0
  401. package/dist/shaders/shadow.js +104 -70
  402. package/dist/shaders/shadow.js.map +1 -1
  403. package/dist/shaders/skin_brdf.js +243 -0
  404. package/dist/shaders/skin_brdf.js.map +1 -0
  405. package/dist/shaders/ssr.js +6 -159
  406. package/dist/shaders/ssr.js.map +1 -1
  407. package/dist/shaders/temporal.js +38 -27
  408. package/dist/shaders/temporal.js.map +1 -1
  409. package/dist/shaders/water.js +40 -87
  410. package/dist/shaders/water.js.map +1 -1
  411. package/dist/shaders/water_medium.js +42 -0
  412. package/dist/shaders/water_medium.js.map +1 -0
  413. package/dist/shadow/dom.js +110 -19
  414. package/dist/shadow/dom.js.map +1 -1
  415. package/dist/shadow/esm.js +3 -3
  416. package/dist/shadow/esm.js.map +1 -1
  417. package/dist/shadow/pcf_opt.js +15 -48
  418. package/dist/shadow/pcf_opt.js.map +1 -1
  419. package/dist/shadow/pcf_pd.js +15 -53
  420. package/dist/shadow/pcf_pd.js.map +1 -1
  421. package/dist/shadow/pcss.js +34 -9
  422. package/dist/shadow/pcss.js.map +1 -1
  423. package/dist/shadow/shadow_impl.js +3 -8
  424. package/dist/shadow/shadow_impl.js.map +1 -1
  425. package/dist/shadow/shadow_region.js +87 -49
  426. package/dist/shadow/shadow_region.js.map +1 -1
  427. package/dist/shadow/shadowmapper.js +93 -53
  428. package/dist/shadow/shadowmapper.js.map +1 -1
  429. package/dist/shadow/ssm.js +18 -72
  430. package/dist/shadow/ssm.js.map +1 -1
  431. package/dist/shadow/vsm.js +3 -3
  432. package/dist/shadow/vsm.js.map +1 -1
  433. package/dist/shapes/shape.js +44 -1
  434. package/dist/shapes/shape.js.map +1 -1
  435. package/dist/utility/buoyancy.js +287 -0
  436. package/dist/utility/buoyancy.js.map +1 -0
  437. package/dist/utility/physical.js +10 -1
  438. package/dist/utility/physical.js.map +1 -1
  439. package/dist/utility/pmrem.js +17 -43
  440. package/dist/utility/pmrem.js.map +1 -1
  441. package/dist/utility/sdf/bake.js +435 -0
  442. package/dist/utility/sdf/bake.js.map +1 -0
  443. package/dist/utility/sdf/bvh.js +576 -0
  444. package/dist/utility/sdf/bvh.js.map +1 -0
  445. package/dist/utility/serialization/manager.js +36 -6
  446. package/dist/utility/serialization/manager.js.map +1 -1
  447. package/dist/utility/serialization/scene/animation.js +77 -7
  448. package/dist/utility/serialization/scene/animation.js.map +1 -1
  449. package/dist/utility/serialization/scene/batch.js +11 -4
  450. package/dist/utility/serialization/scene/batch.js.map +1 -1
  451. package/dist/utility/serialization/scene/camera.js +140 -279
  452. package/dist/utility/serialization/scene/camera.js.map +1 -1
  453. package/dist/utility/serialization/scene/cloth.js +25 -0
  454. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  455. package/dist/utility/serialization/scene/common.js +14 -6
  456. package/dist/utility/serialization/scene/common.js.map +1 -1
  457. package/dist/utility/serialization/scene/foliage.js +821 -0
  458. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  459. package/dist/utility/serialization/scene/hair.js +11 -4
  460. package/dist/utility/serialization/scene/hair.js.map +1 -1
  461. package/dist/utility/serialization/scene/light.js +115 -7
  462. package/dist/utility/serialization/scene/light.js.map +1 -1
  463. package/dist/utility/serialization/scene/material.js +388 -220
  464. package/dist/utility/serialization/scene/material.js.map +1 -1
  465. package/dist/utility/serialization/scene/mesh.js +69 -4
  466. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  467. package/dist/utility/serialization/scene/node.js +140 -5
  468. package/dist/utility/serialization/scene/node.js.map +1 -1
  469. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  470. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  471. package/dist/utility/serialization/scene/particle.js +11 -4
  472. package/dist/utility/serialization/scene/particle.js.map +1 -1
  473. package/dist/utility/serialization/scene/physics.js +120 -0
  474. package/dist/utility/serialization/scene/physics.js.map +1 -0
  475. package/dist/utility/serialization/scene/primitive.js +124 -10
  476. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  477. package/dist/utility/serialization/scene/scene.js +1687 -51
  478. package/dist/utility/serialization/scene/scene.js.map +1 -1
  479. package/dist/utility/serialization/scene/sprite.js +11 -4
  480. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  481. package/dist/utility/serialization/scene/terrain.js +163 -33
  482. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  483. package/dist/utility/serialization/scene/text.js +11 -4
  484. package/dist/utility/serialization/scene/text.js.map +1 -1
  485. package/dist/utility/serialization/scene/water.js +2473 -114
  486. package/dist/utility/serialization/scene/water.js.map +1 -1
  487. package/dist/utility/serialization/types.js.map +1 -1
  488. package/dist/utility/shprojector.js +97 -109
  489. package/dist/utility/shprojector.js.map +1 -1
  490. package/dist/utility/textures/foam.js +170 -0
  491. package/dist/utility/textures/foam.js.map +1 -0
  492. package/dist/utility/textures/ggxlut.js +17 -43
  493. package/dist/utility/textures/ggxlut.js.map +1 -1
  494. package/dist/utility/textures/ltcdata.js +4 -4
  495. package/dist/utility/textures/ltcdata.js.map +1 -1
  496. package/dist/utility/textures/ltclut.js +16 -6
  497. package/dist/utility/textures/ltclut.js.map +1 -1
  498. package/dist/utility/unsupported.js +24 -0
  499. package/dist/utility/unsupported.js.map +1 -0
  500. package/dist/values.js +13 -1
  501. package/dist/values.js.map +1 -1
  502. package/package.json +25 -12
  503. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  504. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  505. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  506. package/src/asset/meshoptimizer/LICENSE +21 -0
@@ -1,6 +1,6 @@
1
- import { Vector3, Disposable, randomUUID, Quaternion, DWeakRef, DRef, Matrix4x4, nextPowerOf2 } from '@zephyr3d/base';
1
+ import { Vector3, Matrix4x4, Disposable, randomUUID, Quaternion, DWeakRef } from '@zephyr3d/base';
2
2
  import { BoundingBox } from '../utility/bounding_volume.js';
3
- import { getDevice } from '../app/api.js';
3
+ import { SkinPaletteAtlas } from './skin_palette_atlas.js';
4
4
 
5
5
  /**
6
6
  * Standardized humanoid joint names for consistent skeleton mapping across models and animations.
@@ -58,7 +58,9 @@ import { getDevice } from '../app/api.js';
58
58
  return HumanoidHandRig;
59
59
  }({});
60
60
  const tmpV0 = new Vector3();
61
- const tmpV1 = new Vector3();
61
+ const tmpMatrix = new Matrix4x4();
62
+ const tmpMatrix2 = new Matrix4x4();
63
+ /** Palette header slot: absolute slot indices of the current and previous sets */ const tmpHeader = new Float32Array(16);
62
64
  const humanoidHelperJointTokens = new Set([
63
65
  'end',
64
66
  'nub',
@@ -78,6 +80,8 @@ const humanoidHelperJointTokens = new Set([
78
80
  _joints;
79
81
  _bindPoseByJoint;
80
82
  _bindPose;
83
+ _retargetPoseByJoint;
84
+ _retargetPose;
81
85
  _rootJoint;
82
86
  _rootBindPose;
83
87
  _playing;
@@ -93,6 +97,14 @@ const humanoidHelperJointTokens = new Set([
93
97
  for(let i = 0; i < joints.length; i++){
94
98
  this._bindPoseByJoint.set(joints[i], bindPose[i]);
95
99
  }
100
+ if (options?.retargetPose && options.retargetPose.length !== joints.length) {
101
+ throw new Error('SkeletonRig(): retarget pose must contain one transform per joint');
102
+ }
103
+ this._retargetPose = options?.retargetPose ?? null;
104
+ this._retargetPoseByJoint = this._retargetPose ? new Map(joints.map((joint, index)=>[
105
+ joint,
106
+ this._retargetPose[index]
107
+ ])) : null;
96
108
  const skeletonRoot = this.findRootJoint(this._joints);
97
109
  this._rootJoint = options?.rootJoint ?? skeletonRoot;
98
110
  this._rootBindPose = options?.rootBindPose ?? this.getNodeBindPose(this._rootJoint);
@@ -145,6 +157,12 @@ const humanoidHelperJointTokens = new Set([
145
157
  get bindPose() {
146
158
  return this._bindPose;
147
159
  }
160
+ /** Effective humanoid retarget reference pose. */ get retargetPose() {
161
+ return this._retargetPose ?? this._bindPose;
162
+ }
163
+ /** Whether this rig has a reference pose that is distinct from its bind pose. */ get hasRetargetPose() {
164
+ return !!this._retargetPose;
165
+ }
148
166
  get rootJoint() {
149
167
  return this._rootJoint;
150
168
  }
@@ -158,6 +176,9 @@ const humanoidHelperJointTokens = new Set([
158
176
  getBindPoseForJoint(joint) {
159
177
  return this._bindPoseByJoint.get(joint) ?? null;
160
178
  }
179
+ getRetargetPoseForJoint(joint) {
180
+ return this._retargetPoseByJoint?.get(joint) ?? this.getBindPoseForJoint(joint);
181
+ }
161
182
  get humanoidJointMapping() {
162
183
  return this._humanoidJointMapping;
163
184
  }
@@ -275,11 +296,14 @@ function sideJointPatterns(side, patterns) {
275
296
  * - Applies skinning state to associated meshes each frame.
276
297
  * - Computes animated axis-aligned bounding boxes using representative skinned vertices.
277
298
  *
278
- * Joint matrix texture layout:
279
- * - Texture format: `rgba32f`.
280
- * - Stored as a 2-layered ring buffer: current and previous joint transforms to support
281
- * temporal addressing if needed. Offsets are tracked in `_jointOffsets[0]` (current)
282
- * and `_jointOffsets[1]` (previous).
299
+ * Joint matrix palette layout:
300
+ * - A block of slots in the shared {@link SkinPaletteAtlas}, one slot per 4x4 matrix.
301
+ * - Slot 0 is a header holding the absolute slot indices of the current and previous sets.
302
+ * - The rest is a 2-layered ring buffer: current and previous joint transforms to support
303
+ * temporal addressing. Offsets relative to the block are tracked in `_jointOffsets[0]`
304
+ * (current) and `_jointOffsets[1]` (previous).
305
+ * - Palette matrices are relative to {@link SkinBinding.referenceNode}, so they do not change
306
+ * when the whole character moves and can be shared by instances of the same model.
283
307
  *
284
308
  * Usage:
285
309
  * - Construct with a rig, bind data, meshes and submesh bounding info.
@@ -295,8 +319,17 @@ function sideJointPatterns(side, patterns) {
295
319
  /** @internal */ _inverseBindMatrices;
296
320
  /** @internal */ _jointMatrices;
297
321
  /** @internal */ _jointOffsets;
298
- /** @internal */ _jointMatrixArray;
299
- /** @internal */ _jointTexture;
322
+ /** @internal */ _paletteBlock;
323
+ /** @internal Number of meshes skinned by other palettes in place of this binding's */ _paletteSuspendCount;
324
+ /** @internal Increased each time the pose relative to the reference node changes */ _paletteVersion;
325
+ /** @internal Whether both palette sets hold the current pose, so a still pose needs no write */ _paletteSettled;
326
+ /**
327
+ * @internal Joints and the nodes between them and the reference node, whose local transforms
328
+ * make up the pose
329
+ */ _poseNodes;
330
+ /** @internal Sum of the local transform tags of the pose nodes when the pose last changed */ _poseTag;
331
+ /** @internal Meshes waiting for the pose to change before updating again */ _sleepingMeshes;
332
+ /** @internal */ _paletteData;
300
333
  /** @internal */ _playing;
301
334
  /** @internal */ _lastUpdateTime;
302
335
  /**
@@ -312,7 +345,13 @@ function sideJointPatterns(side, patterns) {
312
345
  this._rig = rig;
313
346
  this._joints = joints ?? rig.joints;
314
347
  this._inverseBindMatrices = inverseBindMatrices;
315
- this._jointTexture = new DRef();
348
+ this._paletteBlock = null;
349
+ this._paletteSuspendCount = 0;
350
+ this._paletteVersion = 0;
351
+ this._paletteSettled = false;
352
+ this._poseNodes = null;
353
+ this._poseTag = -1;
354
+ this._sleepingMeshes = new Set();
316
355
  this._playing = false;
317
356
  this._lastUpdateTime = 0;
318
357
  if (bindPose && bindPose !== rig.bindPose) {
@@ -321,7 +360,8 @@ function sideJointPatterns(side, patterns) {
321
360
  this._rig = new SkeletonRig(rig.joints, bindPose, {
322
361
  rootJoint: rig.rootJoint,
323
362
  rootBindPose: rig.rootBindPose,
324
- humanoidJointMapping: rig.humanoidJointMapping
363
+ humanoidJointMapping: rig.humanoidJointMapping,
364
+ retargetPose: rig.hasRetargetPose ? rig.retargetPose : null
325
365
  });
326
366
  }
327
367
  this.updateJointMatrices();
@@ -385,9 +425,43 @@ function sideJointPatterns(side, patterns) {
385
425
  /**
386
426
  * Texture containing joint matrices for GPU skinning.
387
427
  *
388
- * Each matrix is stored in 4 texels (one row per texel, RGBA = 4 floats).
428
+ * This is the shared {@link SkinPaletteAtlas} texture; the palette of this binding starts at
429
+ * slot {@link SkinBinding.paletteBase}. Each matrix is stored in 4 texels (one row per texel,
430
+ * RGBA = 4 floats).
389
431
  */ get jointTexture() {
390
- return this._jointTexture.get();
432
+ return SkinPaletteAtlas.instance.texture;
433
+ }
434
+ /**
435
+ * Index of the header slot of this binding's palette in the joint texture.
436
+ *
437
+ * @internal
438
+ */ get paletteBase() {
439
+ return this._paletteBlock?.base ?? 0;
440
+ }
441
+ /**
442
+ * Increased each time the pose relative to the reference node changes, so skinned meshes
443
+ * recompute their bounds only then. A model moving as a whole keeps its pose.
444
+ *
445
+ * @internal
446
+ */ get paletteVersion() {
447
+ return this._paletteVersion;
448
+ }
449
+ /**
450
+ * Have a skinned mesh queued for update the next time the pose changes, instead of every frame.
451
+ *
452
+ * @internal
453
+ */ sleepUntilPoseChanges(mesh) {
454
+ this._sleepingMeshes.add(mesh);
455
+ }
456
+ /**
457
+ * Node the palette matrices are relative to: the parent of the rig's root joint, or null
458
+ * for world space.
459
+ *
460
+ * @remarks
461
+ * A mesh skinned by this binding transforms palette output to its local space by
462
+ * `inverse(mesh.worldMatrix) * referenceNode.worldMatrix`.
463
+ */ get referenceNode() {
464
+ return this._rig.rootJoint?.parent ?? null;
391
465
  }
392
466
  /**
393
467
  * Get joint index by joint node
@@ -419,10 +493,13 @@ function sideJointPatterns(side, patterns) {
419
493
  * @param worldMatrix - Optional world-to-model transform applied before inverse bind.
420
494
  * @internal
421
495
  */ updateJointMatrices() {
422
- if (!this._jointTexture.get()) {
423
- this._createJointTexture();
496
+ if (!this._jointOffsets) {
497
+ this._createPalette();
498
+ } else if (!this._paletteBlock) {
499
+ this._paletteBlock = SkinPaletteAtlas.instance.allocate(this.joints.length * 2 + 1);
424
500
  }
425
- if (this._jointOffsets[0] === 0) {
501
+ const first = this._jointOffsets[0] === 0;
502
+ if (first) {
426
503
  this._jointOffsets[0] = 1;
427
504
  this._jointOffsets[1] = 1;
428
505
  } else {
@@ -432,6 +509,24 @@ function sideJointPatterns(side, patterns) {
432
509
  for(let i = 0; i < this.joints.length; i++){
433
510
  Matrix4x4.multiply(this.joints[i].worldMatrix, this._inverseBindMatrices[i], this._jointMatrices[i + this._jointOffsets[0] - 1]);
434
511
  }
512
+ // CPU-side matrices are world space and always current; the palette and anything derived
513
+ // from the pose only change when the pose relative to the reference node does
514
+ const changed = this._poseChanged() || first;
515
+ if (changed) {
516
+ this._computePalette();
517
+ this._paletteSettled = false;
518
+ this._paletteVersion++;
519
+ for (const mesh of this._sleepingMeshes){
520
+ mesh.scene?.queueUpdateNode(mesh);
521
+ }
522
+ this._sleepingMeshes.clear();
523
+ }
524
+ // The first still frame writes the pose once more so the previous set equals the current
525
+ // one; after that both sets hold it and the atlas is left alone
526
+ if (!this._paletteSettled) {
527
+ this._writePalette();
528
+ this._paletteSettled = !changed;
529
+ }
435
530
  }
436
531
  /**
437
532
  * Reset skeleton to bind pose
@@ -441,14 +536,44 @@ function sideJointPatterns(side, patterns) {
441
536
  this._rig.computeBindPose();
442
537
  }
443
538
  /**
444
- * Compute current joint matrices from the nodes and upload them to the joint texture.
539
+ * Compute current joint matrices from the nodes and write them to the joint texture.
540
+ *
541
+ * @remarks
542
+ * The joint texture is uploaded once per frame when the scene update completes.
445
543
  *
446
544
  * @internal
447
545
  */ apply() {
448
- this.updateJointMatrices();
449
- const tex = this.jointTexture;
450
- this._syncJointMatrixArray();
451
- tex.update(this._jointMatrixArray, 0, 0, tex.width, tex.height);
546
+ if (this._paletteSuspendCount === 0) {
547
+ this.updateJointMatrices();
548
+ }
549
+ }
550
+ /**
551
+ * Stop or resume updating the palette, while meshes are skinned by other palettes in place of
552
+ * this binding's.
553
+ *
554
+ * @remarks
555
+ * Calls are counted; the palette updates again once every suspension is resumed. CPU-side joint
556
+ * matrices are not updated while suspended either.
557
+ *
558
+ * The atlas block of the palette is released while suspended, since no mesh reads it, and
559
+ * allocated again on resume, at a new base: meshes pick it up as their palette overrides are
560
+ * cleared.
561
+ *
562
+ * @param suspend - true to suspend, false to resume
563
+ * @internal
564
+ */ suspendPalette(suspend) {
565
+ const wasSuspended = this._paletteSuspendCount > 0;
566
+ this._paletteSuspendCount = Math.max(0, this._paletteSuspendCount + (suspend ? 1 : -1));
567
+ if (!wasSuspended && this._paletteSuspendCount > 0 && this._paletteBlock) {
568
+ SkinPaletteAtlas.instance.free(this._paletteBlock);
569
+ this._paletteBlock = null;
570
+ } else if (wasSuspended && this._paletteSuspendCount === 0 && this._jointOffsets) {
571
+ this._paletteBlock = SkinPaletteAtlas.instance.allocate(this.joints.length * 2 + 1);
572
+ // The previous set is as old as the suspension, so restart the history: the next update
573
+ // writes both sets, giving no motion for one frame rather than the motion since then
574
+ this._jointOffsets[0] = 0;
575
+ this._paletteSettled = false;
576
+ }
452
577
  }
453
578
  /**
454
579
  * Apply all enabled modifiers.
@@ -480,32 +605,50 @@ function sideJointPatterns(side, patterns) {
480
605
  * Compute the animated bounding box for a single mesh using its representative vertices.
481
606
  *
482
607
  * For each representative vertex:
483
- * - Blends the vertex by up to 4 joint matrices using provided weights.
484
- * - Transforms to the mesh's local space using `invWorldMatrix`.
608
+ * - Blends the vertex by up to 4 palette matrices using provided weights.
609
+ * - Transforms to the mesh's local space using `skinSpaceMatrix`.
485
610
  * - Expands the bounding box.
486
611
  *
612
+ * @remarks
613
+ * Reads the palette, which is relative to {@link SkinBinding.referenceNode} and changes together
614
+ * with {@link SkinBinding.paletteVersion}, rather than the world-space joint matrices: those are
615
+ * a snapshot of when the joints were last updated, and the model may have moved since without
616
+ * changing the pose, so combining them with the current mesh transform offsets the bounds.
617
+ *
487
618
  * @param info - Precomputed bounding data (representative vertices, indices, weights).
488
- * @param invWorldMatrix - Mesh inverse world matrix to convert to model/local space.
619
+ * @param skinSpaceMatrix - Matrix transforming palette output to the mesh's local space,
620
+ * see {@link Mesh.getSkinSpaceMatrix}.
489
621
  * @internal
490
- */ computeBoundingBox(info, invWorldMatrix) {
622
+ */ computeBoundingBox(info, skinSpaceMatrix) {
491
623
  info.boundingBox.beginExtend();
624
+ const palette = this._paletteData;
625
+ if (!palette) {
626
+ return;
627
+ }
628
+ const numJoints = this.joints.length;
492
629
  const influenceCount = Math.max(1, info.influenceCount ?? 4);
493
630
  for(let i = 0; i < info.boundingVertices.length; i++){
494
- tmpV0.setXYZ(0, 0, 0);
631
+ const v = info.boundingVertices[i];
632
+ let x = 0;
633
+ let y = 0;
634
+ let z = 0;
495
635
  const base = i * influenceCount;
496
636
  for(let j = 0; j < influenceCount; j++){
497
637
  const weight = Number(info.boundingVertexJointWeights[base + j]) || 0;
498
638
  if (weight <= 0) {
499
639
  continue;
500
640
  }
501
- const matrix = this._jointMatrices[(Number(info.boundingVertexBlendIndices[base + j]) || 0) + this._jointOffsets[0] - 1];
502
- if (!matrix) {
641
+ const joint = Number(info.boundingVertexBlendIndices[base + j]) || 0;
642
+ if (joint < 0 || joint >= numJoints) {
503
643
  continue;
504
644
  }
505
- matrix.transformPointAffine(info.boundingVertices[i], tmpV1).scaleBy(weight);
506
- tmpV0.addBy(tmpV1);
645
+ const m = joint * 16;
646
+ x += weight * (palette[m] * v.x + palette[m + 4] * v.y + palette[m + 8] * v.z + palette[m + 12]);
647
+ y += weight * (palette[m + 1] * v.x + palette[m + 5] * v.y + palette[m + 9] * v.z + palette[m + 13]);
648
+ z += weight * (palette[m + 2] * v.x + palette[m + 6] * v.y + palette[m + 10] * v.z + palette[m + 14]);
507
649
  }
508
- invWorldMatrix.transformPointAffine(tmpV0, tmpV0);
650
+ tmpV0.setXYZ(x, y, z);
651
+ skinSpaceMatrix.transformPointAffine(tmpV0, tmpV0);
509
652
  info.boundingBox.extend(tmpV0);
510
653
  }
511
654
  }
@@ -516,7 +659,11 @@ function sideJointPatterns(side, patterns) {
516
659
  * - Clears matrix arrays and joint references.
517
660
  */ onDispose() {
518
661
  super.onDispose();
519
- this._jointTexture.dispose();
662
+ if (this._paletteBlock) {
663
+ SkinPaletteAtlas.instance.free(this._paletteBlock);
664
+ this._paletteBlock = null;
665
+ }
666
+ this._sleepingMeshes.clear();
520
667
  const m = SkinBinding._registry.get(this._id);
521
668
  if (m?.get() === this) {
522
669
  SkinBinding._registry.delete(this._id);
@@ -524,38 +671,78 @@ function sideJointPatterns(side, patterns) {
524
671
  }
525
672
  }
526
673
  /**
527
- * Initialize joint texture and CPU-side matrix storage.
674
+ * Allocate the palette block and CPU-side matrix storage.
528
675
  *
529
676
  * Layout details:
530
- * - Texture size is the next power-of-two able to contain all matrices plus two offset texels.
531
- * - `_jointMatrixArray` holds:
532
- * - First 2 vec4s: ring buffer offsets `[current, previous, 0, 0]`.
533
- * - Followed by 2×N matrices (current and previous), each as 16 floats.
534
- * - `_jointMatrices` is a view into `_jointMatrixArray` providing Matrix4x4 objects per slot.
677
+ * - The block holds a header slot followed by 2×N matrix slots (current and previous).
678
+ * - `_jointOffsets` holds the ring buffer offsets `[current, previous]` relative to the block.
679
+ * - `_jointMatrices` holds the world-space skinning matrices of both sets, which CPU-side
680
+ * consumers (bounds, cloth) read.
535
681
  *
536
682
  * @internal
537
- */ _createJointTexture() {
538
- const textureWidth = nextPowerOf2(Math.max(4, Math.ceil(Math.sqrt((this.joints.length * 2 + 1) * 4))));
539
- const device = getDevice();
540
- this._jointTexture.set(device.createTexture2D('rgba32f', textureWidth, textureWidth, {
541
- mipmapping: false,
542
- samplerOptions: {
543
- magFilter: 'nearest',
544
- minFilter: 'nearest'
545
- }
546
- }));
547
- this._jointMatrixArray = new Float32Array(textureWidth * textureWidth * 4);
548
- this._jointOffsets = this._jointMatrixArray.subarray(0, 2);
549
- this._jointOffsets[0] = 0;
550
- this._jointOffsets[1] = 0;
683
+ */ _createPalette() {
684
+ this._paletteBlock = SkinPaletteAtlas.instance.allocate(this.joints.length * 2 + 1);
685
+ this._paletteData = new Float32Array(this.joints.length * 16);
686
+ this._paletteSettled = false;
687
+ this._jointOffsets = new Float32Array(2);
551
688
  this._jointMatrices = Array.from({
552
689
  length: this.joints.length * 2
553
690
  }).map(()=>new Matrix4x4());
554
691
  }
555
- _syncJointMatrixArray() {
556
- for(let i = 0; i < this._jointMatrices.length; i++){
557
- this._jointMatrixArray.set(this._jointMatrices[i], (i + 1) * 16);
692
+ /**
693
+ * Whether the pose may have changed since it last did: the local transform of a joint, or of a
694
+ * node between the joints and the reference node, has changed.
695
+ *
696
+ * @remarks
697
+ * Moving the whole model changes the world matrices of the joints but not the pose, so world
698
+ * matrices cannot tell; and comparing matrices taken back to the reference node trips over
699
+ * rounding far from the origin.
700
+ */ _poseChanged() {
701
+ const reference = this.referenceNode;
702
+ if (!this._poseNodes || this._poseNodes.reference !== reference) {
703
+ const nodes = new Set();
704
+ for (const joint of this.joints){
705
+ for(let node = joint; node && node !== reference; node = node.parent){
706
+ if (nodes.has(node)) {
707
+ break;
708
+ }
709
+ nodes.add(node);
710
+ }
711
+ }
712
+ this._poseNodes = {
713
+ reference,
714
+ nodes: [
715
+ ...nodes
716
+ ]
717
+ };
718
+ this._poseTag = -1;
719
+ }
720
+ let tag = 0;
721
+ for (const node of this._poseNodes.nodes){
722
+ tag += node.localTransformTag;
723
+ }
724
+ if (tag !== this._poseTag) {
725
+ this._poseTag = tag;
726
+ return true;
558
727
  }
728
+ return false;
729
+ }
730
+ /** Compute the current set of matrices relative to the reference node */ _computePalette() {
731
+ const reference = this.referenceNode;
732
+ const invReference = reference ? Matrix4x4.invertAffine(reference.worldMatrix, tmpMatrix) : null;
733
+ const offset = this._jointOffsets[0] - 1;
734
+ for(let i = 0; i < this.joints.length; i++){
735
+ const world = this._jointMatrices[i + offset];
736
+ this._paletteData.set(invReference ? Matrix4x4.multiplyAffine(invReference, world, tmpMatrix2) : world, i * 16);
737
+ }
738
+ }
739
+ /** Write the header and the current set of matrices to the palette */ _writePalette() {
740
+ const atlas = SkinPaletteAtlas.instance;
741
+ const base = this._paletteBlock.base;
742
+ atlas.writeSlots(base + this._jointOffsets[0], this._paletteData);
743
+ tmpHeader[0] = base + this._jointOffsets[0];
744
+ tmpHeader[1] = base + this._jointOffsets[1];
745
+ atlas.writeSlots(base, tmpHeader);
559
746
  }
560
747
  /**
561
748
  * Build representative skinned bounding data for a submesh.
@@ -700,6 +887,63 @@ function sideJointPatterns(side, patterns) {
700
887
  }
701
888
  return result;
702
889
  }
890
+ /**
891
+ * Skin packed direction vectors into mesh-local space for the current skeleton pose.
892
+ *
893
+ * Unlike positions, directions ignore matrix translation and are normalized after
894
+ * conversion through the mesh inverse world matrix.
895
+ *
896
+ * @internal
897
+ */ skinDirectionsToLocal(directions, blendIndices, weights, invWorldMatrix, out, influenceCount) {
898
+ const result = out && out.length === directions.length ? out : new Float32Array(directions.length);
899
+ const matrixOffset = this._jointOffsets[0] - 1;
900
+ const effectiveInfluenceCount = Math.max(1, influenceCount ?? Math.max(1, Math.floor(weights.length / Math.max(1, Math.floor(directions.length / 3)))));
901
+ for(let i = 0; i + 2 < directions.length; i += 3){
902
+ const vertexIndex = i / 3 >> 0;
903
+ const x = directions[i];
904
+ const y = directions[i + 1];
905
+ const z = directions[i + 2];
906
+ let skinnedX = 0;
907
+ let skinnedY = 0;
908
+ let skinnedZ = 0;
909
+ let weightSum = 0;
910
+ const base = vertexIndex * effectiveInfluenceCount;
911
+ for(let j = 0; j < effectiveInfluenceCount; j++){
912
+ const weight = Number(weights[base + j]) || 0;
913
+ if (weight <= 0) {
914
+ continue;
915
+ }
916
+ const jointIndex = (Number(blendIndices[base + j]) || 0) + matrixOffset;
917
+ const matrix = this._jointMatrices[jointIndex];
918
+ if (!matrix) {
919
+ continue;
920
+ }
921
+ skinnedX += (matrix[0] * x + matrix[4] * y + matrix[8] * z) * weight;
922
+ skinnedY += (matrix[1] * x + matrix[5] * y + matrix[9] * z) * weight;
923
+ skinnedZ += (matrix[2] * x + matrix[6] * y + matrix[10] * z) * weight;
924
+ weightSum += weight;
925
+ }
926
+ if (weightSum <= 1e-6) {
927
+ skinnedX = x;
928
+ skinnedY = y;
929
+ skinnedZ = z;
930
+ }
931
+ const localX = invWorldMatrix[0] * skinnedX + invWorldMatrix[4] * skinnedY + invWorldMatrix[8] * skinnedZ;
932
+ const localY = invWorldMatrix[1] * skinnedX + invWorldMatrix[5] * skinnedY + invWorldMatrix[9] * skinnedZ;
933
+ const localZ = invWorldMatrix[2] * skinnedX + invWorldMatrix[6] * skinnedY + invWorldMatrix[10] * skinnedZ;
934
+ const length = Math.hypot(localX, localY, localZ);
935
+ if (length > 1e-8) {
936
+ result[i] = localX / length;
937
+ result[i + 1] = localY / length;
938
+ result[i + 2] = localZ / length;
939
+ } else {
940
+ result[i] = 0;
941
+ result[i + 1] = 1;
942
+ result[i + 2] = 0;
943
+ }
944
+ }
945
+ return result;
946
+ }
703
947
  static normalizeHumanoidJointName(name) {
704
948
  return name.slice(name.lastIndexOf(':') + 1).replace(/([A-Z]+)([A-Z][a-z])/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2').replace(/([a-zA-Z])(\d+)/g, '$1 $2').replace(/(\d+)([a-zA-Z])/g, '$1 $2').replace(/[_:\/\\.-]+/g, ' ').replace(/[^a-zA-Z0-9]+/g, ' ').toLowerCase().replace(/\bforearm\b/g, 'fore arm').replace(/\bupperarm\b/g, 'upper arm').replace(/\blowerarm\b/g, 'lower arm').replace(/\bupleg\b/g, 'up leg').replace(/\bupperleg\b/g, 'upper leg').replace(/\blowerleg\b/g, 'lower leg').replace(/\btoebase\b/g, 'toe base').replace(/\bupperchest\b/g, 'upper chest').replace(/\btoes\b/g, 'toe').replace(/\blittle\b/g, 'pinky').replace(/\bcollar\b/g, 'clavicle').replace(/\s+/g, ' ').trim();
705
949
  }