@woosh/meep-engine 3.22.0 → 3.23.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 (267) hide show
  1. package/package.json +1 -1
  2. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts +118 -0
  3. package/src/core/geom/3d/hash-grid/PointHashGrid3.d.ts.map +1 -0
  4. package/src/core/geom/3d/hash-grid/PointHashGrid3.js +283 -0
  5. package/src/core/geom/3d/shape/BoxShape3D.d.ts.map +1 -1
  6. package/src/core/geom/3d/shape/BoxShape3D.js +6 -17
  7. package/src/core/geom/3d/shape/CapsuleShape3D.d.ts.map +1 -1
  8. package/src/core/geom/3d/shape/CapsuleShape3D.js +3 -14
  9. package/src/core/geom/3d/shape/CylinderShape3D.d.ts.map +1 -1
  10. package/src/core/geom/3d/shape/CylinderShape3D.js +3 -21
  11. package/src/core/geom/3d/shape/PlaneShape3D.d.ts +105 -0
  12. package/src/core/geom/3d/shape/PlaneShape3D.d.ts.map +1 -0
  13. package/src/core/geom/3d/shape/PlaneShape3D.js +251 -0
  14. package/src/core/geom/3d/shape/SphereShape3D.js +3 -3
  15. package/src/core/geom/3d/shape/json/shape_to_type.d.ts.map +1 -1
  16. package/src/core/geom/3d/shape/json/shape_to_type.js +3 -0
  17. package/src/core/geom/3d/shape/json/type_adapters.d.ts +14 -0
  18. package/src/core/geom/3d/shape/json/type_adapters.d.ts.map +1 -1
  19. package/src/core/geom/3d/shape/json/type_adapters.js +15 -0
  20. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts +51 -0
  21. package/src/core/geom/3d/shape/sdf/sdf3_box.d.ts.map +1 -0
  22. package/src/core/geom/3d/shape/sdf/sdf3_box.js +113 -0
  23. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts +46 -0
  24. package/src/core/geom/3d/shape/sdf/sdf3_capsule.d.ts.map +1 -0
  25. package/src/core/geom/3d/shape/sdf/sdf3_capsule.js +82 -0
  26. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts +60 -0
  27. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.d.ts.map +1 -0
  28. package/src/core/geom/3d/shape/sdf/sdf3_cylinder.js +126 -0
  29. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts +50 -0
  30. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.d.ts.map +1 -0
  31. package/src/core/geom/3d/shape/sdf/sdf3_degenerate_normal.js +53 -0
  32. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts +52 -0
  33. package/src/core/geom/3d/shape/sdf/sdf3_plane.d.ts.map +1 -0
  34. package/src/core/geom/3d/shape/sdf/sdf3_plane.js +61 -0
  35. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts +41 -0
  36. package/src/core/geom/3d/shape/sdf/sdf3_sphere.d.ts.map +1 -0
  37. package/src/core/geom/3d/shape/sdf/sdf3_sphere.js +71 -0
  38. package/src/core/process/ConcurrencyGate.d.ts +103 -0
  39. package/src/core/process/ConcurrencyGate.d.ts.map +1 -0
  40. package/src/core/process/ConcurrencyGate.js +207 -0
  41. package/src/engine/asset/AssetManager.d.ts +10 -0
  42. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  43. package/src/engine/asset/AssetManager.js +10 -0
  44. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +30 -13
  45. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts +26 -0
  46. package/src/engine/graphics3/pose/collect_entity_playbacks.d.ts.map +1 -0
  47. package/src/engine/graphics3/pose/collect_entity_playbacks.js +40 -0
  48. package/src/engine/graphics3/pose/query_entity_node_world_pose.d.ts.map +1 -1
  49. package/src/engine/graphics3/pose/query_entity_node_world_pose.js +74 -101
  50. package/src/engine/physics/cloth/MEASUREMENTS.md +1287 -4
  51. package/src/engine/physics/cloth/PLAN.md +1967 -1581
  52. package/src/engine/physics/cloth/build/ClothProxy.d.ts +147 -0
  53. package/src/engine/physics/cloth/build/ClothProxy.d.ts.map +1 -0
  54. package/src/engine/physics/cloth/build/ClothProxy.js +207 -0
  55. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts +70 -0
  56. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.d.ts.map +1 -0
  57. package/src/engine/physics/cloth/build/cloth_proxy_from_joints.js +256 -0
  58. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts +176 -0
  59. package/src/engine/physics/cloth/collider/ClothColliderIndex.d.ts.map +1 -0
  60. package/src/engine/physics/cloth/collider/ClothColliderIndex.js +435 -0
  61. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts +12 -0
  62. package/src/engine/physics/cloth/collider/ClothColliderKind.d.ts.map +1 -0
  63. package/src/engine/physics/cloth/collider/ClothColliderKind.js +38 -0
  64. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts +120 -0
  65. package/src/engine/physics/cloth/collider/ClothColliderRecord.d.ts.map +1 -0
  66. package/src/engine/physics/cloth/collider/ClothColliderRecord.js +137 -0
  67. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts +25 -0
  68. package/src/engine/physics/cloth/collider/cloth_collider_bounds.d.ts.map +1 -0
  69. package/src/engine/physics/cloth/collider/cloth_collider_bounds.js +190 -0
  70. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts +44 -0
  71. package/src/engine/physics/cloth/collider/cloth_collider_pack.d.ts.map +1 -0
  72. package/src/engine/physics/cloth/collider/cloth_collider_pack.js +173 -0
  73. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts +94 -0
  74. package/src/engine/physics/cloth/collider/cloth_collider_sdf.d.ts.map +1 -0
  75. package/src/engine/physics/cloth/collider/cloth_collider_sdf.js +275 -0
  76. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts +126 -0
  77. package/src/engine/physics/cloth/ecs/ClothCollider.d.ts.map +1 -0
  78. package/src/engine/physics/cloth/ecs/ClothCollider.js +199 -0
  79. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts +9 -0
  80. package/src/engine/physics/cloth/ecs/ClothColliderFlags.d.ts.map +1 -0
  81. package/src/engine/physics/cloth/ecs/ClothColliderFlags.js +32 -0
  82. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts +114 -0
  83. package/src/engine/physics/cloth/ecs/ClothColliderSystem.d.ts.map +1 -0
  84. package/src/engine/physics/cloth/ecs/ClothColliderSystem.js +243 -0
  85. package/src/engine/physics/cloth/ecs/ClothDynamicsFlags.js +66 -57
  86. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts +109 -1
  87. package/src/engine/physics/cloth/ecs/ClothInstance.d.ts.map +1 -1
  88. package/src/engine/physics/cloth/ecs/ClothInstance.js +479 -363
  89. package/src/engine/physics/cloth/ecs/ClothRig.d.ts +95 -0
  90. package/src/engine/physics/cloth/ecs/ClothRig.d.ts.map +1 -0
  91. package/src/engine/physics/cloth/ecs/ClothRig.js +140 -0
  92. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts +30 -1
  93. package/src/engine/physics/cloth/ecs/ClothSystem.d.ts.map +1 -1
  94. package/src/engine/physics/cloth/ecs/ClothSystem.js +1021 -773
  95. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts +90 -0
  96. package/src/engine/physics/cloth/ecs/cloth_build_rows.d.ts.map +1 -0
  97. package/src/engine/physics/cloth/ecs/cloth_build_rows.js +374 -0
  98. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts +32 -3
  99. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.d.ts.map +1 -1
  100. package/src/engine/physics/cloth/ecs/cloth_dynamics_library.js +283 -254
  101. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts +59 -0
  102. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.d.ts.map +1 -0
  103. package/src/engine/physics/cloth/ecs/cloth_gather_colliders.js +328 -0
  104. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts +13 -0
  105. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.d.ts.map +1 -0
  106. package/src/engine/physics/cloth/ecs/cloth_reconstruct_pose.js +288 -0
  107. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts +58 -0
  108. package/src/engine/physics/cloth/ecs/cloth_seed_rig.d.ts.map +1 -0
  109. package/src/engine/physics/cloth/ecs/cloth_seed_rig.js +199 -0
  110. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts +8 -63
  111. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.d.ts.map +1 -1
  112. package/src/engine/physics/cloth/ecs/cloth_seed_subtree.js +317 -645
  113. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts +61 -0
  114. package/src/engine/physics/cloth/ecs/cloth_write_back.d.ts.map +1 -1
  115. package/src/engine/physics/cloth/ecs/cloth_write_back.js +212 -449
  116. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts +49 -0
  117. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.d.ts.map +1 -0
  118. package/src/engine/physics/cloth/ecs/cloth_write_back_rig.js +115 -0
  119. package/src/engine/physics/cloth/playground/README.md +155 -1
  120. package/src/engine/physics/cloth/playground/collide.html +178 -0
  121. package/src/engine/physics/cloth/playground/collide_build.d.ts +95 -0
  122. package/src/engine/physics/cloth/playground/collide_build.d.ts.map +1 -0
  123. package/src/engine/physics/cloth/playground/collide_build.js +315 -0
  124. package/src/engine/physics/cloth/playground/collide_main.d.ts +2 -0
  125. package/src/engine/physics/cloth/playground/collide_main.d.ts.map +1 -0
  126. package/src/engine/physics/cloth/playground/collide_main.js +720 -0
  127. package/src/engine/physics/cloth/playground/garment.html +182 -0
  128. package/src/engine/physics/cloth/playground/garment_build.d.ts +78 -0
  129. package/src/engine/physics/cloth/playground/garment_build.d.ts.map +1 -0
  130. package/src/engine/physics/cloth/playground/garment_build.js +359 -0
  131. package/src/engine/physics/cloth/playground/garment_main.d.ts +2 -0
  132. package/src/engine/physics/cloth/playground/garment_main.d.ts.map +1 -0
  133. package/src/engine/physics/cloth/playground/garment_main.js +633 -0
  134. package/src/engine/physics/cloth/solver/ClothState.d.ts +208 -5
  135. package/src/engine/physics/cloth/solver/ClothState.d.ts.map +1 -1
  136. package/src/engine/physics/cloth/solver/ClothState.js +302 -8
  137. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts +87 -0
  138. package/src/engine/physics/cloth/solver/cloth_contact_find.d.ts.map +1 -0
  139. package/src/engine/physics/cloth/solver/cloth_contact_find.js +343 -0
  140. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts +112 -0
  141. package/src/engine/physics/cloth/solver/cloth_self_find.d.ts.map +1 -0
  142. package/src/engine/physics/cloth/solver/cloth_self_find.js +448 -0
  143. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts +4 -1
  144. package/src/engine/physics/cloth/solver/cloth_solve_vertex.d.ts.map +1 -1
  145. package/src/engine/physics/cloth/solver/cloth_solve_vertex.js +16 -1
  146. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts +112 -5
  147. package/src/engine/physics/cloth/solver/cloth_solver_constants.d.ts.map +1 -1
  148. package/src/engine/physics/cloth/solver/cloth_solver_constants.js +117 -6
  149. package/src/engine/physics/cloth/solver/cloth_step.d.ts +40 -9
  150. package/src/engine/physics/cloth/solver/cloth_step.d.ts.map +1 -1
  151. package/src/engine/physics/cloth/solver/cloth_step.js +122 -10
  152. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts +95 -0
  153. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.d.ts.map +1 -0
  154. package/src/engine/physics/cloth/solver/constraint/cloth_backstop_row.js +285 -0
  155. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts +129 -0
  156. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.d.ts.map +1 -0
  157. package/src/engine/physics/cloth/solver/constraint/cloth_contact_row.js +501 -0
  158. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts +75 -0
  159. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.d.ts.map +1 -0
  160. package/src/engine/physics/cloth/solver/constraint/cloth_self_row.js +202 -0
  161. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  162. package/src/shade/playground/vgeo_viewer/README.md +18 -0
  163. package/src/shade/playground/vgeo_viewer/main.js +87 -50
  164. package/src/shade/renderer/buffer/table/GPUDatabase.d.ts.map +1 -1
  165. package/src/shade/renderer/buffer/table/GPUDatabase.js +191 -62
  166. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts +94 -2
  167. package/src/shade/renderer/buffer/table/GPUTypedTable.d.ts.map +1 -1
  168. package/src/shade/renderer/buffer/table/GPUTypedTable.js +414 -2
  169. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts +14 -0
  170. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.d.ts.map +1 -0
  171. package/src/shade/renderer/buffer/table/GPU_TABLE_PARTIAL_UPLOAD_DESCRIPTOR_WORDS.js +13 -0
  172. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts +17 -0
  173. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.d.ts.map +1 -0
  174. package/src/shade/renderer/buffer/table/gpu_table_partial_upload_shader.js +116 -0
  175. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts +9 -4
  176. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.d.ts.map +1 -1
  177. package/src/shade/renderer/geometry/bvh/GPUGeometryBVHManager.js +843 -734
  178. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts +12 -0
  179. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.d.ts.map +1 -1
  180. package/src/shade/renderer/geometry/bvh/GPUGeometryMeshletsBVH.js +13 -0
  181. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts +17 -0
  182. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.d.ts.map +1 -1
  183. package/src/shade/renderer/geometry/meshlet/GPUMeshletManager.js +185 -30
  184. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +17 -0
  185. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +141 -24
  186. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +204 -64
  187. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +110 -10
  188. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +19 -0
  189. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +19 -6
  190. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -1
  191. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +26 -7
  192. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +173 -14
  193. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -1
  194. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +458 -51
  195. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +49 -13
  196. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -1
  197. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +52 -14
  198. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts +20 -0
  199. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.d.ts.map +1 -0
  200. package/src/shade/renderer/geometry/virtual/format/read/tool/VGEO_MAX_AUDIT_BYTES.js +19 -0
  201. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts +27 -0
  202. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.d.ts.map +1 -0
  203. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_audit_container.js +48 -0
  204. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts +29 -0
  205. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.d.ts.map +1 -0
  206. package/src/shade/renderer/geometry/virtual/format/read/tool/vgeo_install_all_pages.js +60 -0
  207. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +8 -1
  208. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -1
  209. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +32 -2
  210. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +258 -0
  211. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +1 -0
  212. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.js +723 -0
  213. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +49 -0
  214. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +1 -0
  215. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.js +50 -0
  216. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  217. package/src/shade/renderer/postprocess/nss/NSS.d.ts +1 -1
  218. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts +3 -0
  219. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.d.ts.map +1 -1
  220. package/src/shade/renderer/texture/bindless/GPUBindlessTextureManager.js +121 -21
  221. package/src/shade/renderer/texture/virtual/README.md +6 -4
  222. package/src/shade/renderer/texture/virtual/VirtualTextureManager.d.ts.map +1 -1
  223. package/src/shade/renderer/texture/virtual/VirtualTextureManager.js +7 -0
  224. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.d.ts +3 -3
  225. package/src/shade/renderer/texture/virtual/source/VTSourceTiled.js +3 -3
  226. package/src/engine/ecs/system/SystemExecutionPhase.d.ts +0 -9
  227. package/src/engine/ecs/system/SystemExecutionPhase.d.ts.map +0 -1
  228. package/src/engine/graphics/texture/virtual/NOTES.md +0 -128
  229. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts +0 -6
  230. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.d.ts.map +0 -1
  231. package/src/engine/graphics/texture/virtual/VT_DEFAULT_PAGE_RESOLUTION.js +0 -5
  232. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +0 -49
  233. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +0 -1
  234. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.js +0 -264
  235. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +0 -44
  236. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +0 -1
  237. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.js +0 -228
  238. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts +0 -3
  239. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.d.ts.map +0 -1
  240. package/src/engine/graphics/texture/virtual/VirtualTextureUsageShader.js +0 -73
  241. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts +0 -14
  242. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.d.ts.map +0 -1
  243. package/src/engine/graphics/texture/virtual/debug/ResidencyDebugView.js +0 -85
  244. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +0 -12
  245. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +0 -1
  246. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.js +0 -63
  247. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +0 -12
  248. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +0 -1
  249. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.js +0 -243
  250. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts +0 -30
  251. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.d.ts.map +0 -1
  252. package/src/engine/graphics/texture/virtual/tile/VirtualTextureTile.js +0 -39
  253. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts +0 -9
  254. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.d.ts.map +0 -1
  255. package/src/engine/graphics/texture/virtual/tile/compose_finger_print.js +0 -24
  256. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts +0 -9
  257. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.d.ts.map +0 -1
  258. package/src/engine/graphics/texture/virtual/tile/compose_tile_address.js +0 -26
  259. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts +0 -11
  260. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +0 -1
  261. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.js +0 -12
  262. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts +0 -7
  263. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.d.ts.map +0 -1
  264. package/src/engine/graphics/texture/virtual/tile/finger_print_to_tile_address.js +0 -16
  265. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts +0 -7
  266. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.d.ts.map +0 -1
  267. package/src/engine/graphics/texture/virtual/tile/tile_address_to_finger_print.js +0 -35
