@zephyr3d/scene 0.9.27 → 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 (502) 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 +54 -0
  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 +279 -55
  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 +171 -1
  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 +104 -178
  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 +25436 -15990
  109. package/dist/index.js +65 -11
  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/lambert.js +4 -1
  118. package/dist/material/lambert.js.map +1 -1
  119. package/dist/material/material.js +66 -4
  120. package/dist/material/material.js.map +1 -1
  121. package/dist/material/meshmaterial.js +118 -45
  122. package/dist/material/meshmaterial.js.map +1 -1
  123. package/dist/material/mixins/lightmodel/blinnphong.js +1 -1
  124. package/dist/material/mixins/lightmodel/blinnphong.js.map +1 -1
  125. package/dist/material/mixins/lightmodel/lambert.js +1 -1
  126. package/dist/material/mixins/lightmodel/lambert.js.map +1 -1
  127. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js +34 -61
  128. package/dist/material/mixins/lightmodel/pbrblueprintmixin.js.map +1 -1
  129. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js +16 -2
  130. package/dist/material/mixins/lightmodel/pbrmetallicroughness.js.map +1 -1
  131. package/dist/material/mixins/lightmodel/pbrspecularglossness.js +2 -1
  132. package/dist/material/mixins/lightmodel/pbrspecularglossness.js.map +1 -1
  133. package/dist/material/mixins/lit.js +191 -83
  134. package/dist/material/mixins/lit.js.map +1 -1
  135. package/dist/material/mixins/pbr/common.js +31 -206
  136. package/dist/material/mixins/pbr/common.js.map +1 -1
  137. package/dist/material/mtoon.js +1 -1
  138. package/dist/material/mtoon.js.map +1 -1
  139. package/dist/material/pbrmr.js +3 -0
  140. package/dist/material/pbrmr.js.map +1 -1
  141. package/dist/material/pbrsg.js +3 -0
  142. package/dist/material/pbrsg.js.map +1 -1
  143. package/dist/material/sdf_debug.js +78 -0
  144. package/dist/material/sdf_debug.js.map +1 -0
  145. package/dist/material/shader/helper.js +333 -191
  146. package/dist/material/shader/helper.js.map +1 -1
  147. package/dist/material/shader/terrain_blend.js +204 -43
  148. package/dist/material/shader/terrain_blend.js.map +1 -1
  149. package/dist/material/skin.js +331 -297
  150. package/dist/material/skin.js.map +1 -1
  151. package/dist/material/skinprofile.js +1058 -0
  152. package/dist/material/skinprofile.js.map +1 -0
  153. package/dist/material/sss.js +353 -0
  154. package/dist/material/sss.js.map +1 -0
  155. package/dist/material/sss_kernel.js +265 -0
  156. package/dist/material/sss_kernel.js.map +1 -0
  157. package/dist/material/sssprofile.js +879 -0
  158. package/dist/material/sssprofile.js.map +1 -0
  159. package/dist/material/subsurfaceprofile.js +4 -8
  160. package/dist/material/subsurfaceprofile.js.map +1 -1
  161. package/dist/material/terrain-cm.js +464 -188
  162. package/dist/material/terrain-cm.js.map +1 -1
  163. package/dist/material/unlit.js +3 -0
  164. package/dist/material/unlit.js.map +1 -1
  165. package/dist/material/water.js +1261 -1438
  166. package/dist/material/water.js.map +1 -1
  167. package/dist/node_modules/meshoptimizer/LICENSE +21 -0
  168. package/dist/node_modules/meshoptimizer/meshopt_decoder.js +197 -0
  169. package/dist/node_modules/meshoptimizer/meshopt_decoder.js.map +1 -0
  170. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js +677 -0
  171. package/dist/node_modules/meshoptimizer/meshopt_simplifier.js.map +1 -0
  172. package/dist/physics/character.js +226 -0
  173. package/dist/physics/character.js.map +1 -0
  174. package/dist/physics/collider.js +209 -0
  175. package/dist/physics/collider.js.map +1 -0
  176. package/dist/physics/events.js +79 -0
  177. package/dist/physics/events.js.map +1 -0
  178. package/dist/physics/joint.js +272 -0
  179. package/dist/physics/joint.js.map +1 -0
  180. package/dist/physics/node_physics.js +234 -0
  181. package/dist/physics/node_physics.js.map +1 -0
  182. package/dist/physics/part.js +91 -0
  183. package/dist/physics/part.js.map +1 -0
  184. package/dist/physics/rigid_body.js +379 -0
  185. package/dist/physics/rigid_body.js.map +1 -0
  186. package/dist/physics/vehicle.js +335 -0
  187. package/dist/physics/vehicle.js.map +1 -0
  188. package/dist/physics/world.js +25 -0
  189. package/dist/physics/world.js.map +1 -0
  190. package/dist/posteffect/bloom.js +49 -14
  191. package/dist/posteffect/bloom.js.map +1 -1
  192. package/dist/posteffect/motionblur.js +106 -106
  193. package/dist/posteffect/motionblur.js.map +1 -1
  194. package/dist/posteffect/postsss.js +572 -0
  195. package/dist/posteffect/postsss.js.map +1 -0
  196. package/dist/posteffect/sao.js +2 -6
  197. package/dist/posteffect/sao.js.map +1 -1
  198. package/dist/posteffect/skinsss.js +605 -355
  199. package/dist/posteffect/skinsss.js.map +1 -1
  200. package/dist/posteffect/ssgi.js +91 -162
  201. package/dist/posteffect/ssgi.js.map +1 -1
  202. package/dist/posteffect/ssr.js +3 -11
  203. package/dist/posteffect/ssr.js.map +1 -1
  204. package/dist/posteffect/sss.js +4 -13
  205. package/dist/posteffect/sss.js.map +1 -1
  206. package/dist/posteffect/taa.js +1 -0
  207. package/dist/posteffect/taa.js.map +1 -1
  208. package/dist/render/abuffer_oit.js +3 -2
  209. package/dist/render/abuffer_oit.js.map +1 -1
  210. package/dist/render/clipmap.js +179 -64
  211. package/dist/render/clipmap.js.map +1 -1
  212. package/dist/render/cluster_light.js +958 -224
  213. package/dist/render/cluster_light.js.map +1 -1
  214. package/dist/render/cull_visitor.js +25 -5
  215. package/dist/render/cull_visitor.js.map +1 -1
  216. package/dist/render/debug_views.js +37 -0
  217. package/dist/render/debug_views.js.map +1 -0
  218. package/dist/render/depthpass.js +5 -1
  219. package/dist/render/depthpass.js.map +1 -1
  220. package/dist/render/drawable_mixin.js +53 -6
  221. package/dist/render/drawable_mixin.js.map +1 -1
  222. package/dist/render/dualdepthpeeling_oit.js +5 -5
  223. package/dist/render/dualdepthpeeling_oit.js.map +1 -1
  224. package/dist/render/envlight.js +196 -113
  225. package/dist/render/envlight.js.map +1 -1
  226. package/dist/render/fbm_wavegenerator.js +5 -10
  227. package/dist/render/fbm_wavegenerator.js.map +1 -1
  228. package/dist/render/fft_wavegenerator.js +247 -157
  229. package/dist/render/fft_wavegenerator.js.map +1 -1
  230. package/dist/render/gerstner_wavegenerator.js +16 -38
  231. package/dist/render/gerstner_wavegenerator.js.map +1 -1
  232. package/dist/render/gi/probe_volume.js +1334 -0
  233. package/dist/render/gi/probe_volume.js.map +1 -0
  234. package/dist/render/gi/scene_gi.js +282 -0
  235. package/dist/render/gi/scene_gi.js.map +1 -0
  236. package/dist/render/gi/voxel_atlas.js +198 -0
  237. package/dist/render/gi/voxel_atlas.js.map +1 -0
  238. package/dist/render/gi/voxel_lighting.js +652 -0
  239. package/dist/render/gi/voxel_lighting.js.map +1 -0
  240. package/dist/render/gi/voxel_scene.js +642 -0
  241. package/dist/render/gi/voxel_scene.js.map +1 -0
  242. package/dist/render/gi/voxelize_pass.js +223 -0
  243. package/dist/render/gi/voxelize_pass.js.map +1 -0
  244. package/dist/render/globalbindgroup_allocator.js +3 -2
  245. package/dist/render/globalbindgroup_allocator.js.map +1 -1
  246. package/dist/render/gpu_picking.js +9 -36
  247. package/dist/render/gpu_picking.js.map +1 -1
  248. package/dist/render/instance_culling.js +499 -0
  249. package/dist/render/instance_culling.js.map +1 -0
  250. package/dist/render/lightpass.js +19 -8
  251. package/dist/render/lightpass.js.map +1 -1
  252. package/dist/render/lod.js +46 -0
  253. package/dist/render/lod.js.map +1 -0
  254. package/dist/render/primitive.js +301 -9
  255. package/dist/render/primitive.js.map +1 -1
  256. package/dist/render/primitive_readback.js +209 -0
  257. package/dist/render/primitive_readback.js.map +1 -0
  258. package/dist/render/render_queue.js +162 -11
  259. package/dist/render/render_queue.js.map +1 -1
  260. package/dist/render/renderer.js +10 -7
  261. package/dist/render/renderer.js.map +1 -1
  262. package/dist/render/rendergraph/blackboard.js +14 -1
  263. package/dist/render/rendergraph/blackboard.js.map +1 -1
  264. package/dist/render/rendergraph/executor.js +136 -0
  265. package/dist/render/rendergraph/executor.js.map +1 -1
  266. package/dist/render/rendergraph/forward_plus_builder.js +272 -55
  267. package/dist/render/rendergraph/forward_plus_builder.js.map +1 -1
  268. package/dist/render/rendergraph/frame_graph_context.js +41 -0
  269. package/dist/render/rendergraph/frame_graph_context.js.map +1 -0
  270. package/dist/render/rendergraph/scene_render_context.js +31 -2
  271. package/dist/render/rendergraph/scene_render_context.js.map +1 -1
  272. package/dist/render/rendergraph/types.js.map +1 -1
  273. package/dist/render/renderpass.js +28 -5
  274. package/dist/render/renderpass.js.map +1 -1
  275. package/dist/render/sdf/box_allocator.js +98 -0
  276. package/dist/render/sdf/box_allocator.js.map +1 -0
  277. package/dist/render/sdf/global_sdf.js +865 -0
  278. package/dist/render/sdf/global_sdf.js.map +1 -0
  279. package/dist/render/sdf/scene_sdf.js +562 -0
  280. package/dist/render/sdf/scene_sdf.js.map +1 -0
  281. package/dist/render/sdf/sdf_atlas.js +227 -0
  282. package/dist/render/sdf/sdf_atlas.js.map +1 -0
  283. package/dist/render/sdf/sdf_programs.js +42 -0
  284. package/dist/render/sdf/sdf_programs.js.map +1 -0
  285. package/dist/render/sdf/sdf_view.js +199 -0
  286. package/dist/render/sdf/sdf_view.js.map +1 -0
  287. package/dist/render/sdf/waterline.js +610 -0
  288. package/dist/render/sdf/waterline.js.map +1 -0
  289. package/dist/render/shadow_mask_pass.js +142 -25
  290. package/dist/render/shadow_mask_pass.js.map +1 -1
  291. package/dist/render/shore_wave_generator.js +1193 -0
  292. package/dist/render/shore_wave_generator.js.map +1 -0
  293. package/dist/render/sky.js +516 -86
  294. package/dist/render/sky.js.map +1 -1
  295. package/dist/render/transmission_thickness_pass.js +477 -0
  296. package/dist/render/transmission_thickness_pass.js.map +1 -0
  297. package/dist/render/underwater.js +58 -158
  298. package/dist/render/underwater.js.map +1 -1
  299. package/dist/render/virtualtexture/virtual_texture.js +1214 -0
  300. package/dist/render/virtualtexture/virtual_texture.js.map +1 -0
  301. package/dist/render/volumetric_cloud/cloud_common.js +472 -0
  302. package/dist/render/volumetric_cloud/cloud_common.js.map +1 -0
  303. package/dist/render/volumetric_cloud/cloud_noise.js +189 -0
  304. package/dist/render/volumetric_cloud/cloud_noise.js.map +1 -0
  305. package/dist/render/volumetric_cloud/debug_view.js +131 -0
  306. package/dist/render/volumetric_cloud/debug_view.js.map +1 -0
  307. package/dist/render/volumetric_cloud/resources.js +380 -0
  308. package/dist/render/volumetric_cloud/resources.js.map +1 -0
  309. package/dist/render/volumetric_cloud/sky_cache.js +380 -0
  310. package/dist/render/volumetric_cloud/sky_cache.js.map +1 -0
  311. package/dist/render/volumetric_cloud/volumetric_cloud.js +318 -0
  312. package/dist/render/volumetric_cloud/volumetric_cloud.js.map +1 -0
  313. package/dist/render/water_caustics.js +134 -319
  314. package/dist/render/water_caustics.js.map +1 -1
  315. package/dist/render/water_foam.js +627 -0
  316. package/dist/render/water_foam.js.map +1 -0
  317. package/dist/render/water_interaction.js +1795 -0
  318. package/dist/render/water_interaction.js.map +1 -0
  319. package/dist/render/weightedblended_oit.js +3 -3
  320. package/dist/render/weightedblended_oit.js.map +1 -1
  321. package/dist/scene/basesprite.js +9 -4
  322. package/dist/scene/basesprite.js.map +1 -1
  323. package/dist/scene/batchgroup.js +108 -12
  324. package/dist/scene/batchgroup.js.map +1 -1
  325. package/dist/scene/environment.js +28 -7
  326. package/dist/scene/environment.js.map +1 -1
  327. package/dist/scene/foliage.js +1020 -0
  328. package/dist/scene/foliage.js.map +1 -0
  329. package/dist/scene/foliage_buckets.js +147 -0
  330. package/dist/scene/foliage_buckets.js.map +1 -0
  331. package/dist/scene/foliage_mask.js +358 -0
  332. package/dist/scene/foliage_mask.js.map +1 -0
  333. package/dist/scene/hair.js +15 -4
  334. package/dist/scene/hair.js.map +1 -1
  335. package/dist/scene/light.js +179 -13
  336. package/dist/scene/light.js.map +1 -1
  337. package/dist/scene/mesh.js +327 -45
  338. package/dist/scene/mesh.js.map +1 -1
  339. package/dist/scene/meshdrawable.js +6 -0
  340. package/dist/scene/meshdrawable.js.map +1 -1
  341. package/dist/scene/msdftext.js +9 -3
  342. package/dist/scene/msdftext.js.map +1 -1
  343. package/dist/scene/msdftextsprite.js +9 -3
  344. package/dist/scene/msdftextsprite.js.map +1 -1
  345. package/dist/scene/particlesys.js +8 -2
  346. package/dist/scene/particlesys.js.map +1 -1
  347. package/dist/scene/physics_settings.js +157 -0
  348. package/dist/scene/physics_settings.js.map +1 -0
  349. package/dist/scene/scene.js +190 -44
  350. package/dist/scene/scene.js.map +1 -1
  351. package/dist/scene/scene_node.js +147 -6
  352. package/dist/scene/scene_node.js.map +1 -1
  353. package/dist/scene/terrain-cm/bladegrassmaterial.js +735 -0
  354. package/dist/scene/terrain-cm/bladegrassmaterial.js.map +1 -0
  355. package/dist/scene/terrain-cm/grass.js +881 -42
  356. package/dist/scene/terrain-cm/grass.js.map +1 -1
  357. package/dist/scene/terrain-cm/grass_gpu.js +929 -0
  358. package/dist/scene/terrain-cm/grass_gpu.js.map +1 -0
  359. package/dist/scene/terrain-cm/grassmaterial.js +180 -9
  360. package/dist/scene/terrain-cm/grassmaterial.js.map +1 -1
  361. package/dist/scene/terrain-cm/terrain-cm.js +465 -36
  362. package/dist/scene/terrain-cm/terrain-cm.js.map +1 -1
  363. package/dist/scene/terrain-cm/terrain_gi_albedo.js +257 -0
  364. package/dist/scene/terrain-cm/terrain_gi_albedo.js.map +1 -0
  365. package/dist/scene/terrain-cm/terrain_rvt.js +395 -0
  366. package/dist/scene/terrain-cm/terrain_rvt.js.map +1 -0
  367. package/dist/scene/update_queue.js +54 -0
  368. package/dist/scene/update_queue.js.map +1 -0
  369. package/dist/scene/water.js +633 -268
  370. package/dist/scene/water.js.map +1 -1
  371. package/dist/scene/water_surface_sampler.js +324 -0
  372. package/dist/scene/water_surface_sampler.js.map +1 -0
  373. package/dist/scene/wind.js +317 -0
  374. package/dist/scene/wind.js.map +1 -0
  375. package/dist/shaders/atmosphere.js +388 -166
  376. package/dist/shaders/atmosphere.js.map +1 -1
  377. package/dist/shaders/fog.js +100 -32
  378. package/dist/shaders/fog.js.map +1 -1
  379. package/dist/shaders/gi.js +365 -0
  380. package/dist/shaders/gi.js.map +1 -0
  381. package/dist/shaders/ltc_rect.js +202 -0
  382. package/dist/shaders/ltc_rect.js.map +1 -0
  383. package/dist/shaders/misc.js +1 -10
  384. package/dist/shaders/misc.js.map +1 -1
  385. package/dist/shaders/noise.js +5 -1
  386. package/dist/shaders/noise.js.map +1 -1
  387. package/dist/shaders/probes.js +309 -0
  388. package/dist/shaders/probes.js.map +1 -0
  389. package/dist/shaders/sdf.js +537 -0
  390. package/dist/shaders/sdf.js.map +1 -0
  391. package/dist/shaders/shadow.js +104 -70
  392. package/dist/shaders/shadow.js.map +1 -1
  393. package/dist/shaders/skin_brdf.js +243 -0
  394. package/dist/shaders/skin_brdf.js.map +1 -0
  395. package/dist/shaders/ssgi.js +63 -0
  396. package/dist/shaders/ssgi.js.map +1 -0
  397. package/dist/shaders/ssgi_reprojection.js +118 -0
  398. package/dist/shaders/ssgi_reprojection.js.map +1 -0
  399. package/dist/shaders/ssr.js +6 -159
  400. package/dist/shaders/ssr.js.map +1 -1
  401. package/dist/shaders/temporal.js +38 -27
  402. package/dist/shaders/temporal.js.map +1 -1
  403. package/dist/shaders/water.js +32 -82
  404. package/dist/shaders/water.js.map +1 -1
  405. package/dist/shaders/water_medium.js +7 -21
  406. package/dist/shaders/water_medium.js.map +1 -1
  407. package/dist/shadow/dom.js +110 -19
  408. package/dist/shadow/dom.js.map +1 -1
  409. package/dist/shadow/esm.js +3 -3
  410. package/dist/shadow/esm.js.map +1 -1
  411. package/dist/shadow/pcf_opt.js +15 -48
  412. package/dist/shadow/pcf_opt.js.map +1 -1
  413. package/dist/shadow/pcf_pd.js +15 -53
  414. package/dist/shadow/pcf_pd.js.map +1 -1
  415. package/dist/shadow/pcss.js +34 -9
  416. package/dist/shadow/pcss.js.map +1 -1
  417. package/dist/shadow/shadow_impl.js +3 -8
  418. package/dist/shadow/shadow_impl.js.map +1 -1
  419. package/dist/shadow/shadow_region.js +40 -2
  420. package/dist/shadow/shadow_region.js.map +1 -1
  421. package/dist/shadow/shadowmapper.js +93 -53
  422. package/dist/shadow/shadowmapper.js.map +1 -1
  423. package/dist/shadow/ssm.js +18 -72
  424. package/dist/shadow/ssm.js.map +1 -1
  425. package/dist/shadow/vsm.js +3 -3
  426. package/dist/shadow/vsm.js.map +1 -1
  427. package/dist/shapes/shape.js +44 -1
  428. package/dist/shapes/shape.js.map +1 -1
  429. package/dist/utility/buoyancy.js +287 -0
  430. package/dist/utility/buoyancy.js.map +1 -0
  431. package/dist/utility/physical.js +10 -1
  432. package/dist/utility/physical.js.map +1 -1
  433. package/dist/utility/pmrem.js +17 -43
  434. package/dist/utility/pmrem.js.map +1 -1
  435. package/dist/utility/sdf/bake.js +435 -0
  436. package/dist/utility/sdf/bake.js.map +1 -0
  437. package/dist/utility/sdf/bvh.js +576 -0
  438. package/dist/utility/sdf/bvh.js.map +1 -0
  439. package/dist/utility/serialization/manager.js +34 -6
  440. package/dist/utility/serialization/manager.js.map +1 -1
  441. package/dist/utility/serialization/scene/animation.js +46 -5
  442. package/dist/utility/serialization/scene/animation.js.map +1 -1
  443. package/dist/utility/serialization/scene/batch.js +11 -4
  444. package/dist/utility/serialization/scene/batch.js.map +1 -1
  445. package/dist/utility/serialization/scene/camera.js +87 -254
  446. package/dist/utility/serialization/scene/camera.js.map +1 -1
  447. package/dist/utility/serialization/scene/cloth.js +25 -0
  448. package/dist/utility/serialization/scene/cloth.js.map +1 -0
  449. package/dist/utility/serialization/scene/common.js +14 -6
  450. package/dist/utility/serialization/scene/common.js.map +1 -1
  451. package/dist/utility/serialization/scene/foliage.js +821 -0
  452. package/dist/utility/serialization/scene/foliage.js.map +1 -0
  453. package/dist/utility/serialization/scene/hair.js +11 -4
  454. package/dist/utility/serialization/scene/hair.js.map +1 -1
  455. package/dist/utility/serialization/scene/light.js +115 -7
  456. package/dist/utility/serialization/scene/light.js.map +1 -1
  457. package/dist/utility/serialization/scene/material.js +388 -220
  458. package/dist/utility/serialization/scene/material.js.map +1 -1
  459. package/dist/utility/serialization/scene/mesh.js +69 -4
  460. package/dist/utility/serialization/scene/mesh.js.map +1 -1
  461. package/dist/utility/serialization/scene/node.js +140 -5
  462. package/dist/utility/serialization/scene/node.js.map +1 -1
  463. package/dist/utility/serialization/scene/node_physics.js +1318 -0
  464. package/dist/utility/serialization/scene/node_physics.js.map +1 -0
  465. package/dist/utility/serialization/scene/particle.js +11 -4
  466. package/dist/utility/serialization/scene/particle.js.map +1 -1
  467. package/dist/utility/serialization/scene/physics.js +120 -0
  468. package/dist/utility/serialization/scene/physics.js.map +1 -0
  469. package/dist/utility/serialization/scene/primitive.js +124 -10
  470. package/dist/utility/serialization/scene/primitive.js.map +1 -1
  471. package/dist/utility/serialization/scene/scene.js +1687 -51
  472. package/dist/utility/serialization/scene/scene.js.map +1 -1
  473. package/dist/utility/serialization/scene/sprite.js +11 -4
  474. package/dist/utility/serialization/scene/sprite.js.map +1 -1
  475. package/dist/utility/serialization/scene/terrain.js +163 -33
  476. package/dist/utility/serialization/scene/terrain.js.map +1 -1
  477. package/dist/utility/serialization/scene/text.js +11 -4
  478. package/dist/utility/serialization/scene/text.js.map +1 -1
  479. package/dist/utility/serialization/scene/water.js +1543 -264
  480. package/dist/utility/serialization/scene/water.js.map +1 -1
  481. package/dist/utility/serialization/types.js.map +1 -1
  482. package/dist/utility/shprojector.js +10 -22
  483. package/dist/utility/shprojector.js.map +1 -1
  484. package/dist/utility/textures/foam.js +170 -0
  485. package/dist/utility/textures/foam.js.map +1 -0
  486. package/dist/utility/textures/ggxlut.js +17 -43
  487. package/dist/utility/textures/ggxlut.js.map +1 -1
  488. package/dist/utility/textures/ltcdata.js +4 -4
  489. package/dist/utility/textures/ltcdata.js.map +1 -1
  490. package/dist/utility/textures/ltclut.js +16 -6
  491. package/dist/utility/textures/ltclut.js.map +1 -1
  492. package/dist/utility/unsupported.js +24 -0
  493. package/dist/utility/unsupported.js.map +1 -0
  494. package/dist/values.js +13 -1
  495. package/dist/values.js.map +1 -1
  496. package/package.json +25 -12
  497. package/src/asset/loaders/ktx2/basis/LICENSE +201 -0
  498. package/src/asset/loaders/ktx2/basis/basis_transcoder.js +2 -0
  499. package/src/asset/loaders/ktx2/basis/basis_transcoder.wasm +0 -0
  500. package/src/asset/meshoptimizer/LICENSE +21 -0
  501. package/dist/animation/joint_dynamics/convex_collider.js +0 -320
  502. package/dist/animation/joint_dynamics/convex_collider.js.map +0 -1
