@woosh/meep-engine 3.17.2 → 3.18.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 (263) hide show
  1. package/editor/actions/concrete/ComponentAddAction.d.ts +1 -0
  2. package/editor/actions/concrete/ComponentAddAction.d.ts.map +1 -1
  3. package/editor/actions/concrete/ComponentAddAction.js +4 -0
  4. package/editor/actions/concrete/ComponentRemoveAction.d.ts +1 -0
  5. package/editor/actions/concrete/ComponentRemoveAction.d.ts.map +1 -1
  6. package/editor/actions/concrete/ComponentRemoveAction.js +4 -0
  7. package/editor/actions/concrete/EntityCreateAction.d.ts +1 -0
  8. package/editor/actions/concrete/EntityCreateAction.d.ts.map +1 -1
  9. package/editor/actions/concrete/EntityCreateAction.js +7 -0
  10. package/editor/actions/concrete/EntityRemoveAction.d.ts +1 -0
  11. package/editor/actions/concrete/EntityRemoveAction.d.ts.map +1 -1
  12. package/editor/actions/concrete/EntityRemoveAction.js +4 -0
  13. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts +10 -0
  14. package/editor/actions/concrete/PatchTerrainHeightAction.d.ts.map +1 -1
  15. package/editor/actions/concrete/PatchTerrainHeightAction.js +107 -85
  16. package/editor/actions/concrete/TransformModifyAction.d.ts +1 -0
  17. package/editor/actions/concrete/TransformModifyAction.d.ts.map +1 -1
  18. package/editor/actions/concrete/TransformModifyAction.js +4 -0
  19. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  20. package/editor/particles/effect/ParticleEffectDocument.js +10 -6
  21. package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
  22. package/editor/particles/effect/ParticleReferenceSimulation.js +98 -4
  23. package/editor/particles/effect/make_starter_particle_effect.d.ts.map +1 -1
  24. package/editor/particles/effect/make_starter_particle_effect.js +0 -2
  25. package/editor/tools/engine/ToolEngine.d.ts +30 -0
  26. package/editor/tools/engine/ToolEngine.d.ts.map +1 -1
  27. package/editor/tools/engine/ToolEngine.js +257 -188
  28. package/editor/view/ecs/EntityList.d.ts.map +1 -1
  29. package/editor/view/ecs/EntityList.js +6 -5
  30. package/editor/view/particles/effect/ParticleEmitterInspectorView.d.ts.map +1 -1
  31. package/editor/view/particles/effect/ParticleEmitterInspectorView.js +17 -9
  32. package/package.json +1 -1
  33. package/src/CODEC_LAYOUT_VERIFICATION.md +1 -2
  34. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.d.ts +56 -0
  35. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.d.ts.map +1 -0
  36. package/src/core/binary/meshopt/MESHOPT_VERTEX_BLOCK.js +73 -0
  37. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.d.ts.map +1 -1
  38. package/src/core/binary/meshopt/meshopt_decode_vertex_buffer.js +18 -63
  39. package/src/core/binary/meshopt/meshopt_encode_byte_group.d.ts +53 -0
  40. package/src/core/binary/meshopt/meshopt_encode_byte_group.d.ts.map +1 -0
  41. package/src/core/binary/meshopt/meshopt_encode_byte_group.js +140 -0
  42. package/src/core/binary/meshopt/meshopt_encode_data_block.d.ts +32 -0
  43. package/src/core/binary/meshopt/meshopt_encode_data_block.d.ts.map +1 -0
  44. package/src/core/binary/meshopt/meshopt_encode_data_block.js +77 -0
  45. package/src/core/binary/meshopt/meshopt_encode_index_sequence.d.ts +46 -0
  46. package/src/core/binary/meshopt/meshopt_encode_index_sequence.d.ts.map +1 -0
  47. package/src/core/binary/meshopt/meshopt_encode_index_sequence.js +146 -0
  48. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.d.ts +40 -0
  49. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.d.ts.map +1 -0
  50. package/src/core/binary/meshopt/meshopt_encode_vertex_buffer.js +700 -0
  51. package/src/core/binary/meshopt/meshopt_write_uint_var.d.ts +24 -0
  52. package/src/core/binary/meshopt/meshopt_write_uint_var.d.ts.map +1 -0
  53. package/src/core/binary/meshopt/meshopt_write_uint_var.js +39 -0
  54. package/src/core/math/random/seededRandom_Mulberry32.d.ts.map +1 -1
  55. package/src/core/math/random/seededRandom_Mulberry32.js +4 -2
  56. package/src/core/process/undo/Action.d.ts +19 -0
  57. package/src/core/process/undo/Action.d.ts.map +1 -1
  58. package/src/core/process/undo/Action.js +17 -0
  59. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts +78 -0
  60. package/src/engine/graphics3/GPUParticleEmitterSystem.d.ts.map +1 -0
  61. package/src/engine/graphics3/GPUParticleEmitterSystem.js +310 -0
  62. package/src/engine/graphics3/GraphicsEngine.d.ts +17 -0
  63. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  64. package/src/engine/graphics3/GraphicsEngine.js +30 -10
  65. package/src/engine/graphics3/particles/particle_gpu_records.d.ts.map +1 -1
  66. package/src/engine/graphics3/particles/particle_gpu_records.js +0 -2
  67. package/src/engine/interpolation/InterpolationSystem.d.ts +7 -0
  68. package/src/engine/interpolation/InterpolationSystem.d.ts.map +1 -1
  69. package/src/engine/interpolation/InterpolationSystem.js +10 -0
  70. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  71. package/src/engine/network/NetworkSession.js +14 -34
  72. package/src/engine/network/time/RenderPlayout.d.ts +76 -0
  73. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -0
  74. package/src/engine/network/time/RenderPlayout.js +163 -0
  75. package/src/engine/network/transport/adapters/WebSocketTransport.d.ts.map +1 -1
  76. package/src/engine/network/transport/adapters/WebSocketTransport.js +11 -4
  77. package/src/engine/physics/ecs/PhysicsSystem.d.ts +4 -12
  78. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  79. package/src/engine/physics/ecs/PhysicsSystem.js +39 -13
  80. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  81. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  82. package/src/engine/sound/simulation/core/VolumeField.js +4 -1
  83. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +23 -2
  84. package/src/shade/playground/particle_system/README.md +139 -139
  85. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  86. package/src/shade/playground/particle_system/particle_prototype.js +0 -2
  87. package/src/shade/playground/particle_system/particle_scene.d.ts +6 -9
  88. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -1
  89. package/src/shade/playground/particle_system/particle_scene.js +6 -13
  90. package/src/shade/playground/ssr_reprojection/README.md +103 -0
  91. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.d.ts +17 -0
  92. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.d.ts.map +1 -0
  93. package/src/shade/playground/ssr_reprojection/SpatialFilterProbe.js +68 -0
  94. package/src/shade/playground/ssr_reprojection/index.html +79 -0
  95. package/src/shade/playground/ssr_reprojection/main.d.ts +2 -0
  96. package/src/shade/playground/ssr_reprojection/main.d.ts.map +1 -0
  97. package/src/shade/playground/ssr_reprojection/main.js +245 -0
  98. package/src/shade/playground/ssr_reprojection/scene.d.ts +18 -0
  99. package/src/shade/playground/ssr_reprojection/scene.d.ts.map +1 -0
  100. package/src/shade/playground/ssr_reprojection/scene.js +51 -0
  101. package/src/shade/renderer/Renderer.d.ts +2 -23
  102. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  103. package/src/shade/renderer/Renderer.js +185 -218
  104. package/src/shade/renderer/animation/GPUAnimationManager.d.ts +5 -8
  105. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  106. package/src/shade/renderer/animation/GPUAnimationManager.js +12 -12
  107. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  108. package/src/shade/renderer/buffer/table/GPUTypedTable.js +6 -0
  109. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.d.ts.map +1 -1
  110. package/src/shade/renderer/buffer/table/single/GPUSingleTypeTable.js +7 -0
  111. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.d.ts +4 -0
  112. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.d.ts.map +1 -0
  113. package/src/shade/renderer/global_illumination/brick4/gpu/draw/chunk_brick4_sample_specular.js +51 -0
  114. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.d.ts.map +1 -1
  115. package/src/shade/renderer/global_illumination/brick4/gpu/draw/shader_brick4_specular.js +5 -35
  116. package/src/shade/renderer/particles/DESIGN.md +703 -514
  117. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +16 -4
  118. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  119. package/src/shade/renderer/particles/GPUParticleSystem.js +1189 -991
  120. package/src/shade/renderer/particles/ParticleConstants.d.ts +64 -0
  121. package/src/shade/renderer/particles/ParticleConstants.d.ts.map +1 -1
  122. package/src/shade/renderer/particles/ParticleConstants.js +71 -0
  123. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts +57 -0
  124. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.d.ts.map +1 -0
  125. package/src/shade/renderer/particles/bounds/chunk_particle_bounds.js +181 -0
  126. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.d.ts +7 -0
  127. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.d.ts.map +1 -0
  128. package/src/shade/renderer/particles/bounds/chunk_particle_bounds_unknown.js +12 -0
  129. package/src/shade/renderer/particles/bounds/graph_particle_bounds.d.ts +33 -0
  130. package/src/shade/renderer/particles/bounds/graph_particle_bounds.d.ts.map +1 -0
  131. package/src/shade/renderer/particles/bounds/graph_particle_bounds.js +67 -0
  132. package/src/shade/renderer/particles/bounds/shader_particle_bounds.d.ts +40 -0
  133. package/src/shade/renderer/particles/bounds/shader_particle_bounds.d.ts.map +1 -0
  134. package/src/shade/renderer/particles/bounds/shader_particle_bounds.js +187 -0
  135. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +15 -2
  136. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  137. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +14 -8
  138. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts +58 -4
  139. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.d.ts.map +1 -1
  140. package/src/shade/renderer/particles/data/PARTICLE_COUNTERS.js +79 -4
  141. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.d.ts +23 -1
  142. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.d.ts.map +1 -1
  143. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STATE.js +35 -2
  144. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts +4 -2
  145. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.d.ts.map +1 -1
  146. package/src/shade/renderer/particles/data/PARTICLE_EMITTER_STRUCT.js +5 -8
  147. package/src/shade/renderer/particles/data/particle_emitter_record.d.ts.map +1 -1
  148. package/src/shade/renderer/particles/data/particle_emitter_record.js +0 -6
  149. package/src/shade/renderer/particles/graph_particles.d.ts +25 -3
  150. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  151. package/src/shade/renderer/particles/graph_particles.js +108 -31
  152. package/src/shade/renderer/particles/graph_particles_avboit.d.ts +6 -4
  153. package/src/shade/renderer/particles/graph_particles_avboit.d.ts.map +1 -1
  154. package/src/shade/renderer/particles/graph_particles_avboit.js +5 -5
  155. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts +5 -0
  156. package/src/shade/renderer/particles/runtime/EmitterRegistry.d.ts.map +1 -1
  157. package/src/shade/renderer/particles/runtime/EmitterRegistry.js +27 -6
  158. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts +4 -0
  159. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.d.ts.map +1 -1
  160. package/src/shade/renderer/particles/runtime/GPUParticleEmitterContext.js +6 -1
  161. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts +35 -27
  162. package/src/shade/renderer/particles/runtime/ParticleEmitter.d.ts.map +1 -1
  163. package/src/shade/renderer/particles/runtime/ParticleEmitter.js +424 -425
  164. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts +20 -0
  165. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_warmup.d.ts.map +1 -0
  166. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts +4 -0
  167. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.d.ts.map +1 -1
  168. package/src/shade/renderer/particles/shaders/chunk_particle_render_math.js +38 -2
  169. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.d.ts +22 -0
  170. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.d.ts.map +1 -0
  171. package/src/shade/renderer/particles/shaders/chunk_particle_spawn_budget.js +42 -0
  172. package/src/shade/renderer/particles/shaders/shader_particle_avboit_draw.js +1 -1
  173. package/src/shade/renderer/particles/shaders/shader_particle_avboit_occupancy.d.ts.map +1 -1
  174. package/src/shade/renderer/particles/shaders/shader_particle_avboit_occupancy.js +53 -22
  175. package/src/shade/renderer/particles/shaders/shader_particle_emitter_tick.d.ts.map +1 -1
  176. package/src/shade/renderer/particles/shaders/shader_particle_emitter_tick.js +213 -216
  177. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts +50 -0
  178. package/src/shade/renderer/particles/shaders/shader_particle_reclaim.d.ts.map +1 -0
  179. package/src/shade/renderer/particles/shaders/shader_particle_render.js +1 -1
  180. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.d.ts +36 -0
  181. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.d.ts.map +1 -0
  182. package/src/shade/renderer/particles/warmup/chunk_particle_warmup_step.js +102 -0
  183. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts +102 -0
  184. package/src/shade/renderer/particles/warmup/graph_particle_warmup.d.ts.map +1 -0
  185. package/src/shade/renderer/particles/warmup/graph_particle_warmup.js +329 -0
  186. package/src/shade/renderer/particles/warmup/shader_particle_warmup.d.ts +112 -0
  187. package/src/shade/renderer/particles/warmup/shader_particle_warmup.d.ts.map +1 -0
  188. package/src/shade/renderer/particles/warmup/shader_particle_warmup.js +318 -0
  189. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts +35 -0
  190. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.d.ts.map +1 -0
  191. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance.js +108 -0
  192. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts +3 -0
  193. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.d.ts.map +1 -0
  194. package/src/shade/renderer/particles/warmup/shader_particle_warmup_advance_wide.js +70 -0
  195. package/src/shade/renderer/particles/warmup/warmup_schedule.d.ts +62 -0
  196. package/src/shade/renderer/particles/warmup/warmup_schedule.d.ts.map +1 -0
  197. package/src/shade/renderer/particles/warmup/warmup_schedule.js +55 -0
  198. package/src/shade/renderer/postprocess/PostProcess.d.ts.map +1 -1
  199. package/src/shade/renderer/postprocess/PostProcess.js +2 -1
  200. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +286 -0
  201. package/src/shade/renderer/postprocess/ssr/SSR.d.ts +57 -21
  202. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  203. package/src/shade/renderer/postprocess/ssr/SSR.js +230 -129
  204. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.d.ts +11 -0
  205. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.d.ts.map +1 -0
  206. package/src/shade/renderer/postprocess/ssr/SSRReprojectionMode.js +6 -0
  207. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.d.ts +4 -0
  208. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.d.ts.map +1 -0
  209. package/src/shade/renderer/postprocess/ssr/chunk_ssr_metadata.js +32 -0
  210. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.d.ts +4 -0
  211. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.d.ts.map +1 -0
  212. package/src/shade/renderer/postprocess/ssr/chunk_ssr_spatial_variance.js +41 -0
  213. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts +3 -0
  214. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.d.ts.map +1 -0
  215. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_reprojection.js +30 -0
  216. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts +4 -0
  217. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.d.ts.map +1 -0
  218. package/src/shade/renderer/postprocess/ssr/reproject/chunk_ssr_sample_history.js +70 -0
  219. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts +21 -0
  220. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.d.ts.map +1 -0
  221. package/src/shade/renderer/postprocess/ssr/resolve/build_ssr_resolve_shader.js +363 -0
  222. package/src/shade/renderer/postprocess/ssr/resolve/chunk_get_neighbour_weight.js +1 -1
  223. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.d.ts +2 -0
  224. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.d.ts.map +1 -0
  225. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_Brick4.js +24 -0
  226. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts +1 -6
  227. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.d.ts.map +1 -1
  228. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_IBL.js +16 -332
  229. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts +1 -6
  230. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.d.ts.map +1 -1
  231. package/src/shade/renderer/postprocess/ssr/resolve/ssr_resolve_shader_LPV.js +25 -358
  232. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts +0 -5
  233. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.d.ts.map +1 -1
  234. package/src/shade/renderer/postprocess/ssr/ssr_reproject_shader.js +201 -276
  235. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts +1 -0
  236. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.d.ts.map +1 -1
  237. package/src/shade/renderer/postprocess/ssr/ssr_spatial_denoise_shader.js +167 -143
  238. package/src/shade/renderer/shader/graph/graph_create_buffer.d.ts +15 -0
  239. package/src/shade/renderer/shader/graph/graph_create_buffer.d.ts.map +1 -0
  240. package/src/shade/renderer/shader/graph/graph_create_buffer.js +20 -0
  241. package/src/shade/renderer/view/GPUViewContext.d.ts +3 -4
  242. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  243. package/src/shade/renderer/view/GPUViewContext.js +5 -5
  244. package/src/core/binary/meshopt/__meshopt_test_streams.d.ts +0 -24
  245. package/src/core/binary/meshopt/__meshopt_test_streams.d.ts.map +0 -1
  246. package/src/core/binary/meshopt/__meshopt_test_streams.js +0 -237
  247. package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts +0 -84
  248. package/src/core/geom/3d/atlas/atlas_test_fixtures.d.ts.map +0 -1
  249. package/src/core/geom/3d/atlas/atlas_test_fixtures.js +0 -266
  250. package/src/engine/asset/loaders/gltf_test_fixtures.d.ts +0 -97
  251. package/src/engine/asset/loaders/gltf_test_fixtures.d.ts.map +0 -1
  252. package/src/engine/asset/loaders/gltf_test_fixtures.js +0 -359
  253. package/src/shade/renderer/animation/skin_test_fixtures.d.ts +0 -86
  254. package/src/shade/renderer/animation/skin_test_fixtures.d.ts.map +0 -1
  255. package/src/shade/renderer/animation/skin_test_fixtures.js +0 -250
  256. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts +0 -16
  257. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.d.ts.map +0 -1
  258. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_layers_test_fixtures.js +0 -27
  259. package/src/shade/renderer/particles/particle_test_fixtures.d.ts +0 -151
  260. package/src/shade/renderer/particles/particle_test_fixtures.d.ts.map +0 -1
  261. package/src/shade/renderer/particles/particle_test_fixtures.js +0 -229
  262. package/src/shade/renderer/particles/shaders/chunk_particle_emitter_world_sphere.js +0 -23
  263. package/src/shade/renderer/postprocess/ssr/reproject/shader_ffx_denoiser_reflections_reproject.js +0 -457