@@ -0,0 +1,633 @@
1
+ import { Cloth } from "../ecs/Cloth.js";
2
+ import { CLOTH_DYNAMICS_BY_NAME } from "../ecs/cloth_dynamics_library.js";
3
+ import { PlaygroundCamera, project } from "./cloth_playground_draw.js";
4
+ import { GARMENT_PRESETS, build_garment, garment_sync_colliders } from "./garment_build.js";
5
+
6
+ /**
7
+ * # Skinned garments playground — M3
8
+ *
9
+ * `npm run dev --workspace @woosh/meep-engine`, then
10
+ * <http://localhost:5173/src/engine/physics/cloth/playground/garment.html>.
11
+ *
12
+ * The rig page (`rig.html`) is a `Cloth` over an entity subtree; this is a
13
+ * `Cloth` + a `ClothRig` over a skinned model's **joints**. Every point on
14
+ * screen is a `Node3D.transform_global` — a joint of a `Skin`, not an entity —
15
+ * and it is where it is because the solver wrote its `transform_local` and this
16
+ * page composed the chain.
17
+ *
18
+ * What it exists to show, because these are claims about a hierarchy rather
19
+ * than about an array:
20
+ *
21
+ * - **the two paths are the same solver.** Change the fabric and the garment
22
+ * behaves exactly as the same entry does on the rig page. The rows, the
23
+ * geodesics, the leashes and the colouring all come from
24
+ * `cloth_build_rows.js`, which both seeders call.
25
+ * - **the anchor is a bone.** Drive the character and the garment follows the
26
+ * chest it hangs from, evaluated on the CPU from the clips rather than read
27
+ * back from the GPU — the same evaluator a socket on the same shoulder gets.
28
+ * - **`blend = 0` is the bind pose**, carried by the animated bone. Not the
29
+ * pose the solver left behind, which is what a proxy's baked rest data buys
30
+ * over reading the joints at seed time.
31
+ *
32
+ * @author Alex Goldring
33
+ * @copyright Company Named Limited (c) 2026
34
+ */
35
+
36
+ const FIXED_STEP = 1 / 60;
37
+
38
+ const element = (id) => document.getElementById(id);
39
+
40
+ const canvas = element('view');
41
+ const context = canvas.getContext('2d');
42
+
43
+ const camera = new PlaygroundCamera();
44
+
45
+ camera.target[1] = 0.95;
46
+ camera.distance = 3.2;
47
+ camera.yaw = 0.9;
48
+ camera.pitch = 0.12;
49
+
50
+ const control = {
51
+ preset: 'cape',
52
+ dynamics: 'SILK',
53
+ links: 7,
54
+ spacing: 0.08,
55
+ motion: 'still',
56
+ collide: true,
57
+ self_collision: true,
58
+ blend: 1,
59
+ bind: true,
60
+ frames: false,
61
+ body: true,
62
+ running: true
63
+ };
64
+
65
+ /** @type {import("./garment_build.js").GarmentScene|null} */
66
+ let scene = null;
67
+
68
+ let time = 0;
69
+ let sprint_z = 0;
70
+ let step_ms = 0;
71
+
72
+ const SCREEN = new Float64Array(2);
73
+ const OTHER = new Float64Array(2);
74
+
75
+ // ------------------------------------------------------------------ build
76
+
77
+ async function rebuild() {
78
+ const entry = GARMENT_PRESETS.find(p => p.id === control.preset) ?? GARMENT_PRESETS[0];
79
+
80
+ element('preset_blurb').textContent = entry.blurb;
81
+
82
+ scene = await build_garment({
83
+ preset: control.preset,
84
+ dynamics: control.dynamics,
85
+ links: control.links,
86
+ spacing: control.spacing,
87
+ collide: control.collide,
88
+ self_collision: control.self_collision
89
+ });
90
+
91
+ time = 0;
92
+ sprint_z = 0;
93
+ }
94
+
95
+ // ------------------------------------------------------------------- step
96
+
97
+ function step_once() {
98
+ if (scene === null) {
99
+ return;
100
+ }
101
+
102
+ time += FIXED_STEP;
103
+
104
+ drive_character();
105
+
106
+ garment_sync_colliders(scene);
107
+
108
+ const cloth = scene.ecd.getComponent(scene.entity, Cloth);
109
+
110
+ cloth.blend = control.blend;
111
+
112
+ const started = performance.now();
113
+
114
+ scene.cloth.fixedUpdate(FIXED_STEP);
115
+
116
+ step_ms = performance.now() - started;
117
+ }
118
+
119
+ /**
120
+ * Move the character's own bones, and nothing else. The garment's joints belong
121
+ * to the solver — that is the authority claim, and driving them here would be
122
+ * the race it exists to prevent.
123
+ */
124
+ function drive_character() {
125
+ const root = scene.root;
126
+ const pelvis = scene.pelvis;
127
+
128
+ if (control.motion === 'still') {
129
+ root.transform_local.setTranslation(0, 0, 0);
130
+ root.transform_local.setRotation(0, 0, 0, 1);
131
+ pelvis.transform_local.setTranslation(0, 0.95, 0);
132
+ } else if (control.motion === 'walk') {
133
+ root.transform_local.setTranslation(0, 0, Math.sin(time * 1.6) * 0.9);
134
+ root.transform_local.setRotation(0, 0, 0, 1);
135
+ pelvis.transform_local.setTranslation(0, 0.95 + Math.sin(time * 6.4) * 0.02, 0);
136
+ } else if (control.motion === 'turn') {
137
+ const angle = time * 1.9;
138
+
139
+ root.transform_local.setTranslation(0, 0, 0);
140
+ root.transform_local.setRotation(0, Math.sin(angle * 0.5), 0, Math.cos(angle * 0.5));
141
+ pelvis.transform_local.setTranslation(0, 0.95, 0);
142
+ } else {
143
+ // §7 P7's own profile: a **square wave in velocity**, integrated rather
144
+ // than written as a position — a position that resets is a nine-metre
145
+ // discontinuity, which is a teleport (§7 P6) wearing a sprint's clothes.
146
+ sprint_z += (Math.floor(time) % 2 === 0 ? 9 : -9) * FIXED_STEP;
147
+
148
+ root.transform_local.setTranslation(0, 0, sprint_z);
149
+ root.transform_local.setRotation(0, 0, 0, 1);
150
+ pelvis.transform_local.setTranslation(0, 0.95, 0);
151
+ }
152
+
153
+ root.updateMatrices();
154
+ }
155
+
156
+ // ------------------------------------------------------------------- draw
157
+
158
+ function draw() {
159
+ const width = canvas.width;
160
+ const height = canvas.height;
161
+
162
+ context.clearRect(0, 0, width, height);
163
+
164
+ if (scene === null) {
165
+ return;
166
+ }
167
+
168
+ draw_ground(width, height);
169
+
170
+ if (control.body) {
171
+ draw_body(width, height);
172
+ }
173
+
174
+ if (control.bind) {
175
+ draw_bind(width, height);
176
+ }
177
+
178
+ draw_garment(width, height);
179
+
180
+ if (control.frames) {
181
+ draw_frames(width, height);
182
+ }
183
+ }
184
+
185
+ /**
186
+ * @param {Node3D} node
187
+ * @param {Float64Array} out
188
+ * @param {number} width
189
+ * @param {number} height
190
+ * @returns {number} depth
191
+ */
192
+ function project_node(node, out, width, height) {
193
+ const t = node.transform_global.translation;
194
+
195
+ return project(out, camera, t[0], t[1], t[2], width, height);
196
+ }
197
+
198
+ function draw_ground(width, height) {
199
+ context.save();
200
+ context.strokeStyle = '#1d222a';
201
+ context.lineWidth = 1;
202
+
203
+ for (let i = -6; i <= 6; i++) {
204
+ const t = i * 0.3;
205
+
206
+ context.beginPath();
207
+ project(SCREEN, camera, t, 0, -1.8, width, height);
208
+ context.moveTo(SCREEN[0], SCREEN[1]);
209
+ project(SCREEN, camera, t, 0, 1.8, width, height);
210
+ context.lineTo(SCREEN[0], SCREEN[1]);
211
+ context.stroke();
212
+
213
+ context.beginPath();
214
+ project(SCREEN, camera, -1.8, 0, t, width, height);
215
+ context.moveTo(SCREEN[0], SCREEN[1]);
216
+ project(SCREEN, camera, 1.8, 0, t, width, height);
217
+ context.lineTo(SCREEN[0], SCREEN[1]);
218
+ context.stroke();
219
+ }
220
+
221
+ context.restore();
222
+ }
223
+
224
+ function draw_body(width, height) {
225
+ context.save();
226
+ context.strokeStyle = '#4b5666';
227
+ context.lineWidth = Math.max(2, width / 500);
228
+
229
+ for (const node of scene.bone) {
230
+ if (node.parent === null) {
231
+ continue;
232
+ }
233
+
234
+ project_node(node.parent, SCREEN, width, height);
235
+ project_node(node, OTHER, width, height);
236
+
237
+ context.beginPath();
238
+ context.moveTo(SCREEN[0], SCREEN[1]);
239
+ context.lineTo(OTHER[0], OTHER[1]);
240
+ context.stroke();
241
+ }
242
+
243
+ context.restore();
244
+ }
245
+
246
+ function draw_bind(width, height) {
247
+ context.save();
248
+ context.strokeStyle = '#3a5480';
249
+ context.globalAlpha = 0.55;
250
+ context.setLineDash([3, 3]);
251
+ context.lineWidth = 1;
252
+
253
+ // The bind pose was captured at build, in the character's rest pose, so it
254
+ // is drawn where it was rather than where the character now is — which is
255
+ // the point: it is what `blend = 0` returns *to*, carried by the bone.
256
+ const bind = scene.bind;
257
+ const joint = scene.joint;
258
+
259
+ for (let i = 0; i < joint.length; i++) {
260
+ const node = joint[i];
261
+
262
+ const parent_index = joint.indexOf(node.parent);
263
+
264
+ const from = parent_index >= 0
265
+ ? bind[parent_index]
266
+ : [
267
+ node.parent.transform_global.translation[0],
268
+ node.parent.transform_global.translation[1],
269
+ node.parent.transform_global.translation[2]
270
+ ];
271
+
272
+ project(SCREEN, camera, from[0], from[1], from[2], width, height);
273
+ project(OTHER, camera, bind[i][0], bind[i][1], bind[i][2], width, height);
274
+
275
+ context.beginPath();
276
+ context.moveTo(SCREEN[0], SCREEN[1]);
277
+ context.lineTo(OTHER[0], OTHER[1]);
278
+ context.stroke();
279
+ }
280
+
281
+ context.restore();
282
+ }
283
+
284
+ function draw_garment(width, height) {
285
+ context.save();
286
+ context.strokeStyle = '#7aa2f7';
287
+ context.lineWidth = Math.max(1.5, width / 700);
288
+
289
+ for (const node of scene.joint) {
290
+ project_node(node.parent, SCREEN, width, height);
291
+ project_node(node, OTHER, width, height);
292
+
293
+ context.beginPath();
294
+ context.moveTo(SCREEN[0], SCREEN[1]);
295
+ context.lineTo(OTHER[0], OTHER[1]);
296
+ context.stroke();
297
+ }
298
+
299
+ context.fillStyle = '#9db8ff';
300
+
301
+ for (const node of scene.joint) {
302
+ project_node(node, SCREEN, width, height);
303
+
304
+ context.beginPath();
305
+ context.arc(SCREEN[0], SCREEN[1], Math.max(1.5, width / 700), 0, Math.PI * 2);
306
+ context.fill();
307
+ }
308
+
309
+ context.restore();
310
+ }
311
+
312
+ /**
313
+ * Each joint's reconstructed orientation, as an axis triple. A particle has no
314
+ * orientation, so this is §11.1's swing — the minimal rotation from the link's
315
+ * bind direction to its simulated one, and the reason the rig path can write a
316
+ * `transform_local` at all.
317
+ */
318
+ function draw_frames(width, height) {
319
+ const axes = [
320
+ ['#e5533d', 1, 0, 0],
321
+ ['#5ad19a', 0, 1, 0],
322
+ ['#6b8afd', 0, 0, 1]
323
+ ];
324
+
325
+ const length = control.spacing * 0.4;
326
+
327
+ context.save();
328
+ context.lineWidth = 1;
329
+
330
+ for (const node of scene.joint) {
331
+ const t = node.transform_global;
332
+
333
+ project(SCREEN, camera, t.translation[0], t.translation[1], t.translation[2], width, height);
334
+
335
+ for (const [colour, x, y, z] of axes) {
336
+ const qx = t.rotation[0];
337
+ const qy = t.rotation[1];
338
+ const qz = t.rotation[2];
339
+ const qw = t.rotation[3];
340
+
341
+ const tx = 2 * (qy * z - qz * y);
342
+ const ty = 2 * (qz * x - qx * z);
343
+ const tz = 2 * (qx * y - qy * x);
344
+
345
+ const dx = x + qw * tx + (qy * tz - qz * ty);
346
+ const dy = y + qw * ty + (qz * tx - qx * tz);
347
+ const dz = z + qw * tz + (qx * ty - qy * tx);
348
+
349
+ project(
350
+ OTHER, camera,
351
+ t.translation[0] + dx * length,
352
+ t.translation[1] + dy * length,
353
+ t.translation[2] + dz * length,
354
+ width, height
355
+ );
356
+
357
+ context.strokeStyle = colour;
358
+ context.beginPath();
359
+ context.moveTo(SCREEN[0], SCREEN[1]);
360
+ context.lineTo(OTHER[0], OTHER[1]);
361
+ context.stroke();
362
+ }
363
+ }
364
+
365
+ context.restore();
366
+ }
367
+
368
+ // ---------------------------------------------------------------- readout
369
+
370
+ function refresh_readout() {
371
+ if (scene === null) {
372
+ return;
373
+ }
374
+
375
+ const instance = scene.cloth.instanceOf(scene.entity);
376
+
377
+ if (instance === undefined || !instance.seeded) {
378
+ return;
379
+ }
380
+
381
+ const state = instance.state;
382
+
383
+ element('r_joints').textContent = String(scene.proxy.joint_count);
384
+ element('r_particles').textContent = String(state.particle_count);
385
+ element('r_rows').textContent = `${state.stretch_count} / ${state.leash_count}`;
386
+ element('r_contacts').textContent = String(instance.contact_count);
387
+ element('r_self').textContent = String(instance.self_pairs);
388
+ element('r_step').textContent = `${step_ms.toFixed(3)} ms`;
389
+
390
+ let worst = 0;
391
+
392
+ const anchor = instance.particle_of_node[0] * 3;
393
+
394
+ for (let node = 1; node < instance.node_count; node++) {
395
+ const p = instance.particle_of_node[node] * 3;
396
+
397
+ const distance = Math.hypot(
398
+ state.position[p] - state.position[anchor],
399
+ state.position[p + 1] - state.position[anchor + 1],
400
+ state.position[p + 2] - state.position[anchor + 2]
401
+ );
402
+
403
+ const ratio = distance / instance.geodesic[node];
404
+
405
+ if (ratio > worst) {
406
+ worst = ratio;
407
+ }
408
+ }
409
+
410
+ const reach = element('r_reach');
411
+
412
+ reach.textContent = worst.toFixed(4);
413
+ reach.className = worst > 1.05 ? 'bad' : 'good';
414
+ }
415
+
416
+ // ------------------------------------------------------------------ frame
417
+
418
+ function frame() {
419
+ if (control.running) {
420
+ step_once();
421
+ }
422
+
423
+ draw();
424
+ refresh_readout();
425
+
426
+ requestAnimationFrame(frame);
427
+ }
428
+
429
+ // --------------------------------------------------------------- controls
430
+
431
+ const preset_select = element('preset');
432
+
433
+ for (const entry of GARMENT_PRESETS) {
434
+ const option = document.createElement('option');
435
+
436
+ option.value = entry.id;
437
+ option.textContent = entry.label;
438
+
439
+ preset_select.append(option);
440
+ }
441
+
442
+ preset_select.value = control.preset;
443
+
444
+ preset_select.addEventListener('change', () => {
445
+ control.preset = preset_select.value;
446
+
447
+ const entry = GARMENT_PRESETS.find(p => p.id === control.preset);
448
+
449
+ control.links = entry.links;
450
+ control.dynamics = entry.dynamics;
451
+
452
+ element('links').value = String(control.links);
453
+ element('links_out').textContent = String(control.links);
454
+ element('dynamics').value = control.dynamics;
455
+
456
+ rebuild();
457
+ });
458
+
459
+ const dynamics_select = element('dynamics');
460
+
461
+ for (const name of Object.keys(CLOTH_DYNAMICS_BY_NAME)) {
462
+ const option = document.createElement('option');
463
+
464
+ option.value = name;
465
+ option.textContent = name.toLowerCase();
466
+
467
+ dynamics_select.append(option);
468
+ }
469
+
470
+ dynamics_select.value = control.dynamics;
471
+
472
+ dynamics_select.addEventListener('change', () => {
473
+ control.dynamics = dynamics_select.value;
474
+
475
+ rebuild();
476
+ });
477
+
478
+ /**
479
+ * @param {string} id
480
+ * @param {string} key
481
+ * @param {function(number): string} format
482
+ * @param {boolean} rebuilds
483
+ */
484
+ function slider(id, key, format, rebuilds) {
485
+ const input = element(id);
486
+ const output = element(`${id}_out`);
487
+
488
+ input.value = String(control[key]);
489
+ output.textContent = format(control[key]);
490
+
491
+ input.addEventListener('input', () => {
492
+ control[key] = Number(input.value);
493
+
494
+ output.textContent = format(control[key]);
495
+
496
+ if (rebuilds) {
497
+ rebuild();
498
+ }
499
+ });
500
+ }
501
+
502
+ slider('links', 'links', (v) => String(v), true);
503
+ slider('spacing', 'spacing', (v) => `${(v * 100).toFixed(1)} cm`, true);
504
+ slider('blend', 'blend', (v) => v.toFixed(2), false);
505
+
506
+ for (const motion of ['still', 'walk', 'turn', 'sprint']) {
507
+ element(`motion_${motion}`).addEventListener('click', () => {
508
+ control.motion = motion;
509
+
510
+ for (const other of ['still', 'walk', 'turn', 'sprint']) {
511
+ element(`motion_${other}`).classList.toggle('on', other === motion);
512
+ }
513
+ });
514
+ }
515
+
516
+ element('collide').addEventListener('click', (event) => {
517
+ control.collide = !control.collide;
518
+
519
+ event.target.classList.toggle('on', control.collide);
520
+
521
+ rebuild();
522
+ });
523
+
524
+ element('self_collision').addEventListener('click', (event) => {
525
+ control.self_collision = !control.self_collision;
526
+
527
+ event.target.classList.toggle('on', control.self_collision);
528
+
529
+ rebuild();
530
+ });
531
+
532
+ for (const [id, key] of [['view_bind', 'bind'], ['view_frames', 'frames'], ['view_body', 'body']]) {
533
+ element(id).addEventListener('click', (event) => {
534
+ control[key] = !control[key];
535
+
536
+ event.target.classList.toggle('on', control[key]);
537
+ });
538
+ }
539
+
540
+ element('pause').addEventListener('click', (event) => {
541
+ control.running = !control.running;
542
+
543
+ event.target.textContent = control.running ? 'pause' : 'resume';
544
+ });
545
+
546
+ element('single').addEventListener('click', step_once);
547
+ element('reset').addEventListener('click', rebuild);
548
+
549
+ // ----------------------------------------------------------------- camera
550
+
551
+ let drag = null;
552
+
553
+ canvas.addEventListener('pointerdown', (event) => {
554
+ canvas.setPointerCapture(event.pointerId);
555
+ canvas.classList.add('grabbing');
556
+
557
+ drag = { x: event.clientX, y: event.clientY, pan: event.shiftKey || event.button === 2 };
558
+ });
559
+
560
+ canvas.addEventListener('pointermove', (event) => {
561
+ if (drag === null) {
562
+ return;
563
+ }
564
+
565
+ const dx = event.clientX - drag.x;
566
+ const dy = event.clientY - drag.y;
567
+
568
+ drag.x = event.clientX;
569
+ drag.y = event.clientY;
570
+
571
+ if (!drag.pan) {
572
+ camera.yaw -= dx * 0.006;
573
+ camera.pitch = Math.max(-1.4, Math.min(1.4, camera.pitch + dy * 0.006));
574
+
575
+ return;
576
+ }
577
+
578
+ const scale = camera.distance * 0.0016;
579
+
580
+ camera.target[0] -= dx * Math.cos(camera.yaw) * scale;
581
+ camera.target[2] += dx * Math.sin(camera.yaw) * scale;
582
+ camera.target[1] += dy * scale;
583
+ });
584
+
585
+ function release(event) {
586
+ drag = null;
587
+
588
+ canvas.classList.remove('grabbing');
589
+
590
+ if (event !== undefined && canvas.hasPointerCapture(event.pointerId)) {
591
+ canvas.releasePointerCapture(event.pointerId);
592
+ }
593
+ }
594
+
595
+ canvas.addEventListener('pointerup', release);
596
+ canvas.addEventListener('pointercancel', release);
597
+ canvas.addEventListener('contextmenu', (event) => event.preventDefault());
598
+
599
+ canvas.addEventListener('wheel', (event) => {
600
+ event.preventDefault();
601
+
602
+ camera.distance = Math.max(0.3, Math.min(20, camera.distance * Math.exp(event.deltaY * 0.0012)));
603
+ }, { passive: false });
604
+
605
+ // ------------------------------------------------------------------ start
606
+
607
+ function resize() {
608
+ const ratio = Math.min(2, window.devicePixelRatio || 1);
609
+
610
+ canvas.width = Math.round(canvas.clientWidth * ratio);
611
+ canvas.height = Math.round(canvas.clientHeight * ratio);
612
+ }
613
+
614
+ window.addEventListener('resize', resize);
615
+
616
+ resize();
617
+
618
+ const ready = rebuild();
619
+
620
+ requestAnimationFrame(frame);
621
+
622
+ // A handle for a driver script. `rebuild` returns a promise, because
623
+ // `EntityManager#startup` does and an entity created before it resolves is
624
+ // never linked.
625
+ globalThis.cloth_garment_playground = {
626
+ control,
627
+ camera,
628
+ ready,
629
+ rebuild,
630
+ step_once,
631
+ draw,
632
+ get scene() { return scene; }
633
+ };