@@ -1,9 +1,22 @@
1
- import { PBPrimitiveType } from '@zephyr3d/device';
2
1
  import { Vector3, retainObject, releaseObject, Matrix4x4, uint8ArrayToBase64, base64ToUint8Array } from '@zephyr3d/base';
3
2
  import { getDevice } from '../../app/api.js';
3
+ import { readPrimitiveAttribute, readPrimitiveIndices } from '../../render/primitive_readback.js';
4
4
  import { BoundingBox } from '../../utility/bounding_volume.js';
5
5
  import { updateColliderFromNode } from '../spring/spring_collider.js';
6
+ import { warnUnsupported } from '../../utility/unsupported.js';
6
7
 
8
+ function normalizeTargetWrapWeights(source, vertexCount) {
9
+ const result = new Float32Array(vertexCount);
10
+ result.fill(1);
11
+ if (!source) {
12
+ return result;
13
+ }
14
+ const count = Math.min(vertexCount, source.length);
15
+ for(let i = 0; i < count; i++){
16
+ result[i] = clamp(Number(source[i]) || 0, 0, 1);
17
+ }
18
+ return result;
19
+ }
7
20
  function encodeTypedArrayBase64(view) {
8
21
  return uint8ArrayToBase64(new Uint8Array(view.buffer, view.byteOffset, view.byteLength));
9
22
  }