@@ -1,359 +0,0 @@
1
- /**
2
- * Shared inline glTF fixtures for the loader test suites — one triangle, in both of the containers
3
- * the format ships in. Test-only; not imported by production code.
4
- *
5
- * The point of authoring the bytes here rather than checking a model in is that every field a loader
6
- * reads is visible in one place: change the accessor and the test that depends on it says so.
7
- */
8
-
9
- import { encode_meshopt_attributes } from "../../../core/binary/meshopt/__meshopt_test_streams.js";
10
- import { align_4 } from "../../../core/binary/align_4.js";
11
-
12
- export const GLTF_FIXTURE_NODE_NAME = 'unit_root';
13
- export const GLTF_FIXTURE_MESH_NAME = 'unit_body';
14
-
15
- /**
16
- * Byte length of what {@link build_triangle_bin} produces — three positions, three normals, three
17
- * texture coordinates and three indices, laid out back to back.
18
- * @type {number}
19
- */
20
- export const GLTF_FIXTURE_BIN_BYTE_LENGTH = 102;
21
-
22
- /**
23
- * @returns {ArrayBuffer}
24
- */
25
- export function build_triangle_bin() {
26
- const buffer = new ArrayBuffer(GLTF_FIXTURE_BIN_BYTE_LENGTH);
27
-
28
- new Float32Array(buffer, 0, 9).set([0, 0, 0, 1, 0, 0, 0, 1, 0]);
29
- new Float32Array(buffer, 36, 9).set([0, 0, 1, 0, 0, 1, 0, 0, 1]);
30
- new Float32Array(buffer, 72, 6).set([0, 0, 1, 0, 0, 1]);
31
- new Uint16Array(buffer, 96, 3).set([0, 1, 2]);
32
-
33
- return buffer;
34
- }
35
-
36
- /**
37
- * @param {string|undefined} buffer_uri `undefined` for a .glb, whose buffer is the binary chunk
38
- * @returns {object}
39
- */
40
- export function build_triangle_gltf_json(buffer_uri) {
41
- return {
42
- asset: { version: '2.0' },
43
- scene: 0,
44
- scenes: [{ nodes: [0] }],
45
- nodes: [{ name: GLTF_FIXTURE_NODE_NAME, mesh: 0 }],
46
- meshes: [{
47
- name: GLTF_FIXTURE_MESH_NAME,
48
- primitives: [{ attributes: { POSITION: 0, NORMAL: 1, TEXCOORD_0: 2 }, indices: 3 }]
49
- }],
50
- accessors: [
51
- {
52
- bufferView: 0, componentType: 5126, count: 3, type: 'VEC3',
53
- min: [0, 0, 0], max: [1, 1, 0]
54
- },
55
- { bufferView: 1, componentType: 5126, count: 3, type: 'VEC3' },
56
- { bufferView: 2, componentType: 5126, count: 3, type: 'VEC2' },
57
- { bufferView: 3, componentType: 5123, count: 3, type: 'SCALAR' }
58
- ],
59
- bufferViews: [
60
- { buffer: 0, byteOffset: 0, byteLength: 36 },
61
- { buffer: 0, byteOffset: 36, byteLength: 36 },
62
- { buffer: 0, byteOffset: 72, byteLength: 24 },
63
- { buffer: 0, byteOffset: 96, byteLength: 6 }
64
- ],
65
- buffers: [buffer_uri === undefined
66
- ? { byteLength: GLTF_FIXTURE_BIN_BYTE_LENGTH }
67
- : { uri: buffer_uri, byteLength: GLTF_FIXTURE_BIN_BYTE_LENGTH }]
68
- };
69
- }
70
-
71
- /**
72
- * The same model with a base-colour texture on it, so that a test can watch what an image costs.
73
- *
74
- * The texture names its image the way the game's own models do — a `source` index into `images`,
75
- * whose entry carries a relative `uri` — because that is the shape {@link gltf_used_image_indices}
76
- * decides against a DDS sibling with, and the one whose bytes have to come from somewhere.
77
- *
78
- * @param {string} buffer_uri
79
- * @param {string} image_uri
80
- * @returns {object}
81
- */
82
- export function build_textured_triangle_gltf_json(buffer_uri, image_uri) {
83
- const json = build_triangle_gltf_json(buffer_uri);
84
-
85
- json.meshes[0].primitives[0].material = 0;
86
-
87
- json.materials = [{
88
- name: 'unit_skin',
89
- pbrMetallicRoughness: { baseColorTexture: { index: 0 } }
90
- }];
91
-
92
- json.textures = [{ source: 0, sampler: 0 }];
93
- json.samplers = [{}];
94
- json.images = [{ uri: image_uri, mimeType: 'image/png' }];
95
-
96
- return json;
97
- }
98
-
99
- /**
100
- * The same model as a .glb — the JSON chunk followed by the binary one.
101
- *
102
- * @returns {ArrayBuffer}
103
- */
104
- export function build_triangle_glb() {
105
- const json_bytes = new TextEncoder().encode(JSON.stringify(build_triangle_gltf_json(undefined)));
106
-
107
- // both chunks are padded to a four byte boundary, per the container's own rule
108
- const json_length = align_4(json_bytes.byteLength);
109
-
110
- const bin = new Uint8Array(build_triangle_bin());
111
- const bin_length = align_4(bin.byteLength);
112
-
113
- const total = 12 + 8 + json_length + 8 + bin_length;
114
-
115
- const glb = new ArrayBuffer(total);
116
- const view = new DataView(glb);
117
- const bytes = new Uint8Array(glb);
118
-
119
- view.setUint32(0, 0x46546C67, true);
120
- view.setUint32(4, 2, true);
121
- view.setUint32(8, total, true);
122
-
123
- view.setUint32(12, json_length, true);
124
- view.setUint32(16, 0x4E4F534A, true);
125
- bytes.set(json_bytes, 20);
126
- bytes.fill(0x20, 20 + json_bytes.byteLength, 20 + json_length);
127
-
128
- const bin_header = 20 + json_length;
129
-
130
- view.setUint32(bin_header, bin_length, true);
131
- view.setUint32(bin_header + 4, 0x004E4942, true);
132
- bytes.set(bin, bin_header + 8);
133
-
134
- return glb;
135
- }
136
-
137
- /*
138
- The same triangle, compressed. Both meshopt extensions are bufferView extensions, so the model is
139
- unchanged above the bufferViews: same nodes, same mesh, same accessors, same uncompressed layout
140
- declared on the parent views. What differs is where the bytes come from.
141
- */
142
-
143
- /**
144
- * Byte length of the placeholder the compressed views point at. It has to be big enough to hold
145
- * every uncompressed view referencing it, which is the same 102 bytes {@link build_triangle_bin}
146
- * lays out.
147
- * @type {number}
148
- */
149
- export const GLTF_FIXTURE_FALLBACK_BYTE_LENGTH = GLTF_FIXTURE_BIN_BYTE_LENGTH;
150
-
151
- /**
152
- * YCoCg colour for the three vertices, as the `COLOR` filter takes it: luma, the two chroma
153
- * differences (signed), and an alpha whose most significant set bit declares the precision.
154
- * @type {number[]}
155
- */
156
- const GLTF_FIXTURE_YCOCG = [
157
- 100, 50, -20 & 0xff, 0xff,
158
- 200, 0, 0, 0xff,
159
- 60, -30 & 0xff, 10, 0xc0
160
- ];
161
-
162
- /**
163
- * What those decode to: R = Y + Co - Cg, G = Y + Cg, B = Y - Co - Cg, with alpha widened by the bit
164
- * its marker cost it.
165
- * @type {number[]}
166
- */
167
- export const GLTF_FIXTURE_COLOURS = [
168
- 170, 80, 70, 255,
169
- 200, 200, 200, 255,
170
- 20, 70, 80, 128
171
- ];
172
-
173
- /**
174
- * The compressed streams, laid out back to back.
175
- *
176
- * Positions, normals and texture coordinates go through the attribute codec; the indices are a
177
- * hand-written triangle stream, because writing a triangle encoder to test a triangle decoder with
178
- * would prove nothing. `0xf0` reads entry 0 of the lookup table, which is `0x00` - three fresh
179
- * vertices, which is exactly (0, 1, 2).
180
- *
181
- * At `codec_version` 1 the attribute streams carry a channel mode each - a rotated exclusive-or for
182
- * the positions, plain byte deltas for the normals, 16-bit deltas for the texture coordinates - and
183
- * with `colour` there is a `COLOR`-filtered stream too. Either makes a file that only
184
- * `KHR_meshopt_compression` defines, and that the vendor extension refuses.
185
- *
186
- * @param {Object} [options]
187
- * @param {number} [options.codec_version] 0 or 1
188
- * @param {boolean} [options.colour] append a `COLOR_0` stream carrying the `COLOR` filter
189
- * @returns {{buffer: ArrayBuffer, ranges: {byteOffset:number, byteLength:number}[]}}
190
- */
191
- export function build_meshopt_triangle_bin({ codec_version = 0, colour = false } = {}) {
192
- const bin = build_triangle_bin();
193
-
194
- /**
195
- * @param {number[]} modes
196
- * @returns {Object}
197
- */
198
- const attributes = (modes) => codec_version === 1
199
- ? { version: 1, channel_modes: modes }
200
- : { version: 0 };
201
-
202
- const streams = [
203
- encode_meshopt_attributes(new Uint8Array(bin, 0, 36), 3, 12, attributes([
204
- 2 | (5 << 4), 2 | (5 << 4), 2 | (5 << 4)
205
- ])),
206
- encode_meshopt_attributes(new Uint8Array(bin, 36, 36), 3, 12, attributes([0, 0, 0])),
207
- encode_meshopt_attributes(new Uint8Array(bin, 72, 24), 3, 8, attributes([1, 1])),
208
- new Uint8Array([0xe1, 0xf0, ...new Array(16).fill(0)])
209
- ];
210
-
211
- if (colour) {
212
- streams.push(encode_meshopt_attributes(new Uint8Array(GLTF_FIXTURE_YCOCG), 3, 4, attributes([0])));
213
- }
214
-
215
- const total = streams.reduce((sum, stream) => sum + stream.length, 0);
216
-
217
- const bytes = new Uint8Array(total);
218
-
219
- const ranges = [];
220
-
221
- let byteOffset = 0;
222
-
223
- for (const stream of streams) {
224
- bytes.set(stream, byteOffset);
225
-
226
- ranges.push({ byteOffset, byteLength: stream.length });
227
-
228
- byteOffset += stream.length;
229
- }
230
-
231
- return { buffer: bytes.buffer, ranges };
232
- }
233
-
234
- /**
235
- * @param {string} extension_name `EXT_meshopt_compression` or `KHR_meshopt_compression`
236
- * @param {string|undefined} buffer_uri `undefined` for a .glb, whose compressed data is the binary chunk
237
- * @param {Object} [options] see {@link build_meshopt_triangle_bin}
238
- * @param {number} [options.codec_version]
239
- * @param {boolean} [options.colour]
240
- * @returns {object}
241
- */
242
- export function build_meshopt_triangle_gltf_json(extension_name, buffer_uri, options = {}) {
243
- const { buffer, ranges } = build_meshopt_triangle_bin(options);
244
-
245
- const json = build_triangle_gltf_json(undefined);
246
-
247
- json.extensionsUsed = [extension_name];
248
- json.extensionsRequired = [extension_name];
249
-
250
- /**
251
- * @param {number} view the parent view's index
252
- * @param {number} byteStride
253
- * @param {number} count
254
- * @param {string} mode
255
- * @returns {object}
256
- */
257
- function compressed(view, byteStride, count, mode) {
258
- return {
259
- buffer: 0,
260
- byteOffset: ranges[view].byteOffset,
261
- byteLength: ranges[view].byteLength,
262
- byteStride,
263
- count,
264
- mode
265
- };
266
- }
267
-
268
- const shapes = [
269
- [12, 3, 'ATTRIBUTES', undefined],
270
- [12, 3, 'ATTRIBUTES', undefined],
271
- [8, 3, 'ATTRIBUTES', undefined],
272
- [2, 3, 'TRIANGLES', undefined]
273
- ];
274
-
275
- if (options.colour === true) {
276
- // an unsigned normalised VEC4, which is what the COLOR filter decodes to
277
- json.bufferViews.push({ buffer: 0, byteOffset: 102, byteLength: 12 });
278
-
279
- json.accessors.push({
280
- bufferView: 4, componentType: 5121, count: 3, type: 'VEC4', normalized: true
281
- });
282
-
283
- json.meshes[0].primitives[0].attributes.COLOR_0 = 4;
284
-
285
- shapes.push([4, 3, 'ATTRIBUTES', 'COLOR']);
286
- }
287
-
288
- json.bufferViews = json.bufferViews.map((view, i) => {
289
- const [byteStride, count, mode, filter] = shapes[i];
290
-
291
- return {
292
- ...view,
293
- // the placeholder, which nothing reads once the views below are decoded
294
- buffer: 1,
295
- // index views are forbidden a stride by the base format, whatever the extension needs
296
- ...(mode === 'ATTRIBUTES' ? { byteStride } : {}),
297
- extensions: {
298
- [extension_name]: {
299
- ...compressed(i, byteStride, count, mode),
300
- ...(filter === undefined ? {} : { filter })
301
- }
302
- }
303
- };
304
- });
305
-
306
- json.buffers = [
307
- buffer_uri === undefined
308
- ? { byteLength: buffer.byteLength }
309
- : { uri: buffer_uri, byteLength: buffer.byteLength },
310
- {
311
- // big enough for every uncompressed view over it, which is what both specs require
312
- byteLength: GLTF_FIXTURE_FALLBACK_BYTE_LENGTH + (options.colour === true ? 12 : 0),
313
- extensions: { [extension_name]: { fallback: true } }
314
- }
315
- ];
316
-
317
- return json;
318
- }
319
-
320
- /**
321
- * The compressed model as a .glb: the JSON chunk, then the compressed data as the binary one.
322
- *
323
- * @param {string} extension_name
324
- * @param {Object} [options] see {@link build_meshopt_triangle_bin}
325
- * @returns {ArrayBuffer}
326
- */
327
- export function build_meshopt_triangle_glb(extension_name, options = {}) {
328
- const json_bytes = new TextEncoder().encode(
329
- JSON.stringify(build_meshopt_triangle_gltf_json(extension_name, undefined, options))
330
- );
331
-
332
- const json_length = align_4(json_bytes.byteLength);
333
-
334
- const bin = new Uint8Array(build_meshopt_triangle_bin(options).buffer);
335
- const bin_length = align_4(bin.byteLength);
336
-
337
- const total = 12 + 8 + json_length + 8 + bin_length;
338
-
339
- const glb = new ArrayBuffer(total);
340
- const view = new DataView(glb);
341
- const bytes = new Uint8Array(glb);
342
-
343
- view.setUint32(0, 0x46546C67, true);
344
- view.setUint32(4, 2, true);
345
- view.setUint32(8, total, true);
346
-
347
- view.setUint32(12, json_length, true);
348
- view.setUint32(16, 0x4E4F534A, true);
349
- bytes.set(json_bytes, 20);
350
- bytes.fill(0x20, 20 + json_bytes.byteLength, 20 + json_length);
351
-
352
- const bin_header = 20 + json_length;
353
-
354
- view.setUint32(bin_header, bin_length, true);
355
- view.setUint32(bin_header + 4, 0x004E4942, true);
356
- bytes.set(bin, bin_header + 8);
357
-
358
- return glb;
359
- }
@@ -1,86 +0,0 @@
1
- /**
2
- * A rigged character in one of the two shapes.
3
- *
4
- * The rest pose **is** the bind pose, which is what a well-formed file has. The bind matrices are
5
- * taken off the skeleton itself rather than composed by hand: the fixture walks the hierarchy once
6
- * with the root's conversion in place and once without, and the two snapshots *are* the two bind
7
- * spaces. Nothing here can drift from the hierarchy it describes, because it is read from it.
8
- *
9
- * The placement node goes on last, after the bind matrices are settled — which is what happens for
10
- * real, and is what makes "the correction does not depend on where the character stands" a fact this
11
- * fixture can be asked about rather than an assumption.
12
- *
13
- * @param {object} options
14
- * @param {BindSpace} options.bind_space
15
- * @param {number} [options.scale] the root's uniform conversion
16
- * @param {boolean} [options.up_axis_rotation] whether the root also carries the −90° about x that an
17
- * FBX-derived file pairs with its conversion. On by default: a correction that handles only
18
- * the scale passes without it.
19
- * @param {number[]} [options.placement] a translation applied above the whole character
20
- * @returns {{
21
- * placement: Node3D,
22
- * root: Node3D,
23
- * mesh: SkinnedMesh,
24
- * skin: Skin,
25
- * joints: Node3D[],
26
- * }}
27
- */
28
- export function make_character({ bind_space, scale, up_axis_rotation, placement, }: {
29
- bind_space: BindSpace;
30
- scale?: number;
31
- up_axis_rotation?: boolean;
32
- placement?: number[];
33
- }): {
34
- placement: Node3D;
35
- root: Node3D;
36
- mesh: SkinnedMesh;
37
- skin: Skin;
38
- joints: Node3D[];
39
- };
40
- /**
41
- * The two shapes a glTF character actually arrives in, built as scene graphs.
42
- *
43
- * Both are legal glTF and both are in the wild; the difference is only the space the file's author
44
- * wrote the inverse-bind matrices in, and it decides whether `inverse(mesh.global) × joint.global ×
45
- * inverse_bind` — the matrix the skinning pass converts to a dual quaternion — comes out rigid. See
46
- * `SKINNING_FRAME_PLAN.md`.
47
- *
48
- * One hierarchy serves both, because the difference is not in the hierarchy:
49
- *
50
- * ```
51
- * "placement" added at runtime, above the file's own roots
52
- * └── "Character" the file's unit conversion and up-axis rotation
53
- * ├── "Mesh" the skinned mesh, no local transform of its own
54
- * └── "Joint0" the joint root — the mesh node's *sibling*, as every rigged glTF has it
55
- * └── "Joint1"
56
- * └── "Joint2"
57
- * ```
58
- *
59
- * @author Alex Goldring
60
- * @copyright Company Named Limited (c) 2026
61
- */
62
- /**
63
- * What every one of this game's creature models puts on its glTF root node — an FBX unit
64
- * conversion, uniform, and inherited by the joints and the mesh node alike.
65
- *
66
- * @type {number}
67
- */
68
- export const EXPORT_SCALE: number;
69
- /**
70
- * The centimetre→metre conversion `Michelle.glb` carries on hers.
71
- *
72
- * @type {number}
73
- */
74
- export const MICHELLE_SCALE: number;
75
- /**
76
- * Where the file's author wrote the inverse-bind matrices.
77
- */
78
- export type BindSpace = string;
79
- export namespace BindSpace {
80
- let PreScale: string;
81
- let World: string;
82
- }
83
- import { Node3D } from "../scene/Node3D.js";
84
- import { SkinnedMesh } from "../scene/SkinnedMesh.js";
85
- import { Skin } from "./Skin.js";
86
- //# sourceMappingURL=skin_test_fixtures.d.ts.map
@@ -1 +0,0 @@
1
- {"version":3,"file":"skin_test_fixtures.d.ts","sourceRoot":"","sources":["../../../../../src/shade/renderer/animation/skin_test_fixtures.js"],"names":[],"mappings":"AAsFA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAd8B,UAAU,EAA7B,SAAS;IACQ,KAAK,GAAtB,MAAM;IACY,gBAAgB,GAAlC,OAAO;IAGY,SAAS,GAA5B,MAAM,EAAE;;eAED,MAAM;UACX,MAAM;UACN,WAAW;UACX,IAAI;YACF,MAAM,EAAE;EAgFtB;AAjLD;;;;;;;;;;;;;;;;;;;;;GAqBG;AAEH;;;;;GAKG;AACH,2BAFU,MAAM,CAEiB;AAEjC;;;;GAIG;AACH,6BAFU,MAAM,CAEmB;;;;wBAKzB,MAAM;;;;;uBA7CO,oBAAoB;4BACf,yBAAyB;qBAChC,WAAW"}
@@ -1,250 +0,0 @@
1
- import { BinaryBuffer } from "../../../core/binary/BinaryBuffer.js";
2
- import { platform_compute_endianness } from "../../../core/binary/platform_compute_endianness.js";
3
- import { m4_invert } from "../../../core/geom/3d/mat4/m4_invert.js";
4
- import { MeshletGeometry } from "../geometry/MeshletGeometry.js";
5
- import {
6
- MESHLET_METADATA_STRUCT
7
- } from "../geometry/meshlet/encoding/MESHLET_METADATA_STRUCT.js";
8
- import { StandardShadeMaterial } from "../material/StandardShadeMaterial.js";
9
- import { write_wgsl_type_value } from "../shader/type/serde/write_gpu_typed_buffer.js";
10
- import { Node3D } from "../scene/Node3D.js";
11
- import { SkinnedMesh } from "../scene/SkinnedMesh.js";
12
- import { Skin } from "./Skin.js";
13
-
14
- /**
15
- * The two shapes a glTF character actually arrives in, built as scene graphs.
16
- *
17
- * Both are legal glTF and both are in the wild; the difference is only the space the file's author
18
- * wrote the inverse-bind matrices in, and it decides whether `inverse(mesh.global) × joint.global ×
19
- * inverse_bind` — the matrix the skinning pass converts to a dual quaternion — comes out rigid. See
20
- * `SKINNING_FRAME_PLAN.md`.
21
- *
22
- * One hierarchy serves both, because the difference is not in the hierarchy:
23
- *
24
- * ```
25
- * "placement" added at runtime, above the file's own roots
26
- * └── "Character" the file's unit conversion and up-axis rotation
27
- * ├── "Mesh" the skinned mesh, no local transform of its own
28
- * └── "Joint0" the joint root — the mesh node's *sibling*, as every rigged glTF has it
29
- * └── "Joint1"
30
- * └── "Joint2"
31
- * ```
32
- *
33
- * @author Alex Goldring
34
- * @copyright Company Named Limited (c) 2026
35
- */
36
-
37
- /**
38
- * What every one of this game's creature models puts on its glTF root node — an FBX unit
39
- * conversion, uniform, and inherited by the joints and the mesh node alike.
40
- *
41
- * @type {number}
42
- */
43
- export const EXPORT_SCALE = 0.35;
44
-
45
- /**
46
- * The centimetre→metre conversion `Michelle.glb` carries on hers.
47
- *
48
- * @type {number}
49
- */
50
- export const MICHELLE_SCALE = 0.01;
51
-
52
- /**
53
- * Where the file's author wrote the inverse-bind matrices.
54
- *
55
- * @enum {string}
56
- */
57
- export const BindSpace = {
58
- /**
59
- * Before the root's conversion — the matrices invert the joints' transforms in the mesh's own
60
- * pre-conversion space, so `joint.global × inverse_bind` carries the conversion and equals the
61
- * mesh node's world transform. This is the arrangement `chunk_skin_blend_mesh_local` was written
62
- * for, and the one where the fold cancels.
63
- */
64
- PreScale: 'pre-scale',
65
-
66
- /**
67
- * After it — the matrices invert the joints' world transforms as the file leaves them, so
68
- * `joint.global × inverse_bind` is the **identity** and the geometry's positions are already in
69
- * converted units. `Michelle.glb` is this shape, and the fold leaves a bare `1 / scale` behind.
70
- */
71
- World: 'world',
72
- };
73
-
74
- /**
75
- * Rest offsets down the joint chain, in the space the geometry's positions live in — a hip, a knee
76
- * and an ankle rather than three copies of the origin, so that a defect which only shows on a joint
77
- * away from the origin cannot pass.
78
- *
79
- * @type {number[][]}
80
- */
81
- const REST_OFFSETS = [
82
- [0, 1, 0],
83
- [0.25, -0.5, 0.1],
84
- [-0.1, -0.45, 0],
85
- ];
86
-
87
- /**
88
- * A rigged character in one of the two shapes.
89
- *
90
- * The rest pose **is** the bind pose, which is what a well-formed file has. The bind matrices are
91
- * taken off the skeleton itself rather than composed by hand: the fixture walks the hierarchy once
92
- * with the root's conversion in place and once without, and the two snapshots *are* the two bind
93
- * spaces. Nothing here can drift from the hierarchy it describes, because it is read from it.
94
- *
95
- * The placement node goes on last, after the bind matrices are settled — which is what happens for
96
- * real, and is what makes "the correction does not depend on where the character stands" a fact this
97
- * fixture can be asked about rather than an assumption.
98
- *
99
- * @param {object} options
100
- * @param {BindSpace} options.bind_space
101
- * @param {number} [options.scale] the root's uniform conversion
102
- * @param {boolean} [options.up_axis_rotation] whether the root also carries the −90° about x that an
103
- * FBX-derived file pairs with its conversion. On by default: a correction that handles only
104
- * the scale passes without it.
105
- * @param {number[]} [options.placement] a translation applied above the whole character
106
- * @returns {{
107
- * placement: Node3D,
108
- * root: Node3D,
109
- * mesh: SkinnedMesh,
110
- * skin: Skin,
111
- * joints: Node3D[],
112
- * }}
113
- */
114
- export function make_character({
115
- bind_space,
116
- scale = EXPORT_SCALE,
117
- up_axis_rotation = true,
118
- placement = [0, 0, 0],
119
- }) {
120
-
121
- const root = new Node3D();
122
-
123
- root.name = 'Character';
124
-
125
- const mesh = new SkinnedMesh();
126
-
127
- mesh.name = 'Mesh';
128
- mesh.geometry = make_geometry();
129
- mesh.material = new StandardShadeMaterial();
130
-
131
- const joints = REST_OFFSETS.map((offset, i) => {
132
- const joint = new Node3D();
133
-
134
- joint.name = `Joint${i}`;
135
- joint.transform_local.setTranslation(offset[0], offset[1], offset[2]);
136
-
137
- return joint;
138
- });
139
-
140
- for (let i = 1; i < joints.length; i++) {
141
- joints[i - 1].addChild(joints[i]);
142
- }
143
-
144
- root.addChildren([mesh, joints[0]]);
145
-
146
- /*
147
- Pass one: the root at the identity, so the joints stand in the pre-conversion space an exporter
148
- writing `PreScale` bind matrices was working in. Pass two adds the conversion, and the joints
149
- stand where the file leaves them — the space a `World` exporter inverts.
150
- */
151
- root.updateMatrices();
152
-
153
- const bind = bind_space === BindSpace.PreScale ? snapshot_joint_globals(joints) : null;
154
-
155
- root.transform_local.setScale(scale, scale, scale);
156
-
157
- if (up_axis_rotation) {
158
- // −90° about x, as a quaternion: the Z-up of the file into the renderer's Y-up
159
- root.transform_local.setRotation(-Math.SQRT1_2, 0, 0, Math.SQRT1_2);
160
- }
161
-
162
- root.updateMatrices();
163
-
164
- const inverse_bind_matrices = new Float32Array(joints.length * 16);
165
-
166
- const source = bind ?? snapshot_joint_globals(joints);
167
-
168
- const inverse = new Float64Array(16);
169
-
170
- for (let i = 0; i < joints.length; i++) {
171
- m4_invert(inverse, source[i]);
172
-
173
- inverse_bind_matrices.set(inverse, i * 16);
174
- }
175
-
176
- const skin = Skin.from({
177
- name: 'fixture',
178
- joints,
179
- inverse_bind_matrices,
180
- meshes: [mesh],
181
- });
182
-
183
- const placement_node = new Node3D();
184
-
185
- placement_node.name = 'placement';
186
- placement_node.transform_local.setTranslation(placement[0], placement[1], placement[2]);
187
- placement_node.addChild(root);
188
- placement_node.updateMatrices();
189
-
190
- return { placement: placement_node, root, mesh, skin, joints };
191
- }
192
-
193
- /**
194
- * Every joint's world matrix as it stands, copied out — a `Transform64` is live, and these are read
195
- * after the hierarchy has been walked again.
196
- *
197
- * @param {Node3D[]} joints
198
- * @returns {Float64Array[]}
199
- */
200
- function snapshot_joint_globals(joints) {
201
- return joints.map(joint => {
202
- const copy = new Float64Array(16);
203
-
204
- // a Transform64's matrix starts at element 0
205
- for (let i = 0; i < 16; i++) {
206
- copy[i] = joint.transform_global[i];
207
- }
208
-
209
- return copy;
210
- });
211
- }
212
-
213
- /**
214
- * One triangle in one meshlet, with enough metadata behind it to be cloned.
215
- *
216
- * A bare {@link MeshletGeometry} is enough for the frame arithmetic, which only ever reads bounds —
217
- * but `register_skin` reaches `GPUMeshSkinningContext#bind`, which allocates a per-instance vertex
218
- * clone and refuses a batch of no meshlets. A fixture that stops short of that cannot be handed to
219
- * the manager at all, and the manager is where half of what this fixture is for gets tested.
220
- *
221
- * @returns {MeshletGeometry}
222
- */
223
- function make_geometry() {
224
- const box = [-1, 0, -1, 1, 2, 1];
225
-
226
- const geometry = new MeshletGeometry();
227
-
228
- geometry.name = 'fixture';
229
- geometry.primitive_count = 1;
230
- geometry.bounding_box.set(box);
231
- geometry.bounding_sphere.set([0, 1, 0, 1.8]);
232
-
233
- const writer = BinaryBuffer.fromEndianness(platform_compute_endianness());
234
-
235
- writer.setCapacity(MESHLET_METADATA_STRUCT.size);
236
-
237
- write_wgsl_type_value({
238
- bounds_box: box,
239
- address: 0,
240
- primitive_count: 1,
241
- vertex_count: 3,
242
- flags: 0,
243
- }, writer, MESHLET_METADATA_STRUCT);
244
-
245
- geometry.meshlets.count = 1;
246
- geometry.meshlets.data_buffer = new ArrayBuffer(3 * 3 * 4);
247
- geometry.meshlets.metadata_buffer = writer.data.slice(0, MESHLET_METADATA_STRUCT.size);
248
-
249
- return geometry;
250
- }