@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
@@ -1,363 +1,479 @@
1
- import { ClothDynamics } from "./ClothDynamics.js";
2
-
3
- /**
4
- * # One live cloth — the binding between a subtree and a `ClothState`
5
- *
6
- * Everything {@link ClothSystem} needs to step one {@link Cloth} and put the
7
- * answer back where it came from. It is a struct: no behaviour, and every array
8
- * is indexed by **node**, which is the entity's position in the subtree walk
9
- * rather than its position in the solver.
10
- *
11
- * ## Two numberings, and why they are not the same one
12
- *
13
- * `ClothState` permutes its particles into colour order and never gives that up
14
- * — the sweep is a pair of counted loops over adjacent indices precisely
15
- * because it does. So a node index and a particle index are different things,
16
- * and {@link particle_of_node} is the only place they meet. Everything on this
17
- * object is in node order; everything in `state` is in particle order; the
18
- * write-back crosses once per node per step and nothing else ever does.
19
- *
20
- * ## The local frame
21
- *
22
- * Particle positions live in the **anchor's own frame** — rigid, so translation
23
- * and rotation but not scale, following the same convention the colliders use.
24
- * That is what makes §7 P7's inertia model natural (a cloth that feels none of
25
- * its anchor's motion is one whose local coordinates simply do not change) and,
26
- * as a consequence rather than as a goal, what makes `Float32` positions ample:
27
- * the coordinates are garment-sized rather than world-sized.
28
- *
29
- * The anchor is node 0, particle `particle_of_node[0]`, sits at the local
30
- * origin, and is pinned. §11.1's "the anchor entity itself is the fixed set" is
31
- * that sentence.
32
- *
33
- * @author Alex Goldring
34
- * @copyright Company Named Limited (c) 2026
35
- */
36
- export class ClothInstance {
37
-
38
- /**
39
- * The entity carrying the {@link Cloth} component — the anchor.
40
- * @type {number}
41
- */
42
- entity = -1;
43
-
44
- /**
45
- * @type {Cloth|null}
46
- */
47
- cloth = null;
48
-
49
- /**
50
- * The anchor's world transform, which is also the cloth's local frame.
51
- * @type {Transform64|null}
52
- */
53
- transform = null;
54
-
55
- /**
56
- * How deep the anchor sits in the transform hierarchy. Instances step in
57
- * ascending depth so that a `Cloth` nested inside another one reads an
58
- * anchor the outer solve has already written this step.
59
- * @type {number}
60
- */
61
- depth = 0;
62
-
63
- /**
64
- * `false` until the subtree has been walked. Seeding is deferred to the
65
- * first step rather than done at link, because a rope's links arrive as
66
- * separate entities and the one carrying the `Cloth` has no reason to be
67
- * last.
68
- * @type {boolean}
69
- */
70
- seeded = false;
71
-
72
- /**
73
- * @type {ClothState|null}
74
- */
75
- state = null;
76
-
77
- /**
78
- * @type {number}
79
- */
80
- node_count = 0;
81
-
82
- /**
83
- * Entity per node, in walk order. Node 0 is the anchor.
84
- * @type {Int32Array|null}
85
- */
86
- node_entity = null;
87
-
88
- /**
89
- * Parent node index, `−1` for the anchor.
90
- * @type {Int32Array|null}
91
- */
92
- node_parent = null;
93
-
94
- /**
95
- * Live `Transform64` per node — the component instance, held so the step
96
- * does not go through the dataset per node per frame.
97
- * @type {Transform64[]}
98
- */
99
- node_transform = [];
100
-
101
- /**
102
- * Live `TransformAttachment` per node; `null` for the anchor.
103
- *
104
- * **While a cloth is live this is its output, not its input.** The
105
- * write-back writes the local transform as well as the world one, so that a
106
- * hierarchy recomposition reproduces the simulated pose rather than
107
- * replacing it with the authored one — which is what makes the cloth's
108
- * correctness independent of where the scheduler put it. The authored pose
109
- * is captured once, at seed, into {@link rest_local_position} and
110
- * {@link rest_local_rotation}, and lives in the cloth from then on.
111
- * @type {TransformAttachment[]}
112
- */
113
- node_attachment = [];
114
-
115
- /**
116
- * The authored local translation of each node, captured at seed, 3 per node.
117
- * Nothing else holds it once the first write-back has run.
118
- * @type {Float32Array|null}
119
- */
120
- rest_local_position = null;
121
-
122
- /**
123
- * The authored local rotation of each node, captured at seed, 4 per node.
124
- * @type {Float32Array|null}
125
- */
126
- rest_local_rotation = null;
127
-
128
- /**
129
- * CSR offsets into {@link node_child}, `node_count + 1` entries.
130
- * @type {Int32Array|null}
131
- */
132
- node_child_offset = null;
133
-
134
- /**
135
- * Simulated children per node, node indices.
136
- * @type {Int32Array|null}
137
- */
138
- node_child = null;
139
-
140
- /**
141
- * Entities the walk pruned — the root of a {@link ClothExclude} subtree, or
142
- * a nested {@link Cloth}'s anchor — paired with {@link pruned_parent}.
143
- *
144
- * They are not particles, and they still have to move: each one composes
145
- * against a link the solver just wrote. The write-back therefore poses each
146
- * of them by hand and announces there, which reaches everything below them
147
- * through the ordinary attachment cascade and reaches nothing above them.
148
- * @type {Int32Array|null}
149
- */
150
- pruned_entity = null;
151
-
152
- /**
153
- * Node each pruned entity hangs off.
154
- * @type {Int32Array|null}
155
- */
156
- pruned_parent = null;
157
-
158
- /**
159
- * @type {number}
160
- */
161
- pruned_count = 0;
162
-
163
- /**
164
- * Live `Transform64` per pruned entity.
165
- * @type {Transform64[]}
166
- */
167
- pruned_transform = [];
168
-
169
- /**
170
- * Live `TransformAttachment` per pruned entity — the local transform
171
- * this pass composes against the link the cloth just solved.
172
- * @type {TransformAttachment[]}
173
- */
174
- pruned_attachment = [];
175
-
176
- /**
177
- * Solver particle for each node.
178
- * @type {Int32Array|null}
179
- */
180
- particle_of_node = null;
181
-
182
- /**
183
- * Geodesic distance from the anchor to each node, metres — the sum of the
184
- * rest link lengths along the path, not the straight-line distance.
185
- *
186
- * This one array drives the tether radius, the slack profile and the pin,
187
- * so the three cannot disagree (§3.4). The anchor's is zero, which is what
188
- * makes it the fixed set without a second mechanism saying so.
189
- * @type {Float32Array|null}
190
- */
191
- geodesic = null;
192
-
193
- /**
194
- * The animated pose in the cloth's local frame — position, 3 per node —
195
- * composed once at seed from {@link rest_local_position} down the walk.
196
- *
197
- * **Constant, and that is a property of the entity path rather than an
198
- * optimisation.** The subtree's authored pose is rigid relative to its
199
- * anchor, so expressed in the anchor's own frame it does not move; the only
200
- * thing that changes step to step is where that frame is. A subtree whose
201
- * links are themselves animated is not an M1 case — that is the rig path,
202
- * where the animated pose comes from the skeleton (§11.2) and is live.
203
- * @type {Float32Array|null}
204
- */
205
- animated_position = null;
206
-
207
- /**
208
- * The animated pose's orientation in the cloth's local frame, 4 per node.
209
- * @type {Float32Array|null}
210
- */
211
- animated_rotation = null;
212
-
213
- /**
214
- * The pose the write-back actually writes: the simulated position lerped
215
- * towards the animated one by {@link Cloth#blend}, in node order and in
216
- * the local frame, 3 per node.
217
- *
218
- * It exists as an array rather than as a per-node temporary because the
219
- * orientation reconstruction needs a node's *neighbours* in the same
220
- * blended pose, and blending them twice — once as a neighbour, once as
221
- * themselves — is how a rounding difference becomes a visible kink.
222
- * @type {Float64Array|null}
223
- */
224
- blended_position = null;
225
-
226
- /**
227
- * The orientation the write-back reconstructed for each node, in the cloth's
228
- * local frame, 4 per node.
229
- *
230
- * Kept for the length of the pass because a node's **local** transform is
231
- * its pose relative to its parent's, so writing it needs the parent's
232
- * reconstructed rotation — and the walk is breadth-first, so by the time a
233
- * node is reached its parent is already in here.
234
- * @type {Float64Array|null}
235
- */
236
- blended_rotation = null;
237
-
238
- /**
239
- * Leash row enforcing the slack bound for each node, `−1` where there is
240
- * none — the anchor, and any node whose `slack` reaches the bound at which
241
- * the row is provably inactive.
242
- * @type {Int32Array|null}
243
- */
244
- slack_row = null;
245
-
246
- /**
247
- * Leash row enforcing the tether bound for each node, `−1` for the anchor.
248
- * @type {Int32Array|null}
249
- */
250
- tether_row = null;
251
-
252
- /**
253
- * Stretch rows carrying the parent link of each node, `−1` for the anchor.
254
- * @type {Int32Array|null}
255
- */
256
- link_row = null;
257
-
258
- /**
259
- * Strain-limit rows on the same links, `−1` when the flag is clear.
260
- * @type {Int32Array|null}
261
- */
262
- strain_row = null;
263
-
264
- /**
265
- * Skip rows — the bending model for a chain, one per node that has a
266
- * grandparent. `−1` where there is none.
267
- * @type {Int32Array|null}
268
- */
269
- skip_row = null;
270
-
271
- /**
272
- * Largest {@link geodesic} in the cloth: how far this cloth can reach from
273
- * its anchor, and the length scale the anchor limits and the teleport
274
- * threshold are derived from.
275
- * @type {number}
276
- */
277
- reach = 0;
278
-
279
- /**
280
- * Shortest row in the cloth, metres.
281
- *
282
- * The trust region caps a vertex update at the shortest row incident on
283
- * that particle (§5.3), so this is the smallest distance any particle can
284
- * be moved in one iteration — and `shortest_row · substeps · iterations`
285
- * is therefore the whole of what one fixed step can undo. The velocity
286
- * clamp is a multiple of it.
287
- * @type {number}
288
- */
289
- shortest_row = 0;
290
-
291
- /**
292
- * The anchor's world translation as of the previous step, `[x, y, z]`.
293
- * @type {Float64Array}
294
- */
295
- anchor_translation = new Float64Array(3);
296
-
297
- /**
298
- * The anchor's world rotation as of the previous step, `[x, y, z, w]`.
299
- * @type {Float64Array}
300
- */
301
- anchor_rotation = new Float64Array([0, 0, 0, 1]);
302
-
303
- /**
304
- * `false` until the first step has recorded an anchor pose to compare
305
- * against. The first step feels no inertia, which is correct: there is no
306
- * motion yet, only a starting place.
307
- * @type {boolean}
308
- */
309
- anchor_valid = false;
310
-
311
- /**
312
- * What {@link Cloth#dynamics} looked like when the rows were last
313
- * parameterised. Compared rather than watched — a value object is cheap to
314
- * compare and a dirty flag is a second thing to keep true.
315
- * @type {ClothDynamics}
316
- */
317
- dynamics_seen = new ClothDynamics();
318
-
319
- /**
320
- * Steps remaining in the post-teleport stabilisation window, during which
321
- * the velocity limit ramps back up from nothing (§7 P6). Zero when not
322
- * stabilising.
323
- * @type {number}
324
- */
325
- stabilise_remaining = 0;
326
-
327
- /**
328
- * Consecutive steps whose largest particle displacement was below the sleep
329
- * threshold.
330
- * @type {number}
331
- */
332
- still_steps = 0;
333
-
334
- /**
335
- * `true` while the cloth is neither stepped nor written back (§7 P5).
336
- *
337
- * The write-back is skipped as well as the step, and that is the whole of
338
- * what makes P5's "bit-identical across the following 300 steps" a fact
339
- * rather than a hope: a pose that is not rewritten cannot drift, and one
340
- * that is rewritten from unchanged inputs is only *probably* identical.
341
- * @type {boolean}
342
- */
343
- asleep = false;
344
-
345
- /**
346
- * What {@link Cloth#blend} was when the write-back last ran.
347
- *
348
- * Sleep skips the write-back, so a `blend` written while a cloth is asleep
349
- * would otherwise take effect at some arbitrary later moment — the next
350
- * time something else happened to wake it. A blend change is a request to
351
- * see a different pose, so it wakes the cloth like any other.
352
- * @type {number}
353
- */
354
- blend_seen = 1;
355
-
356
- /**
357
- * How many times this cloth has been re-seeded by a teleport. Diagnostic:
358
- * a cloth resetting every few seconds is being driven by something that
359
- * looks like a teleport and is not one.
360
- * @type {number}
361
- */
362
- teleport_count = 0;
363
- }
1
+ import { Transform64 } from "../../../ecs/transform/Transform64.js";
2
+ import { ClothDynamics } from "./ClothDynamics.js";
3
+
4
+ /**
5
+ * # One live cloth — the binding between a subtree and a `ClothState`
6
+ *
7
+ * Everything {@link ClothSystem} needs to step one {@link Cloth} and put the
8
+ * answer back where it came from. It is a struct: no behaviour, and every array
9
+ * is indexed by **node**, which is the entity's position in the subtree walk
10
+ * rather than its position in the solver.
11
+ *
12
+ * ## Two numberings, and why they are not the same one
13
+ *
14
+ * `ClothState` permutes its particles into colour order and never gives that up
15
+ * — the sweep is a pair of counted loops over adjacent indices precisely
16
+ * because it does. So a node index and a particle index are different things,
17
+ * and {@link particle_of_node} is the only place they meet. Everything on this
18
+ * object is in node order; everything in `state` is in particle order; the
19
+ * write-back crosses once per node per step and nothing else ever does.
20
+ *
21
+ * ## The local frame
22
+ *
23
+ * Particle positions live in the **anchor's own frame** — rigid, so translation
24
+ * and rotation but not scale, following the same convention the colliders use.
25
+ * That is what makes §7 P7's inertia model natural (a cloth that feels none of
26
+ * its anchor's motion is one whose local coordinates simply do not change) and,
27
+ * as a consequence rather than as a goal, what makes `Float32` positions ample:
28
+ * the coordinates are garment-sized rather than world-sized.
29
+ *
30
+ * The anchor is node 0, particle `particle_of_node[0]`, sits at the local
31
+ * origin, and is pinned. §11.1's "the anchor entity itself is the fixed set" is
32
+ * that sentence.
33
+ *
34
+ * @author Alex Goldring
35
+ * @copyright Company Named Limited (c) 2026
36
+ */
37
+ export class ClothInstance {
38
+
39
+ /**
40
+ * The entity carrying the {@link Cloth} component — the anchor.
41
+ * @type {number}
42
+ */
43
+ entity = -1;
44
+
45
+ /**
46
+ * @type {Cloth|null}
47
+ */
48
+ cloth = null;
49
+
50
+ /**
51
+ * The anchor's world transform, which is also the cloth's local frame.
52
+ * @type {Transform64|null}
53
+ */
54
+ transform = null;
55
+
56
+ /**
57
+ * How deep the anchor sits in the transform hierarchy. Instances step in
58
+ * ascending depth so that a `Cloth` nested inside another one reads an
59
+ * anchor the outer solve has already written this step.
60
+ * @type {number}
61
+ */
62
+ depth = 0;
63
+
64
+ /**
65
+ * `false` until the subtree has been walked. Seeding is deferred to the
66
+ * first step rather than done at link, because a rope's links arrive as
67
+ * separate entities and the one carrying the `Cloth` has no reason to be
68
+ * last.
69
+ * @type {boolean}
70
+ */
71
+ seeded = false;
72
+
73
+ /**
74
+ * @type {ClothState|null}
75
+ */
76
+ state = null;
77
+
78
+ /**
79
+ * @type {number}
80
+ */
81
+ node_count = 0;
82
+
83
+ /**
84
+ * Entity per node, in walk order. Node 0 is the anchor.
85
+ * @type {Int32Array|null}
86
+ */
87
+ node_entity = null;
88
+
89
+ /**
90
+ * Parent node index, `−1` for the anchor.
91
+ * @type {Int32Array|null}
92
+ */
93
+ node_parent = null;
94
+
95
+ /**
96
+ * The {@link ClothRig} beside the {@link Cloth}, or `null` for a cloth that
97
+ * simulates its own entity subtree.
98
+ *
99
+ * This is the discriminator, and it is a component's presence rather than
100
+ * an enum (§3.1). Held here rather than looked up per step because it is
101
+ * what says which seeder ran and therefore which of the two sets of arrays
102
+ * below is the live one.
103
+ * @type {ClothRig|null}
104
+ */
105
+ rig = null;
106
+
107
+ /**
108
+ * Live `Transform64` per node — the component instance, held so the step
109
+ * does not go through the dataset per node per frame. **Entity path only.**
110
+ * @type {Transform64[]}
111
+ */
112
+ node_transform = [];
113
+
114
+ /**
115
+ * Live `Node3D` per node — the joint each node drives. **Rig path only**,
116
+ * and node 0 is the anchor joint, which is not simulated.
117
+ *
118
+ * A joint rather than an entity because a skinned model's joints are not
119
+ * entities and will not be (D47): they are `Node3D`s inside the entity's
120
+ * `SceneBundleInstance`, and the only writable handle is
121
+ * `Node3D.transform_local`.
122
+ * @type {Node3D[]}
123
+ */
124
+ node_joint = [];
125
+
126
+ /**
127
+ * The anchor joint's **world** pose, evaluated on the CPU each step from the
128
+ * clips the entity is playing. **Rig path only.**
129
+ *
130
+ * Evaluated rather than read: a joint of an animated skeleton is under
131
+ * `TransformAuthority.GPU`, so its own `transform_global` is not maintained
132
+ * on the CPU at all and reading it would place the garment wherever the node
133
+ * was last posed by hand. `pose_evaluate_world` is the sanctioned answer and
134
+ * the one a socket on the same skeleton gets, which is what keeps a cape on
135
+ * the shoulder a scabbard hangs from.
136
+ * @type {Transform64}
137
+ */
138
+ anchor_pose = new Transform64();
139
+
140
+ /**
141
+ * Live `TransformAttachment` per node; `null` for the anchor.
142
+ *
143
+ * **While a cloth is live this is its output, not its input.** The
144
+ * write-back writes the local transform as well as the world one, so that a
145
+ * hierarchy recomposition reproduces the simulated pose rather than
146
+ * replacing it with the authored one — which is what makes the cloth's
147
+ * correctness independent of where the scheduler put it. The authored pose
148
+ * is captured once, at seed, into {@link rest_local_position} and
149
+ * {@link rest_local_rotation}, and lives in the cloth from then on.
150
+ * @type {TransformAttachment[]}
151
+ */
152
+ node_attachment = [];
153
+
154
+ /**
155
+ * The authored local translation of each node, captured at seed, 3 per node.
156
+ * Nothing else holds it once the first write-back has run.
157
+ * @type {Float32Array|null}
158
+ */
159
+ rest_local_position = null;
160
+
161
+ /**
162
+ * The authored local rotation of each node, captured at seed, 4 per node.
163
+ * @type {Float32Array|null}
164
+ */
165
+ rest_local_rotation = null;
166
+
167
+ /**
168
+ * CSR offsets into {@link node_child}, `node_count + 1` entries.
169
+ * @type {Int32Array|null}
170
+ */
171
+ node_child_offset = null;
172
+
173
+ /**
174
+ * Simulated children per node, node indices.
175
+ * @type {Int32Array|null}
176
+ */
177
+ node_child = null;
178
+
179
+ /**
180
+ * Entities the walk pruned — the root of a {@link ClothExclude} subtree, or
181
+ * a nested {@link Cloth}'s anchor — paired with {@link pruned_parent}.
182
+ *
183
+ * They are not particles, and they still have to move: each one composes
184
+ * against a link the solver just wrote. The write-back therefore poses each
185
+ * of them by hand and announces there, which reaches everything below them
186
+ * through the ordinary attachment cascade and reaches nothing above them.
187
+ * @type {Int32Array|null}
188
+ */
189
+ pruned_entity = null;
190
+
191
+ /**
192
+ * Node each pruned entity hangs off.
193
+ * @type {Int32Array|null}
194
+ */
195
+ pruned_parent = null;
196
+
197
+ /**
198
+ * @type {number}
199
+ */
200
+ pruned_count = 0;
201
+
202
+ /**
203
+ * Live `Transform64` per pruned entity.
204
+ * @type {Transform64[]}
205
+ */
206
+ pruned_transform = [];
207
+
208
+ /**
209
+ * Live `TransformAttachment` per pruned entity — the local transform
210
+ * this pass composes against the link the cloth just solved.
211
+ * @type {TransformAttachment[]}
212
+ */
213
+ pruned_attachment = [];
214
+
215
+ /**
216
+ * Solver particle for each node.
217
+ * @type {Int32Array|null}
218
+ */
219
+ particle_of_node = null;
220
+
221
+ /**
222
+ * Geodesic distance from the anchor to each node, metres — the sum of the
223
+ * rest link lengths along the path, not the straight-line distance.
224
+ *
225
+ * This one array drives the tether radius, the slack profile and the pin,
226
+ * so the three cannot disagree (§3.4). The anchor's is zero, which is what
227
+ * makes it the fixed set without a second mechanism saying so.
228
+ * @type {Float32Array|null}
229
+ */
230
+ geodesic = null;
231
+
232
+ /**
233
+ * The animated pose in the cloth's local frame — position, 3 per node —
234
+ * composed once at seed from {@link rest_local_position} down the walk.
235
+ *
236
+ * **Constant, and that is a property of the entity path rather than an
237
+ * optimisation.** The subtree's authored pose is rigid relative to its
238
+ * anchor, so expressed in the anchor's own frame it does not move; the only
239
+ * thing that changes step to step is where that frame is. A subtree whose
240
+ * links are themselves animated is not an M1 case — that is the rig path,
241
+ * where the animated pose comes from the skeleton (§11.2) and is live.
242
+ * @type {Float32Array|null}
243
+ */
244
+ animated_position = null;
245
+
246
+ /**
247
+ * The animated pose's orientation in the cloth's local frame, 4 per node.
248
+ * @type {Float32Array|null}
249
+ */
250
+ animated_rotation = null;
251
+
252
+ /**
253
+ * The pose the write-back actually writes: the simulated position lerped
254
+ * towards the animated one by {@link Cloth#blend}, in node order and in
255
+ * the local frame, 3 per node.
256
+ *
257
+ * It exists as an array rather than as a per-node temporary because the
258
+ * orientation reconstruction needs a node's *neighbours* in the same
259
+ * blended pose, and blending them twice — once as a neighbour, once as
260
+ * themselves — is how a rounding difference becomes a visible kink.
261
+ * @type {Float64Array|null}
262
+ */
263
+ blended_position = null;
264
+
265
+ /**
266
+ * The orientation the write-back reconstructed for each node, in the cloth's
267
+ * local frame, 4 per node.
268
+ *
269
+ * Kept for the length of the pass because a node's **local** transform is
270
+ * its pose relative to its parent's, so writing it needs the parent's
271
+ * reconstructed rotation — and the walk is breadth-first, so by the time a
272
+ * node is reached its parent is already in here.
273
+ * @type {Float64Array|null}
274
+ */
275
+ blended_rotation = null;
276
+
277
+ /**
278
+ * Leash row enforcing the slack bound for each node, `−1` where there is
279
+ * none — the anchor, and any node whose `slack` reaches the bound at which
280
+ * the row is provably inactive.
281
+ * @type {Int32Array|null}
282
+ */
283
+ slack_row = null;
284
+
285
+ /**
286
+ * Leash row enforcing the tether bound for each node, `−1` for the anchor.
287
+ * @type {Int32Array|null}
288
+ */
289
+ tether_row = null;
290
+
291
+ /**
292
+ * Stretch rows carrying the parent link of each node, `−1` for the anchor.
293
+ * @type {Int32Array|null}
294
+ */
295
+ link_row = null;
296
+
297
+ /**
298
+ * Strain-limit rows on the same links, `−1` when the flag is clear.
299
+ * @type {Int32Array|null}
300
+ */
301
+ strain_row = null;
302
+
303
+ /**
304
+ * Skip rows — the bending model for a chain, one per node that has a
305
+ * grandparent. `−1` where there is none.
306
+ * @type {Int32Array|null}
307
+ */
308
+ skip_row = null;
309
+
310
+ /**
311
+ * Largest {@link geodesic} in the cloth: how far this cloth can reach from
312
+ * its anchor, and the length scale the anchor limits and the teleport
313
+ * threshold are derived from.
314
+ * @type {number}
315
+ */
316
+ reach = 0;
317
+
318
+ /**
319
+ * Shortest row in the cloth, metres.
320
+ *
321
+ * The trust region caps a vertex update at the shortest row incident on
322
+ * that particle (§5.3), so this is the smallest distance any particle can
323
+ * be moved in one iteration — and `shortest_row · substeps · iterations`
324
+ * is therefore the whole of what one fixed step can undo. The velocity
325
+ * clamp is a multiple of it.
326
+ * @type {number}
327
+ */
328
+ shortest_row = 0;
329
+
330
+ /**
331
+ * The anchor's world translation as of the previous step, `[x, y, z]`.
332
+ * @type {Float64Array}
333
+ */
334
+ anchor_translation = new Float64Array(3);
335
+
336
+ /**
337
+ * The anchor's world rotation as of the previous step, `[x, y, z, w]`.
338
+ * @type {Float64Array}
339
+ */
340
+ anchor_rotation = new Float64Array([0, 0, 0, 1]);
341
+
342
+ /**
343
+ * `false` until the first step has recorded an anchor pose to compare
344
+ * against. The first step feels no inertia, which is correct: there is no
345
+ * motion yet, only a starting place.
346
+ * @type {boolean}
347
+ */
348
+ anchor_valid = false;
349
+
350
+ /**
351
+ * What {@link Cloth#dynamics} looked like when the rows were last
352
+ * parameterised. Compared rather than watched — a value object is cheap to
353
+ * compare and a dirty flag is a second thing to keep true.
354
+ * @type {ClothDynamics}
355
+ */
356
+ dynamics_seen = new ClothDynamics();
357
+
358
+ /**
359
+ * Steps remaining in the post-teleport stabilisation window, during which
360
+ * the velocity limit ramps back up from nothing (§7 P6). Zero when not
361
+ * stabilising.
362
+ * @type {number}
363
+ */
364
+ stabilise_remaining = 0;
365
+
366
+ /**
367
+ * Consecutive steps whose largest particle displacement was below the sleep
368
+ * threshold.
369
+ * @type {number}
370
+ */
371
+ still_steps = 0;
372
+
373
+ /**
374
+ * `true` while the cloth is neither stepped nor written back (§7 P5).
375
+ *
376
+ * The write-back is skipped as well as the step, and that is the whole of
377
+ * what makes P5's "bit-identical across the following 300 steps" a fact
378
+ * rather than a hope: a pose that is not rewritten cannot drift, and one
379
+ * that is rewritten from unchanged inputs is only *probably* identical.
380
+ * @type {boolean}
381
+ */
382
+ asleep = false;
383
+
384
+ /**
385
+ * What {@link Cloth#blend} was when the write-back last ran.
386
+ *
387
+ * Sleep skips the write-back, so a `blend` written while a cloth is asleep
388
+ * would otherwise take effect at some arbitrary later moment — the next
389
+ * time something else happened to wake it. A blend change is a request to
390
+ * see a different pose, so it wakes the cloth like any other.
391
+ * @type {number}
392
+ */
393
+ blend_seen = 1;
394
+
395
+ /**
396
+ * The colliders overlapping this cloth this step, packed in **its own
397
+ * frame** rather than the world's — the same layout `ClothColliderIndex`
398
+ * uses, in `Float32` rather than `Float64` because a cloth-local coordinate
399
+ * is garment-sized (§12).
400
+ *
401
+ * Grown, never shrunk, and rewritten every step by
402
+ * `cloth_gather_colliders`. It lives on the instance rather than inside
403
+ * {@link state}'s buffer because its size is a property of the *world* — how
404
+ * many colliders happen to be near this cloth right now — and `ClothState`'s
405
+ * one allocation is sized from the cloth. §12 puts it in the shared buffer
406
+ * when M5 needs it there.
407
+ * @type {Float32Array|null}
408
+ */
409
+ collider_table = null;
410
+
411
+ /**
412
+ * The index handle behind each record in {@link collider_table}. A record
413
+ * index is this step's; a handle is the collider's, and it is what a
414
+ * transient contact's multiplier is warm-started on.
415
+ * @type {Int32Array|null}
416
+ */
417
+ collider_key = null;
418
+
419
+ /**
420
+ * Live records in {@link collider_table}.
421
+ * @type {number}
422
+ */
423
+ collider_count = 0;
424
+
425
+ /**
426
+ * Which particle pairs a self-collision row must never be built on, because
427
+ * a persistent row already governs them (§9). CSR, sorted, built at seed and
428
+ * replaced by a re-seed — it depends only on the row tables, so nothing about
429
+ * a `ClothDynamics` change can invalidate it short of the rows themselves
430
+ * changing, and those changes all go through `cloth_build_rows`.
431
+ * @type {{offset: Int32Array, partner: Int32Array}|null}
432
+ */
433
+ self_exclusions = null;
434
+
435
+ /**
436
+ * How close two particles get in the **bind pose** with no row between them,
437
+ * metres — or `Infinity` when nothing is within reach of anything.
438
+ *
439
+ * The ceiling on a self-collision row's radius, and the reason it is a
440
+ * measured length rather than a multiple of {@link shortest_row}: on a
441
+ * triangulated sheet the two agree, and on a rigged garment — strips with
442
+ * nothing joining one to the next — they do not agree at all.
443
+ * `CLOTH_SELF_RADIUS_MAX_RATIO` and `MEASUREMENTS.md` §37.
444
+ * @type {number}
445
+ */
446
+ closest_free_pair = Infinity;
447
+
448
+ /**
449
+ * Self-collision pairs the last step found. Diagnostic, and the one to
450
+ * watch: a garment pinned at `CLOTH_SELF_PAIRS_PER_PARTICLE` per particle is
451
+ * one whose pairs are being dropped.
452
+ * @type {number}
453
+ */
454
+ self_pairs = 0;
455
+
456
+ /**
457
+ * Contact rows the last step created. Diagnostic — a garment whose contact
458
+ * count is pinned at four per particle is one whose collider set has more
459
+ * overlap than `CLOTH_CONTACT_SLOTS` can express.
460
+ * @type {number}
461
+ */
462
+ contact_count = 0;
463
+
464
+ /**
465
+ * `true` once the system has said why this cloth will not seed and stopped
466
+ * asking. A proxy that does not fit its skin will not start fitting it, and a
467
+ * warning a frame is a log nobody reads.
468
+ * @type {boolean}
469
+ */
470
+ refused = false;
471
+
472
+ /**
473
+ * How many times this cloth has been re-seeded by a teleport. Diagnostic:
474
+ * a cloth resetting every few seconds is being driven by something that
475
+ * looks like a teleport and is not one.
476
+ * @type {number}
477
+ */
478
+ teleport_count = 0;
479
+ }