@@ -67,68 +80,6 @@ function getInitialColliderBufferFloatCount(colliders, type, stride) {
67
80
  const count = (colliders ?? []).reduce((total, collider)=>total + (collider?.type === type ? 1 : 0), 0);
68
81
  return Math.max(1, count) * stride;
69
82
  }
70
- function getPrimitiveScalarByteSize(type) {
71
- switch(type){
72
- case PBPrimitiveType.I16:
73
- case PBPrimitiveType.I16_NORM:
74
- case PBPrimitiveType.U16:
75
- case PBPrimitiveType.U16_NORM:
76
- case PBPrimitiveType.F16:
77
- return 2;
78
- case PBPrimitiveType.I32:
79
- case PBPrimitiveType.I32_NORM:
80
- case PBPrimitiveType.U32:
81
- case PBPrimitiveType.U32_NORM:
82
- case PBPrimitiveType.F32:
83
- return 4;
84
- default:
85
- return 1;
86
- }
87
- }
88
- function readPrimitiveScalar(view, byteOffset, scalarType, normalized) {
89
- switch(scalarType){
90
- case PBPrimitiveType.I8:
91
- case PBPrimitiveType.I8_NORM:
92
- {
93
- const value = view.getInt8(byteOffset);
94
- return normalized ? Math.max(-1, value / 127) : value;
95
- }
96
- case PBPrimitiveType.U8:
97
- case PBPrimitiveType.U8_NORM:
98
- {
99
- const value = view.getUint8(byteOffset);
100
- return normalized ? value / 255 : value;
101
- }
102
- case PBPrimitiveType.I16:
103
- case PBPrimitiveType.I16_NORM:
104
- {
105
- const value = view.getInt16(byteOffset, true);
106
- return normalized ? Math.max(-1, value / 32767) : value;
107
- }
108
- case PBPrimitiveType.U16:
109
- case PBPrimitiveType.U16_NORM:
110
- {
111
- const value = view.getUint16(byteOffset, true);
112
- return normalized ? value / 65535 : value;
113
- }
114
- case PBPrimitiveType.I32:
115
- case PBPrimitiveType.I32_NORM:
116
- {
117
- const value = view.getInt32(byteOffset, true);
118
- return normalized ? Math.max(-1, value / 2147483647) : value;
119
- }
120
- case PBPrimitiveType.U32:
121
- case PBPrimitiveType.U32_NORM:
122
- {
123
- const value = view.getUint32(byteOffset, true);
124
- return normalized ? value / 4294967295 : value;
125
- }
126
- case PBPrimitiveType.F32:
127
- return view.getFloat32(byteOffset, true);
128
- default:
129
- throw new Error(`Unsupported vertex scalar type: ${scalarType}`);
130
- }
131
- }
132
83
  function distance3(positions, a, b) {
133
84
  const a0 = a * 3;
134
85
  const b0 = b * 3;
@@ -486,6 +437,7 @@ function createIntegrateProgram(device, workgroupSize) {
486
437
  this.sphereData = pb.float[0]().storageBufferReadonly(0);
487
438
  this.capsuleData = pb.float[0]().storageBufferReadonly(0);
488
439
  this.planeData = pb.float[0]().storageBufferReadonly(0);
440
+ this.boxData = pb.float[0]().storageBufferReadonly(0);
489
441
  this.vertexCount = pb.uint().uniform(0);
490
442
  this.deltaTime = pb.float().uniform(0);
491
443
  this.damping = pb.float().uniform(0);
@@ -493,6 +445,7 @@ function createIntegrateProgram(device, workgroupSize) {
493
445
  this.sphereCount = pb.uint().uniform(0);
494
446
  this.capsuleCount = pb.uint().uniform(0);
495
447
  this.planeCount = pb.uint().uniform(0);
448
+ this.boxCount = pb.uint().uniform(0);
496
449
  this.dynamicFriction = pb.float().uniform(0);
497
450
  this.staticFriction = pb.float().uniform(0);
498
451
  this.minDistance = pb.float().uniform(0);
@@ -633,6 +586,34 @@ function createIntegrateProgram(device, workgroupSize) {
633
586
  });
634
587
  });
635
588
  });
589
+ this.$for(pb.uint('b'), 0, this.boxCount, function() {
590
+ this.$l.boxBase = pb.mul(this.b, 16);
591
+ this.$l.boxCenter = pb.vec3(this.boxData.at(this.boxBase), this.boxData.at(pb.add(this.boxBase, 1)), this.boxData.at(pb.add(this.boxBase, 2)));
592
+ this.$l.boxHalf = pb.vec3(this.boxData.at(pb.add(this.boxBase, 3)), this.boxData.at(pb.add(this.boxBase, 4)), this.boxData.at(pb.add(this.boxBase, 5)));
593
+ this.$l.boxAxisX = pb.vec3(this.boxData.at(pb.add(this.boxBase, 6)), this.boxData.at(pb.add(this.boxBase, 7)), this.boxData.at(pb.add(this.boxBase, 8)));
594
+ this.$l.boxAxisY = pb.vec3(this.boxData.at(pb.add(this.boxBase, 9)), this.boxData.at(pb.add(this.boxBase, 10)), this.boxData.at(pb.add(this.boxBase, 11)));
595
+ this.$l.boxAxisZ = pb.vec3(this.boxData.at(pb.add(this.boxBase, 12)), this.boxData.at(pb.add(this.boxBase, 13)), this.boxData.at(pb.add(this.boxBase, 14)));
596
+ this.$l.boxRel = pb.sub(this.next, this.boxCenter);
597
+ this.$l.boxLocal = pb.vec3(pb.dot(this.boxRel, this.boxAxisX), pb.dot(this.boxRel, this.boxAxisY), pb.dot(this.boxRel, this.boxAxisZ));
598
+ this.$l.boxPen = pb.sub(this.boxHalf, pb.abs(this.boxLocal));
599
+ this.$if(pb.and(pb.and(pb.greaterThan(this.boxPen.x, 0), pb.greaterThan(this.boxPen.y, 0)), pb.greaterThan(this.boxPen.z, 0)), function() {
600
+ this.$l.boxAxis = this.boxAxisX;
601
+ this.$l.boxDepth = this.boxPen.x;
602
+ this.$l.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.x, 0));
603
+ this.$if(pb.lessThan(this.boxPen.y, this.boxDepth), function() {
604
+ this.boxAxis = this.boxAxisY;
605
+ this.boxDepth = this.boxPen.y;
606
+ this.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.y, 0));
607
+ });
608
+ this.$if(pb.lessThan(this.boxPen.z, this.boxDepth), function() {
609
+ this.boxAxis = this.boxAxisZ;
610
+ this.boxDepth = this.boxPen.z;
611
+ this.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.z, 0));
612
+ });
613
+ this.$l.boxSign = this.boxSign;
614
+ this.next = pb.add(this.next, pb.mul(this.boxAxis, pb.mul(this.boxSign, this.boxDepth)));
615
+ });
616
+ });
636
617
  this.next = pb.add(pb.mul(this.next, this.freeWeight), pb.mul(this.rest, this.pinWeight));
637
618
  this.$l.prevOut = pb.add(pb.mul(this.current, this.freeWeight), pb.mul(this.rest, this.pinWeight));
638
619
  this.prevPositions.setAt(this.base, this.prevOut.x);
@@ -666,6 +647,7 @@ function createConstraintProgram(device, workgroupSize) {
666
647
  this.sphereData = pb.float[0]().storageBufferReadonly(0);
667
648
  this.capsuleData = pb.float[0]().storageBufferReadonly(0);
668
649
  this.planeData = pb.float[0]().storageBufferReadonly(0);
650
+ this.boxData = pb.float[0]().storageBufferReadonly(0);
669
651
  this.vertexCount = pb.uint().uniform(0);
670
652
  this.maxNeighbors = pb.uint().uniform(0);
671
653
  this.stiffness = pb.float().uniform(0);
@@ -673,6 +655,7 @@ function createConstraintProgram(device, workgroupSize) {
673
655
  this.sphereCount = pb.uint().uniform(0);
674
656
  this.capsuleCount = pb.uint().uniform(0);
675
657
  this.planeCount = pb.uint().uniform(0);
658
+ this.boxCount = pb.uint().uniform(0);
676
659
  this.dynamicFriction = pb.float().uniform(0);
677
660
  this.staticFriction = pb.float().uniform(0);
678
661
  this.minDistance = pb.float().uniform(0);
@@ -760,6 +743,34 @@ function createConstraintProgram(device, workgroupSize) {
760
743
  this.corrected = pb.sub(this.corrected, pb.mul(this.planeNormal, this.planeDistance));
761
744
  });
762
745
  });
746
+ this.$for(pb.uint('b'), 0, this.boxCount, function() {
747
+ this.$l.boxBase = pb.mul(this.b, 16);
748
+ this.$l.boxCenter = pb.vec3(this.boxData.at(this.boxBase), this.boxData.at(pb.add(this.boxBase, 1)), this.boxData.at(pb.add(this.boxBase, 2)));
749
+ this.$l.boxHalf = pb.vec3(this.boxData.at(pb.add(this.boxBase, 3)), this.boxData.at(pb.add(this.boxBase, 4)), this.boxData.at(pb.add(this.boxBase, 5)));
750
+ this.$l.boxAxisX = pb.vec3(this.boxData.at(pb.add(this.boxBase, 6)), this.boxData.at(pb.add(this.boxBase, 7)), this.boxData.at(pb.add(this.boxBase, 8)));
751
+ this.$l.boxAxisY = pb.vec3(this.boxData.at(pb.add(this.boxBase, 9)), this.boxData.at(pb.add(this.boxBase, 10)), this.boxData.at(pb.add(this.boxBase, 11)));
752
+ this.$l.boxAxisZ = pb.vec3(this.boxData.at(pb.add(this.boxBase, 12)), this.boxData.at(pb.add(this.boxBase, 13)), this.boxData.at(pb.add(this.boxBase, 14)));
753
+ this.$l.boxRel = pb.sub(this.corrected, this.boxCenter);
754
+ this.$l.boxLocal = pb.vec3(pb.dot(this.boxRel, this.boxAxisX), pb.dot(this.boxRel, this.boxAxisY), pb.dot(this.boxRel, this.boxAxisZ));
755
+ this.$l.boxPen = pb.sub(this.boxHalf, pb.abs(this.boxLocal));
756
+ this.$if(pb.and(pb.and(pb.greaterThan(this.boxPen.x, 0), pb.greaterThan(this.boxPen.y, 0)), pb.greaterThan(this.boxPen.z, 0)), function() {
757
+ this.$l.boxAxis = this.boxAxisX;
758
+ this.$l.boxDepth = this.boxPen.x;
759
+ this.$l.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.x, 0));
760
+ this.$if(pb.lessThan(this.boxPen.y, this.boxDepth), function() {
761
+ this.boxAxis = this.boxAxisY;
762
+ this.boxDepth = this.boxPen.y;
763
+ this.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.y, 0));
764
+ });
765
+ this.$if(pb.lessThan(this.boxPen.z, this.boxDepth), function() {
766
+ this.boxAxis = this.boxAxisZ;
767
+ this.boxDepth = this.boxPen.z;
768
+ this.boxSign = pb.select(pb.float(1), pb.float(-1), pb.greaterThanEqual(this.boxLocal.z, 0));
769
+ });
770
+ this.$l.boxSign = this.boxSign;
771
+ this.corrected = pb.add(this.corrected, pb.mul(this.boxAxis, pb.mul(this.boxSign, this.boxDepth)));
772
+ });
773
+ });
763
774
  this.positions.setAt(this.base, this.corrected.x);
764
775
  this.positions.setAt(pb.add(this.base, 1), this.corrected.y);
765
776
  this.positions.setAt(pb.add(this.base, 2), this.corrected.z);
@@ -883,45 +894,11 @@ async function readPositionDataFromPrimitive(primitive) {
883
894
  return positions;
884
895
  }
885
896
  async function readVertexAttributeDataFromPrimitive(primitive, semantic, componentCount) {
886
- const info = primitive.getVertexBufferInfo(semantic);
887
- if (!info || !info.type.isPrimitiveType() || info.type.cols < componentCount) {
888
- return null;
889
- }
890
- const vertexCount = primitive.getNumVertices();
891
- if (vertexCount <= 0) {
892
- return null;
893
- }
894
- const bytes = await info.buffer.getBufferSubData();
895
- const result = new Float32Array(vertexCount * componentCount);
896
- const scalarType = info.type.scalarType;
897
- const normalized = info.type.normalized;
898
- const componentByteSize = getPrimitiveScalarByteSize(scalarType);
899
- const baseByteOffset = info.drawOffset + info.offset;
900
- if (scalarType === PBPrimitiveType.F32 && !normalized && baseByteOffset % 4 === 0 && info.stride % 4 === 0) {
901
- const raw = new Float32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);
902
- const stride = info.stride >> 2;
903
- const srcOffset = baseByteOffset >> 2;
904
- for(let i = 0; i < vertexCount; i++){
905
- const src = srcOffset + i * stride;
906
- const dst = i * componentCount;
907
- for(let c = 0; c < componentCount; c++){
908
- result[dst + c] = raw[src + c];
909
- }
910
- }
911
- return result;
912
- }
913
- if (scalarType === PBPrimitiveType.F16) {
914
- throw new Error(`GPU cloth initialization failed: unsupported ${semantic} attribute format.`);
915
- }
916
- const view = new DataView(bytes.buffer, bytes.byteOffset, bytes.byteLength);
917
- for(let i = 0; i < vertexCount; i++){
918
- const src = baseByteOffset + i * info.stride;
919
- const dst = i * componentCount;
920
- for(let c = 0; c < componentCount; c++){
921
- result[dst + c] = readPrimitiveScalar(view, src + c * componentByteSize, scalarType, normalized);
922
- }
897
+ try {
898
+ return await readPrimitiveAttribute(primitive, semantic, componentCount);
899
+ } catch (err) {
900
+ throw new Error(`GPU cloth initialization failed: ${err instanceof Error ? err.message : err}`);
923
901
  }
924
- return result;
925
902
  }
926
903
  async function readSkinningDataFromPrimitive(primitive) {
927
904
  try {
@@ -934,42 +911,60 @@ async function readSkinningDataFromPrimitive(primitive) {
934
911
  }
935
912
  return {
936
913
  blendIndices,
937
- blendWeights
914
+ blendWeights,
915
+ influenceCount: 4
938
916
  };
939
917
  } catch {
940
918
  return null;
941
919
  }
942
920
  }
943
- function buildNonIndexedTriangles(primitive, vertexCount) {
944
- if (primitive.primitiveType !== 'triangle-list') {
945
- throw new Error('GPU cloth initialization failed: only triangle-list primitive is supported.');
921
+ async function readSkinningDataFromMesh(mesh) {
922
+ if (!mesh.primitive) {
923
+ return null;
946
924
  }
947
- const start = primitive.indexStart;
948
- const count = primitive.indexCount;
949
- if (count <= 0 || count % 3 !== 0 || start < 0 || start + count > vertexCount) {
950
- throw new Error('GPU cloth initialization failed: invalid non-indexed triangle range.');
925
+ const base = await readSkinningDataFromPrimitive(mesh.primitive);
926
+ if (!base) {
927
+ return null;
951
928
  }
952
- const indices = new Uint32Array(count);
953
- for(let i = 0; i < count; i++){
954
- indices[i] = start + i;
929
+ const extra = mesh.getSkinInfluenceData?.() ?? null;
930
+ const influenceCount = Math.max(4, Math.floor(Number(extra?.influenceCount) || 4));
931
+ if (!extra || influenceCount <= 4) {
932
+ return base;
933
+ }
934
+ const vertexCount = mesh.primitive.getNumVertices();
935
+ const pairCount = Math.ceil((influenceCount - 4) / 2);
936
+ if (extra.data.length < vertexCount * pairCount * 4) {
937
+ return base;
938
+ }
939
+ const blendIndices = new Float32Array(vertexCount * influenceCount);
940
+ const blendWeights = new Float32Array(vertexCount * influenceCount);
941
+ for(let vertex = 0; vertex < vertexCount; vertex++){
942
+ const baseSource = vertex * 4;
943
+ const target = vertex * influenceCount;
944
+ blendIndices.set(base.blendIndices.subarray(baseSource, baseSource + 4), target);
945
+ blendWeights.set(base.blendWeights.subarray(baseSource, baseSource + 4), target);
946
+ for(let influence = 4; influence < influenceCount; influence++){
947
+ const extraInfluence = influence - 4;
948
+ const source = (vertex * pairCount + (extraInfluence >> 1)) * 4 + (extraInfluence & 1) * 2;
949
+ blendIndices[target + influence] = Number(extra.data[source]) || 0;
950
+ blendWeights[target + influence] = Number(extra.data[source + 1]) || 0;
951
+ }
955
952
  }
956
- return indices;
953
+ return {
954
+ blendIndices,
955
+ blendWeights,
956
+ influenceCount
957
+ };
957
958
  }
958
- async function readIndexDataFromPrimitive(primitive, vertexCount) {
959
- const indexBuffer = primitive.getIndexBuffer();
960
- if (!indexBuffer) {
961
- return buildNonIndexedTriangles(primitive, vertexCount);
962
- }
963
- if (primitive.primitiveType !== 'triangle-list') {
964
- throw new Error('GPU cloth initialization failed: only triangle-list primitive is supported.');
965
- }
966
- const bytes = await indexBuffer.getBufferSubData();
967
- if (indexBuffer.indexType.primitiveType === PBPrimitiveType.U16) {
968
- const src = new Uint16Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 1);
969
- return new Uint16Array(src);
959
+ /**
960
+ * The primitive's full-detail triangles. With mesh LODs the index buffer holds
961
+ * every level in its own range; reading all of it would stack them together.
962
+ */ async function readIndexDataFromPrimitive(primitive) {
963
+ try {
964
+ return await readPrimitiveIndices(primitive);
965
+ } catch (err) {
966
+ throw new Error(`GPU cloth initialization failed: ${err instanceof Error ? err.message : err}`);
970
967
  }
971
- const src = new Uint32Array(bytes.buffer, bytes.byteOffset, bytes.byteLength >> 2);
972
- return new Uint32Array(src);
973
968
  }
974
969
  function createWrapDeformerProgram(device, workgroupSize) {
975
970
  const program = device.buildComputeProgram({
@@ -983,11 +978,15 @@ function createWrapDeformerProgram(device, workgroupSize) {
983
978
  this.sourceTriangleIndices = pb.uint[0]().storageBufferReadonly(0);
984
979
  this.sourceBarycentrics = pb.float[0]().storageBufferReadonly(0);
985
980
  this.targetLocalOffsets = pb.float[0]().storageBufferReadonly(0);
981
+ this.targetSkinPositions = pb.float[0]().storageBufferReadonly(0);
982
+ this.targetSkinNormals = pb.float[0]().storageBufferReadonly(0);
983
+ this.targetWrapWeights = pb.float[0]().storageBufferReadonly(0);
986
984
  this.targetPositions = pb.float[0]().storageBuffer(0);
987
985
  this.targetNormals = pb.float[0]().storageBuffer(0);
988
986
  this.vertexCount = pb.uint().uniform(0);
989
987
  this.sourceToTargetMatrix = pb.mat4().uniform(0);
990
988
  this.minDistance = pb.float().uniform(0);
989
+ this.hasTargetNormals = pb.float().uniform(0);
991
990
  pb.main(function() {
992
991
  this.$l.vertex = this.$builtins.globalInvocationId.x;
993
992
  this.$if(pb.lessThan(this.vertex, this.vertexCount), function() {
@@ -1052,6 +1051,18 @@ function createWrapDeformerProgram(device, workgroupSize) {
1052
1051
  });
1053
1052
  this.$l.localOffset = pb.vec3(this.targetLocalOffsets.at(this.targetBase), this.targetLocalOffsets.at(pb.add(this.targetBase, 1)), this.targetLocalOffsets.at(pb.add(this.targetBase, 2)));
1054
1053
  this.$l.deformedPosition = pb.add(this.basePoint, pb.add(pb.mul(this.tangent, this.localOffset.x), pb.mul(this.bitangent, this.localOffset.y), pb.mul(this.normal, this.localOffset.z)));
1054
+ this.$l.wrapWeight = this.targetWrapWeights.at(this.vertex);
1055
+ this.$l.skinPosition = pb.vec3(this.targetSkinPositions.at(this.targetBase), this.targetSkinPositions.at(pb.add(this.targetBase, 1)), this.targetSkinPositions.at(pb.add(this.targetBase, 2)));
1056
+ this.deformedPosition = pb.add(pb.mul(this.skinPosition, pb.sub(1, this.wrapWeight)), pb.mul(this.deformedPosition, this.wrapWeight));
1057
+ this.$l.skinNormal = pb.vec3(this.targetSkinNormals.at(this.targetBase), this.targetSkinNormals.at(pb.add(this.targetBase, 1)), this.targetSkinNormals.at(pb.add(this.targetBase, 2)));
1058
+ this.$l.normalWeight = pb.max(this.wrapWeight, pb.sub(1, this.hasTargetNormals));
1059
+ this.normal = pb.add(pb.mul(this.skinNormal, pb.sub(1, this.normalWeight)), pb.mul(this.normal, this.normalWeight));
1060
+ this.normalLen = pb.length(this.normal);
1061
+ this.$if(pb.greaterThan(this.normalLen, this.minDistance), function() {
1062
+ this.normal = pb.div(this.normal, this.normalLen);
1063
+ }).$else(function() {
1064
+ this.normal = pb.vec3(0, 1, 0);
1065
+ });
1055
1066
  this.targetPositions.setAt(this.targetBase, this.deformedPosition.x);
1056
1067
  this.targetPositions.setAt(pb.add(this.targetBase, 1), this.deformedPosition.y);
1057
1068
  this.targetPositions.setAt(pb.add(this.targetBase, 2), this.deformedPosition.z);
@@ -1085,6 +1096,28 @@ function getWrapSourceToTargetMatrix(source, target, out) {
1085
1096
  }
1086
1097
  return Matrix4x4.multiplyAffine(target.invWorldMatrix, source.worldMatrix, out);
1087
1098
  }
1099
+ /** @internal Conservative bounds for the blend of wrapped and skinned target vertices. */ function calculateGPUClothWrapBoundingBox(sourceBBox, sourceToTargetMatrix, skinPositions, offsetDistances, wrapWeights) {
1100
+ const wrappedBox = sourceBBox.transform(sourceToTargetMatrix);
1101
+ let minX = Number.POSITIVE_INFINITY;
1102
+ let minY = Number.POSITIVE_INFINITY;
1103
+ let minZ = Number.POSITIVE_INFINITY;
1104
+ let maxX = Number.NEGATIVE_INFINITY;
1105
+ let maxY = Number.NEGATIVE_INFINITY;
1106
+ let maxZ = Number.NEGATIVE_INFINITY;
1107
+ for(let vertex = 0; vertex < wrapWeights.length; vertex++){
1108
+ const base = vertex * 3;
1109
+ const weight = wrapWeights[vertex];
1110
+ const skinWeight = 1 - weight;
1111
+ const radius = weight * offsetDistances[vertex] + 0.001;
1112
+ minX = Math.min(minX, skinWeight * skinPositions[base] + weight * wrappedBox.minPoint.x - radius);
1113
+ minY = Math.min(minY, skinWeight * skinPositions[base + 1] + weight * wrappedBox.minPoint.y - radius);
1114
+ minZ = Math.min(minZ, skinWeight * skinPositions[base + 2] + weight * wrappedBox.minPoint.z - radius);
1115
+ maxX = Math.max(maxX, skinWeight * skinPositions[base] + weight * wrappedBox.maxPoint.x + radius);
1116
+ maxY = Math.max(maxY, skinWeight * skinPositions[base + 1] + weight * wrappedBox.maxPoint.y + radius);
1117
+ maxZ = Math.max(maxZ, skinWeight * skinPositions[base + 2] + weight * wrappedBox.maxPoint.z + radius);
1118
+ }
1119
+ return new BoundingBox(new Vector3(minX, minY, minZ), new Vector3(maxX, maxY, maxZ));
1120
+ }
1088
1121
  class GPUClothWrapBinding {
1089
1122
  _device;
1090
1123
  _source;
@@ -1093,17 +1126,28 @@ class GPUClothWrapBinding {
1093
1126
  _wrapTriangleIndexBuffer;
1094
1127
  _wrapBarycentricBuffer;
1095
1128
  _wrapLocalOffsetBuffer;
1129
+ _targetSkinPositionBuffer;
1130
+ _targetSkinNormalBuffer;
1131
+ _targetWrapWeightBuffer;
1096
1132
  _program;
1097
1133
  _bindGroup;
1098
1134
  _workgroupCount;
1099
- _maxOffsetDistance;
1135
+ _targetOffsetDistances;
1136
+ _targetWrapWeights;
1100
1137
  _sourceToTargetMatrix;
1101
1138
  _positionBuffer;
1102
1139
  _normalBuffer;
1103
1140
  _originalPositionBuffer;
1104
1141
  _originalNormalBuffer;
1105
1142
  _restoreSkinning;
1106
- constructor(device, source, target, targetPrimitive, wrapTriangleIndexBuffer, wrapBarycentricBuffer, wrapLocalOffsetBuffer, program, bindGroup, positionBuffer, normalBuffer, originalPositionBuffer, originalNormalBuffer, workgroupCount, maxOffsetDistance, restoreSkinning){
1143
+ _targetBasePositions;
1144
+ _targetBaseNormals;
1145
+ _targetBlendIndices;
1146
+ _targetBlendWeights;
1147
+ _targetSkinnedPositions;
1148
+ _targetSkinnedNormals;
1149
+ _hasPartialWrap;
1150
+ constructor(device, source, target, targetPrimitive, wrapTriangleIndexBuffer, wrapBarycentricBuffer, wrapLocalOffsetBuffer, targetSkinPositionBuffer, targetSkinNormalBuffer, targetWrapWeightBuffer, program, bindGroup, positionBuffer, normalBuffer, originalPositionBuffer, originalNormalBuffer, workgroupCount, targetOffsetDistances, restoreSkinning, targetBasePositions, targetBaseNormals, targetBlendIndices, targetBlendWeights, targetWrapWeights){
1107
1151
  this._device = device;
1108
1152
  this._source = source;
1109
1153
  this._target = target;
@@ -1111,20 +1155,31 @@ class GPUClothWrapBinding {
1111
1155
  this._wrapTriangleIndexBuffer = wrapTriangleIndexBuffer;
1112
1156
  this._wrapBarycentricBuffer = wrapBarycentricBuffer;
1113
1157
  this._wrapLocalOffsetBuffer = wrapLocalOffsetBuffer;
1158
+ this._targetSkinPositionBuffer = targetSkinPositionBuffer;
1159
+ this._targetSkinNormalBuffer = targetSkinNormalBuffer;
1160
+ this._targetWrapWeightBuffer = targetWrapWeightBuffer;
1114
1161
  this._program = program;
1115
1162
  this._bindGroup = bindGroup;
1116
1163
  this._workgroupCount = workgroupCount;
1117
- this._maxOffsetDistance = maxOffsetDistance;
1164
+ this._targetOffsetDistances = targetOffsetDistances;
1165
+ this._targetWrapWeights = targetWrapWeights;
1118
1166
  this._sourceToTargetMatrix = new Matrix4x4();
1119
1167
  this._positionBuffer = positionBuffer;
1120
1168
  this._normalBuffer = normalBuffer;
1121
1169
  this._originalPositionBuffer = originalPositionBuffer;
1122
1170
  this._originalNormalBuffer = originalNormalBuffer;
1123
1171
  this._restoreSkinning = restoreSkinning;
1124
- }
1125
- static async create(device, source, sourcePositionBuffer, sourceRestPositions, sourceIndexData, target, workgroupSize) {
1172
+ this._targetBasePositions = targetBasePositions;
1173
+ this._targetBaseNormals = targetBaseNormals;
1174
+ this._targetBlendIndices = targetBlendIndices;
1175
+ this._targetBlendWeights = targetBlendWeights;
1176
+ this._targetSkinnedPositions = new Float32Array(targetBasePositions);
1177
+ this._targetSkinnedNormals = new Float32Array(targetBaseNormals);
1178
+ this._hasPartialWrap = targetWrapWeights.some((weight)=>weight < 1 - 1e-6);
1179
+ }
1180
+ static async create(device, source, sourcePositionBuffer, sourceRestPositions, sourceIndexData, target, workgroupSize, targetWrapWeights) {
1126
1181
  const data = await GPUClothWrapBinding.createBindingData(source, sourceRestPositions, sourceIndexData, target);
1127
- return GPUClothWrapBinding.createFromData(device, source, sourcePositionBuffer, sourceRestPositions, sourceIndexData, target, workgroupSize, data);
1182
+ return GPUClothWrapBinding.createFromData(device, source, sourcePositionBuffer, sourceRestPositions, sourceIndexData, target, workgroupSize, data, targetWrapWeights);
1128
1183
  }
1129
1184
  static async createBindingData(source, sourceRestPositions, sourceIndexData, target) {
1130
1185
  if (!target?.primitive) {
@@ -1227,7 +1282,7 @@ class GPUClothWrapBinding {
1227
1282
  targetLocalOffsets: encodeTypedArrayBase64(targetLocalOffsets)
1228
1283
  };
1229
1284
  }
1230
- static createFromData(device, source, sourcePositionBuffer, sourceRestPositions, _sourceIndexData, target, workgroupSize, data) {
1285
+ static async createFromData(device, source, sourcePositionBuffer, sourceRestPositions, _sourceIndexData, target, workgroupSize, data, targetWrapWeightSource) {
1231
1286
  if (!target?.primitive) {
1232
1287
  throw new Error('GPU cloth wrap failed: target mesh has no primitive.');
1233
1288
  }
@@ -1236,11 +1291,24 @@ class GPUClothWrapBinding {
1236
1291
  if (!isWrapBindingDataCompatible(data, sourceRestPositions, vertexCount)) {
1237
1292
  throw new Error('GPU cloth wrap failed: binding cache is incompatible with current meshes.');
1238
1293
  }
1294
+ const [targetBasePositions, targetBaseNormalsSource, targetSkinningData] = await Promise.all([
1295
+ readPositionDataFromPrimitive(targetPrimitive),
1296
+ readVertexAttributeDataFromPrimitive(targetPrimitive, 'normal', 3),
1297
+ readSkinningDataFromMesh(target)
1298
+ ]);
1239
1299
  const expectedElementCount = vertexCount * 3;
1300
+ const hasTargetNormals = !!targetBaseNormalsSource;
1301
+ const targetBaseNormals = targetBaseNormalsSource ?? new Float32Array(expectedElementCount);
1302
+ const targetWrapWeights = normalizeTargetWrapWeights(targetWrapWeightSource, vertexCount);
1240
1303
  const influenceElementCount = vertexCount * data.influenceCount;
1241
1304
  const wrapSourceTriangleIndices = decodeTypedArrayFromBase64(Uint32Array, data.sourceTriangleIndices, influenceElementCount);
1242
1305
  const wrapSourceBarycentrics = decodeTypedArrayFromBase64(Float32Array, data.sourceBarycentrics, influenceElementCount);
1243
1306
  const wrapTargetLocalOffsets = decodeTypedArrayFromBase64(Float32Array, data.targetLocalOffsets, expectedElementCount);
1307
+ const targetOffsetDistances = new Float32Array(vertexCount);
1308
+ for(let vertex = 0; vertex < vertexCount; vertex++){
1309
+ const base = vertex * 3;
1310
+ targetOffsetDistances[vertex] = Math.hypot(wrapTargetLocalOffsets[base], wrapTargetLocalOffsets[base + 1], wrapTargetLocalOffsets[base + 2]);
1311
+ }
1244
1312
  const positionBuffer = device.createVertexBuffer('position_f32x3', new Float32Array(expectedElementCount), {
1245
1313
  storage: true,
1246
1314
  managed: false
@@ -1276,6 +1344,27 @@ class GPUClothWrapBinding {
1276
1344
  managed: false
1277
1345
  });
1278
1346
  wrapLocalOffsetBuffer.bufferSubData(0, wrapTargetLocalOffsets);
1347
+ const targetSkinPositionBuffer = device.createBuffer(targetBasePositions.byteLength, {
1348
+ usage: 'uniform',
1349
+ storage: true,
1350
+ dynamic: false,
1351
+ managed: false
1352
+ });
1353
+ targetSkinPositionBuffer.bufferSubData(0, targetBasePositions);
1354
+ const targetSkinNormalBuffer = device.createBuffer(targetBaseNormals.byteLength, {
1355
+ usage: 'uniform',
1356
+ storage: true,
1357
+ dynamic: false,
1358
+ managed: false
1359
+ });
1360
+ targetSkinNormalBuffer.bufferSubData(0, targetBaseNormals);
1361
+ const targetWrapWeightBuffer = device.createBuffer(targetWrapWeights.byteLength, {
1362
+ usage: 'uniform',
1363
+ storage: true,
1364
+ dynamic: false,
1365
+ managed: false
1366
+ });
1367
+ targetWrapWeightBuffer.bufferSubData(0, targetWrapWeights);
1279
1368
  const program = createWrapDeformerProgram(device, workgroupSize);
1280
1369
  if (!program) {
1281
1370
  throw new Error('GPU cloth wrap failed: could not create compute program.');
@@ -1285,12 +1374,16 @@ class GPUClothWrapBinding {
1285
1374
  bindGroup.setBuffer('sourceTriangleIndices', wrapTriangleIndexBuffer);
1286
1375
  bindGroup.setBuffer('sourceBarycentrics', wrapBarycentricBuffer);
1287
1376
  bindGroup.setBuffer('targetLocalOffsets', wrapLocalOffsetBuffer);
1377
+ bindGroup.setBuffer('targetSkinPositions', targetSkinPositionBuffer);
1378
+ bindGroup.setBuffer('targetSkinNormals', targetSkinNormalBuffer);
1379
+ bindGroup.setBuffer('targetWrapWeights', targetWrapWeightBuffer);
1288
1380
  bindGroup.setBuffer('targetPositions', positionBuffer);
1289
1381
  bindGroup.setBuffer('targetNormals', normalBuffer);
1290
1382
  const sourceToTargetBindMatrix = getWrapSourceToTargetMatrix(source, target);
1291
1383
  bindGroup.setValue('vertexCount', vertexCount);
1292
1384
  bindGroup.setValue('sourceToTargetMatrix', sourceToTargetBindMatrix);
1293
1385
  bindGroup.setValue('minDistance', 1e-5);
1386
+ bindGroup.setValue('hasTargetNormals', hasTargetNormals ? 1 : 0);
1294
1387
  const originalPositionBuffer = targetPrimitive.getVertexBuffer('position');
1295
1388
  const originalNormalBuffer = targetPrimitive.getVertexBuffer('normal');
1296
1389
  retainObject(originalPositionBuffer);
@@ -1306,11 +1399,12 @@ class GPUClothWrapBinding {
1306
1399
  target.setBoneMatrices?.(null);
1307
1400
  target.setAnimatedBoundingBox?.(null);
1308
1401
  }
1309
- const binding = new GPUClothWrapBinding(device, source, target, targetPrimitive, wrapTriangleIndexBuffer, wrapBarycentricBuffer, wrapLocalOffsetBuffer, program, bindGroup, positionBuffer, normalBuffer, originalPositionBuffer, originalNormalBuffer, Math.max(1, Math.ceil(vertexCount / workgroupSize)), Math.max(0, Number(data.maxOffsetDistance) || 0), restoreSkinning);
1402
+ const binding = new GPUClothWrapBinding(device, source, target, targetPrimitive, wrapTriangleIndexBuffer, wrapBarycentricBuffer, wrapLocalOffsetBuffer, targetSkinPositionBuffer, targetSkinNormalBuffer, targetWrapWeightBuffer, program, bindGroup, positionBuffer, normalBuffer, originalPositionBuffer, originalNormalBuffer, Math.max(1, Math.ceil(vertexCount / workgroupSize)), targetOffsetDistances, restoreSkinning, targetBasePositions, targetBaseNormals, targetSkinningData?.blendIndices ?? null, targetSkinningData?.blendWeights ?? null, targetWrapWeights);
1310
1403
  binding.update();
1311
1404
  return binding;
1312
1405
  }
1313
1406
  update() {
1407
+ this.updateTargetSkinning();
1314
1408
  getWrapSourceToTargetMatrix(this._source, this._target, this._sourceToTargetMatrix);
1315
1409
  this._bindGroup.setValue('sourceToTargetMatrix', this._sourceToTargetMatrix);
1316
1410
  this._device.setProgram(this._program);
@@ -1324,6 +1418,9 @@ class GPUClothWrapBinding {
1324
1418
  this._wrapTriangleIndexBuffer.dispose();
1325
1419
  this._wrapBarycentricBuffer.dispose();
1326
1420
  this._wrapLocalOffsetBuffer.dispose();
1421
+ this._targetSkinPositionBuffer.dispose();
1422
+ this._targetSkinNormalBuffer.dispose();
1423
+ this._targetWrapWeightBuffer.dispose();
1327
1424
  if (this._targetPrimitive) {
1328
1425
  this._targetPrimitive.removeVertexBuffer('position');
1329
1426
  if (this._originalPositionBuffer) {
@@ -1343,73 +1440,31 @@ class GPUClothWrapBinding {
1343
1440
  this._target.suspendSkinning = this._restoreSkinning;
1344
1441
  }
1345
1442
  }
1443
+ updateTargetSkinning() {
1444
+ if (!this._hasPartialWrap) {
1445
+ return;
1446
+ }
1447
+ const skeletonId = String(this._target?.skeletonName ?? '');
1448
+ const skeleton = skeletonId && typeof this._target?.findSkeletonById === 'function' ? this._target.findSkeletonById(skeletonId) : null;
1449
+ if (skeleton?.skinPositionsToLocal && this._targetBlendIndices && this._targetBlendWeights && this._target?.invWorldMatrix) {
1450
+ skeleton.skinPositionsToLocal(this._targetBasePositions, this._targetBlendIndices, this._targetBlendWeights, this._target.invWorldMatrix, this._targetSkinnedPositions);
1451
+ if (skeleton.skinDirectionsToLocal && this._targetBaseNormals.length > 0) {
1452
+ skeleton.skinDirectionsToLocal(this._targetBaseNormals, this._targetBlendIndices, this._targetBlendWeights, this._target.invWorldMatrix, this._targetSkinnedNormals);
1453
+ }
1454
+ } else {
1455
+ this._targetSkinnedPositions.set(this._targetBasePositions);
1456
+ this._targetSkinnedNormals.set(this._targetBaseNormals);
1457
+ }
1458
+ this._targetSkinPositionBuffer.bufferSubData(0, this._targetSkinnedPositions);
1459
+ this._targetSkinNormalBuffer.bufferSubData(0, this._targetSkinnedNormals);
1460
+ }
1346
1461
  updateBoundingBox() {
1347
1462
  const sourceBBox = this._source?.getAnimatedBoundingBox?.() ?? this._source?.primitive?.getBoundingVolume?.()?.toAABB?.() ?? null;
1348
1463
  if (!sourceBBox) {
1349
1464
  return;
1350
1465
  }
1351
- let minX = Number.POSITIVE_INFINITY;
1352
- let minY = Number.POSITIVE_INFINITY;
1353
- let minZ = Number.POSITIVE_INFINITY;
1354
- let maxX = Number.NEGATIVE_INFINITY;
1355
- let maxY = Number.NEGATIVE_INFINITY;
1356
- let maxZ = Number.NEGATIVE_INFINITY;
1357
1466
  getWrapSourceToTargetMatrix(this._source, this._target, this._sourceToTargetMatrix);
1358
- const corners = [
1359
- [
1360
- sourceBBox.minPoint.x,
1361
- sourceBBox.minPoint.y,
1362
- sourceBBox.minPoint.z
1363
- ],
1364
- [
1365
- sourceBBox.minPoint.x,
1366
- sourceBBox.minPoint.y,
1367
- sourceBBox.maxPoint.z
1368
- ],
1369
- [
1370
- sourceBBox.minPoint.x,
1371
- sourceBBox.maxPoint.y,
1372
- sourceBBox.minPoint.z
1373
- ],
1374
- [
1375
- sourceBBox.minPoint.x,
1376
- sourceBBox.maxPoint.y,
1377
- sourceBBox.maxPoint.z
1378
- ],
1379
- [
1380
- sourceBBox.maxPoint.x,
1381
- sourceBBox.minPoint.y,
1382
- sourceBBox.minPoint.z
1383
- ],
1384
- [
1385
- sourceBBox.maxPoint.x,
1386
- sourceBBox.minPoint.y,
1387
- sourceBBox.maxPoint.z
1388
- ],
1389
- [
1390
- sourceBBox.maxPoint.x,
1391
- sourceBBox.maxPoint.y,
1392
- sourceBBox.minPoint.z
1393
- ],
1394
- [
1395
- sourceBBox.maxPoint.x,
1396
- sourceBBox.maxPoint.y,
1397
- sourceBBox.maxPoint.z
1398
- ]
1399
- ];
1400
- for (const corner of corners){
1401
- const x = this._sourceToTargetMatrix[0] * corner[0] + this._sourceToTargetMatrix[4] * corner[1] + this._sourceToTargetMatrix[8] * corner[2] + this._sourceToTargetMatrix[12];
1402
- const y = this._sourceToTargetMatrix[1] * corner[0] + this._sourceToTargetMatrix[5] * corner[1] + this._sourceToTargetMatrix[9] * corner[2] + this._sourceToTargetMatrix[13];
1403
- const z = this._sourceToTargetMatrix[2] * corner[0] + this._sourceToTargetMatrix[6] * corner[1] + this._sourceToTargetMatrix[10] * corner[2] + this._sourceToTargetMatrix[14];
1404
- minX = Math.min(minX, x);
1405
- minY = Math.min(minY, y);
1406
- minZ = Math.min(minZ, z);
1407
- maxX = Math.max(maxX, x);
1408
- maxY = Math.max(maxY, y);
1409
- maxZ = Math.max(maxZ, z);
1410
- }
1411
- const padding = Math.max(0.001, this._maxOffsetDistance);
1412
- this._target?.setAnimatedBoundingBox?.(new BoundingBox(new Vector3(minX - padding, minY - padding, minZ - padding), new Vector3(maxX + padding, maxY + padding, maxZ + padding)));
1467
+ this._target?.setAnimatedBoundingBox?.(calculateGPUClothWrapBoundingBox(sourceBBox, this._sourceToTargetMatrix, this._targetSkinnedPositions, this._targetOffsetDistances, this._targetWrapWeights));
1413
1468
  }
1414
1469
  }
1415
1470
  /**
@@ -1422,7 +1477,7 @@ class GPUClothWrapBinding {
1422
1477
  }
1423
1478
  const sourcePrimitive = source.primitive;
1424
1479
  const sourcePositions = await readPositionDataFromPrimitive(sourcePrimitive);
1425
- const sourceIndices = toUInt32Indices(await readIndexDataFromPrimitive(sourcePrimitive, sourcePositions.length / 3 >> 0));
1480
+ const sourceIndices = toUInt32Indices(await readIndexDataFromPrimitive(sourcePrimitive));
1426
1481
  return GPUClothWrapBinding.createBindingData(source, sourcePositions, sourceIndices, target);
1427
1482
  }
1428
1483
  /**
@@ -1472,9 +1527,11 @@ class GPUClothWrapBinding {
1472
1527
  _sphereColliderBuffer;
1473
1528
  _capsuleColliderBuffer;
1474
1529
  _planeColliderBuffer;
1530
+ _boxColliderBuffer;
1475
1531
  _sphereColliderData;
1476
1532
  _capsuleColliderData;
1477
1533
  _planeColliderData;
1534
+ _boxColliderData;
1478
1535
  _triangleIndexBuffer;
1479
1536
  _triangleNormalBuffer;
1480
1537
  _vertexTriangleAdjacencyBuffer;
@@ -1545,9 +1602,11 @@ class GPUClothWrapBinding {
1545
1602
  this._sphereColliderBuffer = null;
1546
1603
  this._capsuleColliderBuffer = null;
1547
1604
  this._planeColliderBuffer = null;
1605
+ this._boxColliderBuffer = null;
1548
1606
  this._sphereColliderData = new Float32Array(getInitialColliderBufferFloatCount(this._colliders, 'sphere', 4));
1549
1607
  this._capsuleColliderData = new Float32Array(getInitialColliderBufferFloatCount(this._colliders, 'capsule', 8));
1550
1608
  this._planeColliderData = new Float32Array(getInitialColliderBufferFloatCount(this._colliders, 'plane', 8));
1609
+ this._boxColliderData = new Float32Array(getInitialColliderBufferFloatCount(this._colliders, 'box', 16));
1551
1610
  this._triangleIndexBuffer = null;
1552
1611
  this._triangleNormalBuffer = null;
1553
1612
  this._vertexTriangleAdjacencyBuffer = null;
@@ -1581,6 +1640,9 @@ class GPUClothWrapBinding {
1581
1640
  };
1582
1641
  if (!supported) {
1583
1642
  this._disabledReason = 'GPU cloth is disabled: current backend is not WebGPU.';
1643
+ if (wantEnabled) {
1644
+ warnUnsupported('GPU cloth (GPUClothComponent)', 'WebGPU', 'the cloth does not move');
1645
+ }
1584
1646
  return;
1585
1647
  }
1586
1648
  if (!this._device) {
@@ -1711,6 +1773,13 @@ class GPUClothWrapBinding {
1711
1773
  managed: false
1712
1774
  });
1713
1775
  this._planeColliderBuffer.bufferSubData(0, this._planeColliderData);
1776
+ this._boxColliderBuffer = this._device.createBuffer(this._boxColliderData.byteLength, {
1777
+ usage: 'uniform',
1778
+ storage: true,
1779
+ dynamic: false,
1780
+ managed: false
1781
+ });
1782
+ this._boxColliderBuffer.bufferSubData(0, this._boxColliderData);
1714
1783
  this._integrateProgram = createIntegrateProgram(this._device, workgroupSize);
1715
1784
  this._constraintProgram = createConstraintProgram(this._device, workgroupSize);
1716
1785
  if (!this._integrateProgram || !this._constraintProgram) {
@@ -1726,12 +1795,14 @@ class GPUClothWrapBinding {
1726
1795
  this._integrateBindGroup.setBuffer('sphereData', this._sphereColliderBuffer);
1727
1796
  this._integrateBindGroup.setBuffer('capsuleData', this._capsuleColliderBuffer);
1728
1797
  this._integrateBindGroup.setBuffer('planeData', this._planeColliderBuffer);
1798
+ this._integrateBindGroup.setBuffer('boxData', this._boxColliderBuffer);
1729
1799
  this._integrateBindGroup.setValue('vertexCount', vertexCount);
1730
1800
  this._integrateBindGroup.setValue('damping', this._damping);
1731
1801
  this._integrateBindGroup.setValue('gravity', this._gravity);
1732
1802
  this._integrateBindGroup.setValue('sphereCount', 0);
1733
1803
  this._integrateBindGroup.setValue('capsuleCount', 0);
1734
1804
  this._integrateBindGroup.setValue('planeCount', 0);
1805
+ this._integrateBindGroup.setValue('boxCount', 0);
1735
1806
  this._integrateBindGroup.setValue('dynamicFriction', this._dynamicFriction);
1736
1807
  this._integrateBindGroup.setValue('staticFriction', this._staticFriction);
1737
1808
  this._integrateBindGroup.setValue('minDistance', 1e-5);
@@ -1744,6 +1815,7 @@ class GPUClothWrapBinding {
1744
1815
  this._constraintBindGroup.setBuffer('sphereData', this._sphereColliderBuffer);
1745
1816
  this._constraintBindGroup.setBuffer('capsuleData', this._capsuleColliderBuffer);
1746
1817
  this._constraintBindGroup.setBuffer('planeData', this._planeColliderBuffer);
1818
+ this._constraintBindGroup.setBuffer('boxData', this._boxColliderBuffer);
1747
1819
  this._constraintBindGroup.setValue('vertexCount', vertexCount);
1748
1820
  this._constraintBindGroup.setValue('maxNeighbors', this._maxNeighbors);
1749
1821
  this._constraintBindGroup.setValue('stiffness', this._stiffness);
@@ -1751,6 +1823,7 @@ class GPUClothWrapBinding {
1751
1823
  this._constraintBindGroup.setValue('sphereCount', 0);
1752
1824
  this._constraintBindGroup.setValue('capsuleCount', 0);
1753
1825
  this._constraintBindGroup.setValue('planeCount', 0);
1826
+ this._constraintBindGroup.setValue('boxCount', 0);
1754
1827
  this._constraintBindGroup.setValue('dynamicFriction', this._dynamicFriction);
1755
1828
  this._constraintBindGroup.setValue('staticFriction', this._staticFriction);
1756
1829
  this._constraintBindGroup.setValue('minDistance', 1e-5);
@@ -1811,7 +1884,7 @@ class GPUClothWrapBinding {
1811
1884
  static async createFromPrimitive(primitive, options) {
1812
1885
  const positionData = await readPositionDataFromPrimitive(primitive);
1813
1886
  const skinningData = await readSkinningDataFromPrimitive(primitive);
1814
- const indexData = await readIndexDataFromPrimitive(primitive, positionData.length / 3 >> 0);
1887
+ const indexData = await readIndexDataFromPrimitive(primitive);
1815
1888
  return new GPUClothSystem({
1816
1889
  ...options,
1817
1890
  primitive,
@@ -1825,8 +1898,16 @@ class GPUClothWrapBinding {
1825
1898
  if (!mesh.primitive) {
1826
1899
  throw new Error('GPU cloth initialization failed: mesh has no primitive.');
1827
1900
  }
1828
- return GPUClothSystem.createFromPrimitive(mesh.primitive, {
1901
+ const positionData = await readPositionDataFromPrimitive(mesh.primitive);
1902
+ const skinningData = await readSkinningDataFromMesh(mesh);
1903
+ const indexData = await readIndexDataFromPrimitive(mesh.primitive);
1904
+ return new GPUClothSystem({
1829
1905
  ...options,
1906
+ primitive: mesh.primitive,
1907
+ positionData,
1908
+ indexData,
1909
+ skinningBlendIndices: skinningData?.blendIndices ?? undefined,
1910
+ skinningBlendWeights: skinningData?.blendWeights ?? undefined,
1830
1911
  collisionSpaceNode: mesh,
1831
1912
  scene: mesh.scene ?? null
1832
1913
  });
@@ -1848,7 +1929,7 @@ class GPUClothWrapBinding {
1848
1929
  }
1849
1930
  }
1850
1931
  }
1851
- setWrapTargetsFromBindingData(targets) {
1932
+ async setWrapTargetsFromBindingData(targets) {
1852
1933
  this.clearWrapTargets();
1853
1934
  if (!this.supported || !this._device || !this._positionBuffer || !this._sourcePositionData || !this._sourceIndexData) {
1854
1935
  return;
@@ -1861,7 +1942,7 @@ class GPUClothWrapBinding {
1861
1942
  }
1862
1943
  seen.add(target);
1863
1944
  try {
1864
- const binding = GPUClothWrapBinding.createFromData(this._device, this._collisionSpaceNode, this._positionBuffer, this._sourcePositionData, this._sourceIndexData, target, this._workgroupSize, entry.data);
1945
+ const binding = await GPUClothWrapBinding.createFromData(this._device, this._collisionSpaceNode, this._positionBuffer, this._sourcePositionData, this._sourceIndexData, target, this._workgroupSize, entry.data, entry.targetWrapWeights);
1865
1946
  this._wrapBindings.push(binding);
1866
1947
  } catch (err) {
1867
1948
  console.error('GPU cloth wrap target binding cache initialization failed:', err);
@@ -2077,6 +2158,8 @@ class GPUClothWrapBinding {
2077
2158
  this._capsuleColliderBuffer = null;
2078
2159
  this._planeColliderBuffer?.dispose();
2079
2160
  this._planeColliderBuffer = null;
2161
+ this._boxColliderBuffer?.dispose();
2162
+ this._boxColliderBuffer = null;
2080
2163
  releaseObject(this._originalPositionBuffer);
2081
2164
  this._originalPositionBuffer = null;
2082
2165
  releaseObject(this._originalNormalBuffer);
@@ -2145,6 +2228,7 @@ class GPUClothWrapBinding {
2145
2228
  const spheres = [];
2146
2229
  const capsules = [];
2147
2230
  const planes = [];
2231
+ const boxes = [];
2148
2232
  const blend = this.getTemporalBlendFactor(deltaTime, DEFAULT_COLLIDER_SMOOTHING_TIME);
2149
2233
  for (const collider of this._colliders){
2150
2234
  if (!collider?.enabled) {
@@ -2175,6 +2259,10 @@ class GPUClothWrapBinding {
2175
2259
  point: smoothed.point,
2176
2260
  normal: smoothed.normal
2177
2261
  });
2262
+ } else if (collider.type === 'box') {
2263
+ boxes.push({
2264
+ collider: collider
2265
+ });
2178
2266
  }
2179
2267
  }
2180
2268
  const sphereData = new Float32Array(Math.max(1, spheres.length) * 4);
@@ -2220,6 +2308,31 @@ class GPUClothWrapBinding {
2220
2308
  planeData[base + 6] = normal.z;
2221
2309
  planeData[base + 7] = 0;
2222
2310
  }
2311
+ const boxData = new Float32Array(Math.max(1, boxes.length) * 16);
2312
+ for(let i = 0; i < boxes.length; i++){
2313
+ const base = i * 16;
2314
+ const box = boxes[i].collider;
2315
+ const center = this.toCollisionSpacePoint(box.center);
2316
+ const axisX = this.toCollisionSpaceVector(box.axes[0]);
2317
+ const axisY = this.toCollisionSpaceVector(box.axes[1]);
2318
+ const axisZ = this.toCollisionSpaceVector(box.axes[2]);
2319
+ boxData[base] = center.x;
2320
+ boxData[base + 1] = center.y;
2321
+ boxData[base + 2] = center.z;
2322
+ boxData[base + 3] = this.toCollisionSpaceRadius(box.halfExtents.x);
2323
+ boxData[base + 4] = this.toCollisionSpaceRadius(box.halfExtents.y);
2324
+ boxData[base + 5] = this.toCollisionSpaceRadius(box.halfExtents.z);
2325
+ boxData[base + 6] = axisX.x;
2326
+ boxData[base + 7] = axisX.y;
2327
+ boxData[base + 8] = axisX.z;
2328
+ boxData[base + 9] = axisY.x;
2329
+ boxData[base + 10] = axisY.y;
2330
+ boxData[base + 11] = axisY.z;
2331
+ boxData[base + 12] = axisZ.x;
2332
+ boxData[base + 13] = axisZ.y;
2333
+ boxData[base + 14] = axisZ.z;
2334
+ boxData[base + 15] = 0;
2335
+ }
2223
2336
  if (!this._sphereColliderBuffer || this._sphereColliderBuffer.byteLength < sphereData.byteLength) {
2224
2337
  if (this._sphereColliderBuffer) {
2225
2338
  // Drain queued uploads for the old buffer before replacing it.
@@ -2268,12 +2381,29 @@ class GPUClothWrapBinding {
2268
2381
  this._constraintBindGroup?.setBuffer('planeData', this._planeColliderBuffer);
2269
2382
  }
2270
2383
  this._planeColliderBuffer.bufferSubData(0, planeData);
2384
+ if (!this._boxColliderBuffer || this._boxColliderBuffer.byteLength < boxData.byteLength) {
2385
+ if (this._boxColliderBuffer) {
2386
+ this._device.flush();
2387
+ this._boxColliderBuffer.dispose();
2388
+ }
2389
+ this._boxColliderBuffer = this._device.createBuffer(boxData.byteLength, {
2390
+ usage: 'uniform',
2391
+ storage: true,
2392
+ dynamic: false,
2393
+ managed: false
2394
+ });
2395
+ this._integrateBindGroup.setBuffer('boxData', this._boxColliderBuffer);
2396
+ this._constraintBindGroup?.setBuffer('boxData', this._boxColliderBuffer);
2397
+ }
2398
+ this._boxColliderBuffer.bufferSubData(0, boxData);
2271
2399
  this._integrateBindGroup.setValue('sphereCount', spheres.length);
2272
2400
  this._integrateBindGroup.setValue('capsuleCount', capsules.length);
2273
2401
  this._integrateBindGroup.setValue('planeCount', planes.length);
2402
+ this._integrateBindGroup.setValue('boxCount', boxes.length);
2274
2403
  this._constraintBindGroup?.setValue('sphereCount', spheres.length);
2275
2404
  this._constraintBindGroup?.setValue('capsuleCount', capsules.length);
2276
2405
  this._constraintBindGroup?.setValue('planeCount', planes.length);
2406
+ this._constraintBindGroup?.setValue('boxCount', boxes.length);
2277
2407
  }
2278
2408
  getSubstepPoseFollow() {
2279
2409
  const effectivePoseFollow = this.getEffectivePoseFollow();
@@ -2520,5 +2650,5 @@ class GPUClothWrapBinding {
2520
2650
  }
2521
2651
  }
2522
2652
 
2523
- export { GPUClothSystem, createGPUClothWrapBindingData, isGPUClothSupported };
2653
+ export { GPUClothSystem, calculateGPUClothWrapBoundingBox, createGPUClothWrapBindingData, isGPUClothSupported };
2524
2654
  //# sourceMappingURL=gpu_cloth_system.js.map