@woosh/meep-engine 3.60.4 → 3.60.5

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 (379) hide show
  1. package/CHANGELOG.md +2602 -0
  2. package/CONTRIBUTING.md +7 -0
  3. package/MIGRATION_2_TO_3.md +136 -0
  4. package/SECURITY.md +4 -0
  5. package/editor/EditorCameraNavigation.d.ts +2 -1
  6. package/editor/EditorCameraNavigation.d.ts.map +1 -1
  7. package/editor/EditorCameraNavigation.js +51 -57
  8. package/package.json +6 -2
  9. package/src/engine/EngineHarness.d.ts +3 -9
  10. package/src/engine/EngineHarness.d.ts.map +1 -1
  11. package/src/engine/EngineHarness.js +6 -8
  12. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
  13. package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
  14. package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
  15. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
  16. package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
  17. package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
  18. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
  19. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
  20. package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
  21. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
  22. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
  23. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
  24. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
  25. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
  26. package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
  27. package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
  28. package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
  29. package/src/engine/graphics/ecs/water/Water.js +8 -0
  30. package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
  31. package/src/engine/graphics3/WaterSystem.js +731 -734
  32. package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
  33. package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
  34. package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
  35. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
  36. package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
  37. package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
  38. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
  39. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
  40. package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
  41. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
  42. package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
  43. package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
  44. package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
  45. package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
  46. package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
  47. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
  48. package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
  49. package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
  50. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
  51. package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
  52. package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
  53. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
  54. package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
  55. package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
  56. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
  57. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  58. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
  59. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  60. package/src/shade/playground/water_refraction/README.md +5 -6
  61. package/src/shade/playground/water_refraction/index.html +1 -1
  62. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  63. package/src/shade/renderer/Renderer.js +7 -5
  64. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
  65. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  66. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
  67. package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
  68. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
  69. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
  70. package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
  71. package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
  72. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +2 -2
  73. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +2 -2
  74. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +2 -1
  75. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
  76. package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +18 -1
  77. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
  78. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
  79. package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
  80. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
  81. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
  82. package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
  83. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
  84. package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
  85. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  86. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
  87. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +5 -5
  88. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
  89. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +10 -10
  90. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
  91. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  92. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
  93. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
  94. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
  95. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
  96. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
  97. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
  98. package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
  99. package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
  100. package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
  101. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
  102. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
  103. package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
  104. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
  105. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
  106. package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
  107. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
  108. package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
  109. package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
  110. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
  111. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
  112. package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
  113. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
  114. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
  115. package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
  116. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
  117. package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
  118. package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
  119. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
  120. package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
  121. package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
  122. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
  123. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
  124. package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
  125. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
  126. package/src/shade/renderer/material/GPUMaterialManager.d.ts +7 -0
  127. package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
  128. package/src/shade/renderer/material/GPUMaterialManager.js +11 -0
  129. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
  130. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
  131. package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
  132. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
  133. package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
  134. package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
  135. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  136. package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
  137. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
  138. package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
  139. package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
  140. package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
  141. package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
  142. package/src/shade/renderer/water/shader_water.js +22 -13
  143. package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
  144. package/src/shade/renderer/water/shader_water_avboit.js +7 -7
  145. package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
  146. package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
  147. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
  148. package/editor/REWORK_PLAN_2026_08.md +0 -692
  149. package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
  150. package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
  151. package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
  152. package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
  153. package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
  154. package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
  155. package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
  156. package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
  157. package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
  158. package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
  159. package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
  160. package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
  161. package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
  162. package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
  163. package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
  164. package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
  165. package/src/REVIEW_2026_08_06/adv-core.md +0 -511
  166. package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
  167. package/src/REVIEW_2026_08_06/adv-view.md +0 -446
  168. package/src/REVIEW_2026_08_06/api-core.md +0 -296
  169. package/src/REVIEW_2026_08_06/api-engine.md +0 -195
  170. package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
  171. package/src/REVIEW_2026_08_06/core-binary.md +0 -348
  172. package/src/REVIEW_2026_08_06/core-collection.md +0 -376
  173. package/src/REVIEW_2026_08_06/core-math.md +0 -221
  174. package/src/REVIEW_2026_08_06/core-process.md +0 -266
  175. package/src/REVIEW_2026_08_06/core-science.md +0 -223
  176. package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
  177. package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
  178. package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
  179. package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
  180. package/src/REVIEW_2026_08_06/engine-input.md +0 -197
  181. package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
  182. package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
  183. package/src/REVIEW_2026_08_06/generation.md +0 -176
  184. package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
  185. package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
  186. package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
  187. package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
  188. package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
  189. package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
  190. package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
  191. package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
  192. package/src/REVIEW_2026_08_06/view.md +0 -667
  193. package/src/REVIEW_2026_08_06.md +0 -610
  194. package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
  195. package/src/core/bvh2/bvh3/NOTES.md +0 -2
  196. package/src/core/bvh8/NOTES.md +0 -63
  197. package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
  198. package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
  199. package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
  200. package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
  201. package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
  202. package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
  203. package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
  204. package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
  205. package/src/core/geom/3d/gjk/NOTES.md +0 -8
  206. package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
  207. package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
  208. package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
  209. package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
  210. package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
  211. package/src/engine/REVIEW_2026_07_03.md +0 -211
  212. package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
  213. package/src/engine/control/first-person/DESIGN.md +0 -658
  214. package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
  215. package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
  216. package/src/engine/control/first-person/TODO.md +0 -160
  217. package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
  218. package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
  219. package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
  220. package/src/engine/ecs/ik/PLAN.md +0 -179
  221. package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
  222. package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
  223. package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
  224. package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
  225. package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
  226. package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
  227. package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
  228. package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
  229. package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
  230. package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
  231. package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
  232. package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
  233. package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
  234. package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
  235. package/src/engine/network/CONGESTION_CONTROL.md +0 -87
  236. package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
  237. package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
  238. package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
  239. package/src/engine/physics/cloth/PLAN.md +0 -3056
  240. package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
  241. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
  242. package/src/engine/physics/fluid/solver/NOTES.md +0 -46
  243. package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
  244. package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
  245. package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
  246. package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
  247. package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
  248. package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
  249. package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
  250. package/src/format/image/avif/DECISIONS.md +0 -545
  251. package/src/format/image/jpeg/NOTES.md +0 -3
  252. package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
  253. package/src/generation/COORDINATES.md +0 -54
  254. package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
  255. package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
  256. package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
  257. package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
  258. package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
  259. package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
  260. package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
  261. package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
  262. package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
  263. package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
  264. package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
  265. package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
  266. package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
  267. package/src/shade/RENDERER_CONTRACT.md +0 -697
  268. package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
  269. package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
  270. package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
  271. package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
  272. package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
  273. package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
  274. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
  275. package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
  276. package/src/shade/renderer/NOTES.md +0 -78
  277. package/src/shade/renderer/PLAN.md +0 -8
  278. package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
  279. package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
  280. package/src/shade/renderer/atmosphere/NOTES.md +0 -6
  281. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
  282. package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
  283. package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
  284. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
  285. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
  286. package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
  287. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
  288. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
  289. package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
  290. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
  291. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
  292. package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
  293. package/src/shade/renderer/camera/orbital/README.md +0 -81
  294. package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
  295. package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
  296. package/src/shade/renderer/camera/orbital/index.js +0 -9
  297. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
  298. package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
  299. package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
  300. package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
  301. package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
  302. package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
  303. package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
  304. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
  305. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
  306. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
  307. package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
  308. package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
  309. package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
  310. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
  311. package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
  312. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
  313. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
  314. package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
  315. package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
  316. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
  317. package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
  318. package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
  319. package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
  320. package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
  321. package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
  322. package/src/shade/renderer/hiz/NOTES.md +0 -3
  323. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
  324. package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
  325. package/src/shade/renderer/light/cluster/NOTES.md +0 -11
  326. package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
  327. package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
  328. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
  329. package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
  330. package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
  331. package/src/shade/renderer/particles/DESIGN.md +0 -1011
  332. package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
  333. package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
  334. package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
  335. package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
  336. package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
  337. package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
  338. package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
  339. package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
  340. package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
  341. package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
  342. package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
  343. package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
  344. package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
  345. package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
  346. package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
  347. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
  348. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
  349. package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
  350. package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
  351. package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
  352. package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
  353. package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
  354. package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
  355. package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
  356. package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
  357. package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
  358. package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
  359. package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
  360. package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
  361. package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
  362. package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
  363. package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
  364. package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
  365. package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
  366. package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
  367. package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
  368. package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
  369. package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
  370. package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
  371. package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
  372. package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
  373. package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
  374. package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
  375. package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
  376. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
  377. package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
  378. package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
  379. package/src/shade/wgsl/NOTES.md +0 -4
@@ -1,109 +1,125 @@
1
1
  import { assert } from "../../../../core/assert.js";
2
- import { clamp } from "../../../../core/math/clamp.js";
3
2
  import Vector3 from "../../../../core/geom/Vector3.js";
3
+ import { NumericInterval } from "../../../../core/math/interval/NumericInterval.js";
4
+ import { clamp } from "../../../../core/math/clamp.js";
5
+ import { clamp01 } from "../../../../core/math/clamp01.js";
6
+ import { lerp } from "../../../../core/math/lerp.js";
7
+ import { current_time_in_seconds } from "../../../../core/time/current_time_in_seconds.js";
4
8
  import { t64_equals_components } from "../../../../engine/ecs/transform/t64_equals_components.js";
5
9
  import { Transform64 } from "../../../../engine/ecs/transform/Transform64.js";
6
- import { current_time_in_seconds } from "../../../../core/time/current_time_in_seconds.js";
10
+ import { OrbitalCameraRig } from "../../../../engine/graphics/camera/orbital/OrbitalCameraRig.js";
11
+ import TopDownCameraController, {
12
+ computeTopDownTransform,
13
+ top_down_truck_in_view
14
+ } from "../../../../engine/graphics/ecs/camera/topdown/TopDownCameraController.js";
7
15
  import KeyboardDevice from "../../../../engine/input/devices/KeyboardDevice.js";
16
+ import { MouseEventButtons } from "../../../../engine/input/devices/mouse/MouseEventButtons.js";
8
17
  import { PointerDevice } from "../../../../engine/input/devices/PointerDevice.js";
9
- import { OrbitalCameraRig } from "./OrbitalCameraRig.js";
10
- import { OrbitalCameraInput } from "./OrbitalCameraInput.js";
11
- import { createOrbitalCameraConfig } from "./OrbitalCameraConfig.js";
18
+
19
+ const RAD_TO_DEG = 180 / Math.PI;
12
20
 
13
21
  /**
14
- * Smoothed orbital camera controller — a drop-in replacement for the legacy
15
- * {@link ../OrbitalCameraController.js} that adds frame-rate-independent inertia
16
- * via meep's critically-damped springs.
17
- *
18
- * It is a thin FACADE over two decoupled, independently-testable layers:
19
- * - {@link OrbitalCameraRig} — pure control core (springs + goals, no DOM/clock)
20
- * - {@link OrbitalCameraInput} — input adapter (events → rig intents, no kinematics)
22
+ * Seconds; a frame time beyond this is a tab coming back or a hitch, not motion to integrate.
23
+ * @type {number}
24
+ */
25
+ const MAX_DT = 0.1;
26
+
27
+ /**
28
+ * Orbital camera for a Shade {@link PerspectiveCamera} outside the ECS: drag to orbit, right-drag to
29
+ * pan, wheel to zoom, W/A/S/D to fly the target along the view.
21
30
  *
22
- * The facade owns only the things that genuinely need the outside world: device
23
- * lifecycle, the frame `dt`, writing the result onto the camera's transform, and
24
- * the "camera moved outside our control" detection contract. The public surface
25
- * ({@link look}, {@link from_transform}, {@link pan}, {@link update},
26
- * `distanceLimits`, `movement_speed_scale`, `camera`) matches the legacy
27
- * controller so switching is a single import change.
31
+ * The pose is a {@link TopDownCameraController} of its own, the same one an ECS camera carries, and
32
+ * an {@link OrbitalCameraRig} moves it with the feel every orbital camera in the engine shares. Each
33
+ * {@link update} writes the pose onto the camera's transform, and a transform moved by anyone else
34
+ * since is adopted as the new pose instead.
28
35
  *
29
- * @author Alex Goldring (orbital rework)
36
+ * @author Alex Goldring
30
37
  * @copyright Company Named Limited (c) 2026
31
38
  */
32
39
  export class OrbitalCameraController {
40
+ /**
41
+ * Zoom range, world units. Mutate `.min`/`.max` or `set()`; it applies from the next
42
+ * {@link look} or {@link update}.
43
+ * @type {NumericInterval}
44
+ */
45
+ distanceLimits = new NumericInterval(0.1, 1000);
46
+
47
+ /**
48
+ * W/A/S/D speed, world units a second with the camera at the near end of {@link distanceLimits},
49
+ * rising to twice that at the far end.
50
+ * @type {number}
51
+ */
52
+ movement_speed_scale = 1;
53
+
54
+ /**
55
+ * @type {TopDownCameraController}
56
+ */
57
+ pose = new TopDownCameraController();
58
+
59
+ /**
60
+ * the camera transform as this last left it, to tell when someone else moved it
61
+ * @type {Transform64}
62
+ */
63
+ #last_recorded = new Transform64();
64
+
65
+ /**
66
+ * the pose as last written, so a pose that did not change is not written again
67
+ * @type {TopDownCameraController}
68
+ */
69
+ #last_pose = new TopDownCameraController();
70
+
71
+ /**
72
+ * @type {number}
73
+ */
74
+ #last_update_time = current_time_in_seconds();
75
+
76
+ #scratch_eye = new Vector3();
77
+ #scratch_target = new Vector3();
78
+
33
79
  /**
34
80
  * @param {import("../PerspectiveCamera.js").PerspectiveCamera} camera
35
81
  * @param {HTMLElement} domElement
36
- * @param {Partial<import("./OrbitalCameraConfig.js").ORBITAL_CAMERA_FEEL_DEFAULTS>} [configOverrides]
37
82
  */
38
- constructor(camera, domElement, configOverrides) {
83
+ constructor(camera, domElement) {
39
84
  this.camera = camera;
40
85
  this.domElement = domElement;
41
86
 
42
- this.config = createOrbitalCameraConfig(configOverrides);
87
+ this.pose.distance = 1;
88
+ this.#apply_distance_limits();
89
+
90
+ this.rig = new OrbitalCameraRig(this.pose, {
91
+ orbit_buttons: MouseEventButtons.primary,
92
+ pan_buttons: MouseEventButtons.secondary,
93
+ pitch_min: -Math.PI / 2,
94
+ pitch_max: Math.PI / 2,
95
+ pan_axes: Vector3.one
96
+ });
43
97
 
44
- // ── devices (the facade owns their lifecycle) ───────────────────────
45
98
  this.pointer = new PointerDevice(domElement);
46
- this.pointer.domElement = domElement;
99
+ this.pointer.on.dragStart.add(this.#handle_drag_start, this);
100
+ this.pointer.on.drag.add(this.#handle_drag, this);
101
+ this.pointer.on.dragEnd.add(this.#handle_drag_end, this);
102
+ this.pointer.on.wheel.add(this.#handle_wheel, this);
47
103
  this.pointer.start();
48
104
 
49
105
  this.keyboard = new KeyboardDevice(domElement);
50
- this.keyboard.domElement = domElement;
51
106
  this.keyboard.start();
52
107
 
53
- // ── layers ──────────────────────────────────────────────────────────
54
- this.rig = new OrbitalCameraRig({ config: this.config });
55
-
56
- this.input = new OrbitalCameraInput({
57
- rig: this.rig,
58
- pointer: this.pointer,
59
- keyboard: this.keyboard,
60
- viewport: domElement,
61
- lens: camera,
62
- config: this.config,
63
- });
64
- this.input.connect();
65
-
66
- // ── frame bookkeeping ───────────────────────────────────────────────
67
- this._lastRecorded = new Transform64();
68
- // seed so the first no-arg update() sees ~0 dt instead of the page lifetime
69
- this._lastUpdateTime = current_time_in_seconds();
70
- this._scratchEye = new Vector3();
71
- this._scratchTarget = new Vector3();
72
-
73
- // adopt the camera's current pose
74
108
  this.from_transform(camera.transform);
75
109
  }
76
110
 
77
- // ─────────────────────────────────────────────────────────────────────────
78
- // Public API (legacy-compatible)
79
- // ─────────────────────────────────────────────────────────────────────────
80
-
81
- /** Zoom range, in world units (NumericInterval). Mutate `.min/.max` or `.set()`. */
82
- get distanceLimits() {
83
- return this.rig.distanceLimits;
84
- }
85
-
86
- /** Scene-relative WASD/keyboard move speed. */
87
- get movement_speed_scale() {
88
- return this.rig.movementSpeedScale;
89
- }
90
-
91
- set movement_speed_scale(value) {
92
- this.rig.movementSpeedScale = value;
93
- }
94
-
95
- /** Current smoothed orbit distance (radius). */
111
+ /** Orbit distance, world units. */
96
112
  get distance() {
97
- return this.rig.distance;
113
+ return this.pose.distance;
98
114
  }
99
115
 
100
- /** Current smoothed target (shared scratch — copy if you need to retain it). */
116
+ /** Orbit target, live: copy it to keep it. */
101
117
  get target() {
102
- return this.rig.getTarget();
118
+ return this.pose.target;
103
119
  }
104
120
 
105
121
  /**
106
- * Point the camera at `to` from `from`, immediately (no animation).
122
+ * Point the camera at `to` from `from`, at once, stopping any throw.
107
123
  * @param {Vector3} from
108
124
  * @param {Vector3} to
109
125
  */
@@ -111,127 +127,161 @@ export class OrbitalCameraController {
111
127
  assert.defined(from, "from");
112
128
  assert.defined(to, "to");
113
129
 
114
- this.rig.frameTo(from, to, { animate: false });
115
- // apply immediately so a subsequent at-rest update() doesn't skip the write
116
- this.rig.composeTransform(this.camera.transform);
117
- this._lastRecorded.copy(this.camera.transform);
118
- }
130
+ const pose = this.pose;
119
131
 
120
- /**
121
- * Eased "fly to" framing: glide to the new pose over {@link config}.flyToHalfLife
122
- * instead of snapping. The normal update() loop animates it.
123
- * @param {Vector3} from
124
- * @param {Vector3} to
125
- */
126
- flyTo(from, to) {
127
- assert.defined(from, "from");
128
- assert.defined(to, "to");
132
+ this.rig.stop();
133
+
134
+ pose.setFromEyeAndTarget(from, to);
135
+
136
+ // the eye is kept within the zoom range rather than widening the range to fit it
137
+ this.#apply_distance_limits();
138
+ pose.distance = clamp(pose.distance, pose.distanceMin, pose.distanceMax);
129
139
 
130
- this.rig.frameTo(from, to, { animate: true });
131
- // camera transform is unchanged this frame; keep the snapshot in sync so
132
- // the animation isn't mistaken for an external mutation next update().
133
- this._lastRecorded.copy(this.camera.transform);
140
+ this.#write();
134
141
  }
135
142
 
136
143
  /**
137
- * Adopt an external camera transform as the new orbit pose (target is placed
138
- * `distance` ahead along its forward).
144
+ * Adopt a camera transform as the pose, the target the current orbit distance ahead of it.
139
145
  *
140
- * Read component-wise rather than through `Vector3.copy`, because a
141
- * {@link Transform64} answers `forward` and `translation` with raw
142
- * `Float64Array`s — no `.x`, and a `copy` of one silently sets three
143
- * undefineds. Those two arrays are also freshly allocated per access, so
144
- * each is read once into a scratch that outlives the call.
146
+ * Read by component, because a {@link Transform64} answers `forward` with a raw `Float64Array`,
147
+ * allocated on each access.
145
148
  *
146
149
  * @param {Transform64} transform
147
150
  */
148
151
  from_transform(transform) {
149
152
  const forward = transform.forward;
150
153
 
151
- const distance = this.rig.distance;
154
+ const distance = this.pose.distance;
152
155
 
153
- this._scratchEye.set(
156
+ this.#scratch_eye.set(
154
157
  transform.translation_x,
155
158
  transform.translation_y,
156
159
  transform.translation_z
157
160
  );
158
161
 
159
- this._scratchTarget.set(
160
- this._scratchEye.x + forward[0] * distance,
161
- this._scratchEye.y + forward[1] * distance,
162
- this._scratchEye.z + forward[2] * distance
162
+ this.#scratch_target.set(
163
+ this.#scratch_eye.x + forward[0] * distance,
164
+ this.#scratch_eye.y + forward[1] * distance,
165
+ this.#scratch_eye.z + forward[2] * distance
163
166
  );
164
167
 
165
- this.look(this._scratchEye, this._scratchTarget);
168
+ this.look(this.#scratch_eye, this.#scratch_target);
166
169
  }
167
170
 
168
171
  /**
169
- * Screen-space pan of the orbit target, in pointer pixels (legacy signature).
170
- * @param {number} delta_x
171
- * @param {number} delta_y
172
- */
173
- pan(delta_x, delta_y) {
174
- this.rig.panScreen(delta_x, delta_y, this.domElement.clientHeight, this.camera.fov);
175
- }
176
-
177
- /**
178
- * Advance one frame and write the result onto the camera transform.
172
+ * Advance one frame and write the pose onto the camera transform.
179
173
  *
180
- * @param {number} [dt] frame time in seconds. STRONGLY preferred — pass the
181
- * value `create_frame_loop` already hands the callback. Omit to fall back
182
- * to an internal clock (clamped, so no first-frame teleport).
174
+ * @param {number} [dt] frame time in seconds; `create_frame_loop` hands it to its callback. Omit
175
+ * it to measure the time since the last call instead.
183
176
  */
184
177
  update(dt) {
185
- const frameDt = this._resolveDt(dt);
178
+ const frame_dt = this.#resolve_dt(dt);
186
179
 
187
- // continuous (held-key) input → rig intents
188
- this.input.update(frameDt);
180
+ this.#apply_distance_limits();
189
181
 
190
- const camTransform = this.camera.transform;
182
+ if (!t64_equals_components(this.#last_recorded, this.camera.transform)) {
183
+ // moved outside our control: that is the pose now
184
+ this.from_transform(this.camera.transform);
191
185
 
192
- if (!t64_equals_components(this._lastRecorded, camTransform)) {
193
- // camera was moved outside our control — adopt it, skip integration
194
- this.from_transform(camTransform);
195
- } else {
196
- const moved = this.rig.update(frameDt);
197
- if (moved) {
198
- this.rig.composeTransform(camTransform);
199
- }
186
+ return;
200
187
  }
201
188
 
202
- this._lastRecorded.copy(camTransform);
189
+ this.#truck(frame_dt);
190
+
191
+ this.rig.update(frame_dt);
192
+
193
+ if (!this.pose.equals(this.#last_pose)) {
194
+ this.#write();
195
+ }
203
196
  }
204
197
 
205
- /** Detach input subscriptions and stop the devices. */
198
+ /** Detach input and stop the devices. */
206
199
  dispose() {
207
- this.input.disconnect();
208
- this.pointer.stop?.();
209
- this.keyboard.stop?.();
200
+ this.pointer.on.dragStart.remove(this.#handle_drag_start, this);
201
+ this.pointer.on.drag.remove(this.#handle_drag, this);
202
+ this.pointer.on.dragEnd.remove(this.#handle_drag_end, this);
203
+ this.pointer.on.wheel.remove(this.#handle_wheel, this);
204
+ this.pointer.stop();
205
+
206
+ this.keyboard.stop();
207
+ }
208
+
209
+ #write() {
210
+ computeTopDownTransform(this.pose, this.camera.transform);
211
+
212
+ this.#last_pose.copy(this.pose);
213
+ this.#last_recorded.copy(this.camera.transform);
214
+ }
215
+
216
+ #apply_distance_limits() {
217
+ this.pose.distanceMin = this.distanceLimits.min;
218
+ this.pose.distanceMax = this.distanceLimits.max;
219
+ }
220
+
221
+ /**
222
+ * @param {number} dt seconds
223
+ */
224
+ #truck(dt) {
225
+ const keys = this.keyboard.keys;
226
+
227
+ const right = (keys.d?.is_down ? 1 : 0) - (keys.a?.is_down ? 1 : 0);
228
+ const forward = (keys.w?.is_down ? 1 : 0) - (keys.s?.is_down ? 1 : 0);
229
+
230
+ if (right === 0 && forward === 0) {
231
+ return;
232
+ }
233
+
234
+ const zoom_scale = lerp(1, 2, clamp01(this.distanceLimits.normalizeValue(this.pose.distance)));
235
+
236
+ top_down_truck_in_view(this.pose, right, forward, this.movement_speed_scale * zoom_scale * dt);
237
+ }
238
+
239
+ /**
240
+ * @param {Vector2} origin
241
+ * @param {PointerEvent} event
242
+ */
243
+ #handle_drag_start(origin, event) {
244
+ this.rig.begin(event.buttons);
245
+ }
246
+
247
+ /**
248
+ * @param {Vector2} position
249
+ * @param {Vector2} origin
250
+ * @param {Vector2} last_position
251
+ */
252
+ #handle_drag(position, origin, last_position) {
253
+ this.rig.move(
254
+ position.x - last_position.x,
255
+ position.y - last_position.y,
256
+ this.domElement.clientHeight,
257
+ this.camera.fov * RAD_TO_DEG
258
+ );
210
259
  }
211
260
 
212
- // ─────────────────────────────────────────────────────────────────────────
213
- // Internals
214
- // ─────────────────────────────────────────────────────────────────────────
261
+ #handle_drag_end() {
262
+ this.rig.end();
263
+ }
264
+
265
+ /**
266
+ * @param {Vector3} delta signs of the wheel's motion
267
+ */
268
+ #handle_wheel(delta) {
269
+ this.#apply_distance_limits();
270
+
271
+ this.rig.dolly(delta.y);
272
+ }
215
273
 
216
274
  /**
217
- * Resolve and sanitize the frame dt. Prefers the supplied value; otherwise
218
- * derives it from an internal clock. Always clamped to [0, maxDt] so a tab
219
- * refocus / GC hitch can't make the springs jump.
220
275
  * @param {number} [dt]
221
- * @returns {number}
276
+ * @returns {number} seconds, within [0, {@link MAX_DT}]
222
277
  */
223
- _resolveDt(dt) {
278
+ #resolve_dt(dt) {
224
279
  const now = current_time_in_seconds();
225
280
 
226
- let d;
227
- if (typeof dt === "number" && Number.isFinite(dt)) {
228
- d = dt;
229
- } else {
230
- d = now - this._lastUpdateTime;
231
- }
281
+ const elapsed = (typeof dt === "number" && Number.isFinite(dt)) ? dt : now - this.#last_update_time;
232
282
 
233
- this._lastUpdateTime = now;
283
+ this.#last_update_time = now;
234
284
 
235
- return clamp(d, 0, this.config.maxDt);
285
+ return clamp(elapsed, 0, MAX_DT);
236
286
  }
237
287
  }
@@ -143,7 +143,7 @@ export class GPUFluidCascade {
143
143
  * @param {*} _resources
144
144
  * @param {{encoder: ShadeGPUCommandContext}} context
145
145
  */
146
- static "__#277@#execute_restrict"(record: object, _resources: any, context: {
146
+ static "__#279@#execute_restrict"(record: object, _resources: any, context: {
147
147
  encoder: ShadeGPUCommandContext;
148
148
  }): void;
149
149
  /**
@@ -151,7 +151,7 @@ export class GPUFluidCascade {
151
151
  * @param {*} _resources
152
152
  * @param {{encoder: ShadeGPUCommandContext}} context
153
153
  */
154
- static "__#277@#execute_fill"(record: object, _resources: any, context: {
154
+ static "__#279@#execute_fill"(record: object, _resources: any, context: {
155
155
  encoder: ShadeGPUCommandContext;
156
156
  }): void;
157
157
  /**
@@ -159,7 +159,7 @@ export class GPUFluidCascade {
159
159
  * @param {import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
160
160
  * @param {{encoder: ShadeGPUCommandContext}} context
161
161
  */
162
- static "__#277@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
162
+ static "__#279@#execute"(record: object, resources: import("../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
163
163
  encoder: ShadeGPUCommandContext;
164
164
  }): void;
165
165
  /**
@@ -63,7 +63,7 @@ export class GPUFluidCascadeStack {
63
63
  * @param {*} _resources
64
64
  * @param {{encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
65
65
  */
66
- static "__#279@#execute_publish"(pass: object, _resources: any, context: {
66
+ static "__#281@#execute_publish"(pass: object, _resources: any, context: {
67
67
  encoder: import("../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
68
68
  }): void;
69
69
  /**
@@ -90,19 +90,19 @@ export class GPUFluidForcing {
90
90
  * @param {number} clear_size bytes cleared from 0 when the pool reuses the buffer
91
91
  * @returns {BufferResourceDescriptor}
92
92
  */
93
- static "__#280@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
93
+ static "__#282@#descriptor"(kept: BufferResourceDescriptor[], role: number, size: number, usage: number, clear_size: number): BufferResourceDescriptor;
94
94
  /**
95
95
  * @param {object} record
96
96
  * @param {FramePassResources} resources
97
97
  * @param {{encoder: ShadeGPUCommandContext}} context
98
98
  */
99
- static "__#280@#execute_extract"(record: object, resources: FramePassResources, context: {
99
+ static "__#282@#execute_extract"(record: object, resources: FramePassResources, context: {
100
100
  encoder: ShadeGPUCommandContext;
101
101
  }): void;
102
- static "__#280@#execute_clear"(record: any, _resources: any, context: any): void;
103
- static "__#280@#execute_query"(record: any, resources: any, context: any): void;
104
- static "__#280@#execute_command"(record: any, resources: any, context: any): void;
105
- static "__#280@#execute_apply"(record: any, resources: any, context: any): void;
102
+ static "__#282@#execute_clear"(record: any, _resources: any, context: any): void;
103
+ static "__#282@#execute_query"(record: any, resources: any, context: any): void;
104
+ static "__#282@#execute_command"(record: any, resources: any, context: any): void;
105
+ static "__#282@#execute_apply"(record: any, resources: any, context: any): void;
106
106
  /**
107
107
  * @param {object} options
108
108
  * @param {GPUDevice} options.device
@@ -41,7 +41,7 @@ export class GPUFluidPressureSolve {
41
41
  * @param {*} _resources
42
42
  * @param {{encoder: ShadeGPUCommandContext}} context
43
43
  */
44
- static "__#276@#execute"(data: {
44
+ static "__#278@#execute"(data: {
45
45
  solve: GPUFluidPressureSolve;
46
46
  arm: number;
47
47
  count: number;
@@ -49,7 +49,7 @@ export class GPUFluidQueries {
49
49
  * @param {import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources} resources
50
50
  * @param {{encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext}} context
51
51
  */
52
- static "__#281@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
52
+ static "__#283@#execute"(pass: object, resources: import("../../../../engine/graphics/render/frame_graph/FramePassResources.js").FramePassResources, context: {
53
53
  encoder: import("../../../device/ShadeGPUCommandContext.js").ShadeGPUCommandContext;
54
54
  }): void;
55
55
  /**
@@ -245,8 +245,8 @@ export class GPUGeometrySDFManager {
245
245
  * @param {number} options.budget bricks evaluated at most, `mesh_sdf_bake_budget`
246
246
  * @param {number} [options.capture_budget] card pages captured at most, `card_capture_budget`; 0
247
247
  * captures nothing
248
- * @param {GPUResidentMaterialContext|null} [options.materials] what the capture shades with, as it
249
- * stands this frame; needed with a `capture_budget`
248
+ * @param {GPUResidentMaterialContext|null} [options.materials] what a traced capture shades with,
249
+ * which makes what it traces resident; needed with a `capture_budget`
250
250
  * @param {GPUMaterialManager|null} [options.material_contexts] what a raster capture draws with
251
251
  * ({@link GPUMeshCardSets#capture_mode}); needed with a `capture_budget` in that mode
252
252
  */
@@ -980,8 +980,8 @@ export class GPUGeometrySDFManager {
980
980
  * @param {number} options.budget bricks evaluated at most, `mesh_sdf_bake_budget`
981
981
  * @param {number} [options.capture_budget] card pages captured at most, `card_capture_budget`; 0
982
982
  * captures nothing
983
- * @param {GPUResidentMaterialContext|null} [options.materials] what the capture shades with, as it
984
- * stands this frame; needed with a `capture_budget`
983
+ * @param {GPUResidentMaterialContext|null} [options.materials] what a traced capture shades with,
984
+ * which makes what it traces resident; needed with a `capture_budget`
985
985
  * @param {GPUMaterialManager|null} [options.material_contexts] what a raster capture draws with
986
986
  * ({@link GPUMeshCardSets#capture_mode}); needed with a `capture_budget` in that mode
987
987
  */
@@ -162,7 +162,8 @@ export class GPUMeshCardSets {
162
162
  * @param {number} options.budget pages captured at most, `card_capture_budget`
163
163
  * @param {number} options.arena graph handle of the arena, as the frame's bake left it
164
164
  * @param {GPUBuffer} options.headers
165
- * @param {GPUResidentMaterialContext} options.materials what the trace shades with
165
+ * @param {GPUResidentMaterialContext} options.materials what the trace shades with: each traced
166
+ * material is made resident, and the rows committed, before the trace is recorded
166
167
  * @param {GPUMaterialManager} options.material_contexts what the raster draws with: each
167
168
  * material's template and bind group
168
169
  * @param {Object} options.blas the geometry bindings `ray_query_blas_nearest` reads, whose
@@ -1 +1 @@
1
- {"version":3,"file":"GPUMeshCardSets.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js"],"names":[],"mappings":"AAyEA;;;;;;GAMG;AACH,sDAHW,aAAa,GACX,MAAM,CAUlB;AApCD;;;GAGG;AACH,2CAFU,MAAM,CAEmF;AA0DnG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IAmLI;;OAEG;IACH,+BAIC;IAnLD;;;OAGG;IACH,gBAA0B;IAE1B;;;OAGG;IACH,iBAA2B;IA2K3B;;;OAGG;IACH,oBAUC;IAED;;OAEG;IACH,6BAEC;IAED;;;OAGG;IACH,mCAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;;OAIG;IACH,mCAIC;IAED;;;OAGG;IACH,2BAcC;IASD;;;;;OAKG;IACH,+BAgBC;IA7BD;;OAEG;IACH,2BAEC;IA0BD;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,yBAIC;IAED;;;OAGG;IACH,4BAIC;IAED;;;;;;OAMG;IACH,kBAJW,MAAM,YACN,aAAa,GACX,MAAM,CA+BlB;IAED;;OAEG;IACH,YAFW,MAAM,QA2BhB;IAED;;;;;OAKG;IACH,cAFW,MAAM,QAqBhB;IAED;;;;;;;OAOG;IACH,qBALW,MAAM,SACN,MAAM,QACN,MAAM,QAqBhB;IAED;;;;OAIG;IACH,sBAFW,MAAM,QA+BhB;IAuSD;;;;;;;;;;;;;;;OAeG;IACH;QAV+B,KAAK,EAAzB,UAAU;QACM,MAAM,EAAtB,MAAM;QACU,KAAK,EAArB,MAAM;QACa,OAAO;QACU,SAAS,EAA7C,0BAA0B;QACE,iBAAiB,EAA7C,kBAAkB;QAEF,IAAI;aAiG9B;IAiTD;;OAEG;IACH,+BAuBC;IAED,gBAoBC;;CACJ;yBA70CY,OAAO,iEAAiE,EAAE,UAAU;4BACpF,OAAO,oCAAoC,EAAE,aAAa;yCAC1D,OAAO,0DAA0D,EAAE,0BAA0B;iCAC7F,OAAO,yCAAyC,EAAE,kBAAkB;iCACpE,OAAO,yCAAyC,EAAE,kBAAkB;yBACpE,OAAO,yDAAyD,EAAE,UAAU;+BAxB1D,0CAA0C"}
1
+ {"version":3,"file":"GPUMeshCardSets.d.ts","sourceRoot":"","sources":["../../../../../../../src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js"],"names":[],"mappings":"AAyEA;;;;;;GAMG;AACH,sDAHW,aAAa,GACX,MAAM,CAUlB;AApCD;;;GAGG;AACH,2CAFU,MAAM,CAEmF;AA0DnG;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH;IA2LI;;OAEG;IACH,+BAIC;IA3LD;;;OAGG;IACH,gBAA0B;IAE1B;;;OAGG;IACH,iBAA2B;IAmL3B;;;OAGG;IACH,oBAUC;IAED;;OAEG;IACH,6BAEC;IAED;;;OAGG;IACH,mCAEC;IAED;;;OAGG;IACH,6BAEC;IAED;;;;OAIG;IACH,mCAIC;IAED;;;OAGG;IACH,2BAcC;IASD;;;;;OAKG;IACH,+BAgBC;IA7BD;;OAEG;IACH,2BAEC;IA0BD;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,OAAO,CAInB;IAED;;;;;OAKG;IACH,gBAHW,MAAM,GACJ,MAAM,CAIlB;IAED;;;OAGG;IACH,yBAIC;IAED;;;OAGG;IACH,4BAIC;IAED;;;;;;OAMG;IACH,kBAJW,MAAM,YACN,aAAa,GACX,MAAM,CA+BlB;IAED;;OAEG;IACH,YAFW,MAAM,QA2BhB;IAED;;;;;OAKG;IACH,cAFW,MAAM,QAqBhB;IAED;;;;;;;OAOG;IACH,qBALW,MAAM,SACN,MAAM,QACN,MAAM,QAqBhB;IAED;;;;OAIG;IACH,sBAFW,MAAM,QA+BhB;IA0SD;;;;;;;;;;;;;;;;OAgBG;IACH;QAX+B,KAAK,EAAzB,UAAU;QACM,MAAM,EAAtB,MAAM;QACU,KAAK,EAArB,MAAM;QACa,OAAO;QACU,SAAS,EAA7C,0BAA0B;QAEE,iBAAiB,EAA7C,kBAAkB;QAEF,IAAI;aAsG9B;IAiTD;;OAEG;IACH,+BAuBC;IAED,gBAoBC;;CACJ;yBA91CY,OAAO,iEAAiE,EAAE,UAAU;4BACpF,OAAO,oCAAoC,EAAE,aAAa;yCAC1D,OAAO,0DAA0D,EAAE,0BAA0B;iCAC7F,OAAO,yCAAyC,EAAE,kBAAkB;iCACpE,OAAO,yCAAyC,EAAE,kBAAkB;yBACpE,OAAO,yDAAyD,EAAE,UAAU;+BAxB1D,0CAA0C"}
@@ -265,6 +265,14 @@ export class GPUMeshCardSets {
265
265
  */
266
266
  #frame_material_contexts = null;
267
267
 
268
+ /**
269
+ * What a frame's capture traces with: set by {@link graph_capture}. Only what is traced is made
270
+ * resident, each run's material as its run is taken, so a frame that traces nothing leaves the
271
+ * resident materials as they were.
272
+ * @type {GPUResidentMaterialContext|null}
273
+ */
274
+ #frame_materials = null;
275
+
268
276
  // the frame's shelves in the scratch
269
277
  #shelf_x = 0;
270
278
  #shelf_y = 0;
@@ -787,6 +795,9 @@ export class GPUMeshCardSets {
787
795
  // a template that cannot be drawn this way is traced
788
796
  }
789
797
 
798
+ // its row as the material stands now, repacked if it has moved since
799
+ this.#frame_materials.obtain_material(this.#material[id]);
800
+
790
801
  const first = this.#next_page[id];
791
802
  const count = Math.min(pages - first, this.#frame_left);
792
803
 
@@ -930,7 +941,8 @@ export class GPUMeshCardSets {
930
941
  * @param {number} options.budget pages captured at most, `card_capture_budget`
931
942
  * @param {number} options.arena graph handle of the arena, as the frame's bake left it
932
943
  * @param {GPUBuffer} options.headers
933
- * @param {GPUResidentMaterialContext} options.materials what the trace shades with
944
+ * @param {GPUResidentMaterialContext} options.materials what the trace shades with: each traced
945
+ * material is made resident, and the rows committed, before the trace is recorded
934
946
  * @param {GPUMaterialManager} options.material_contexts what the raster draws with: each
935
947
  * material's template and bind group
936
948
  * @param {Object} options.blas the geometry bindings `ray_query_blas_nearest` reads, whose
@@ -947,10 +959,12 @@ export class GPUMeshCardSets {
947
959
  }
948
960
 
949
961
  this.#frame_material_contexts = material_contexts;
962
+ this.#frame_materials = materials;
950
963
 
951
964
  this.#take(budget);
952
965
 
953
966
  this.#frame_material_contexts = null;
967
+ this.#frame_materials = null;
954
968
 
955
969
  const completed = this.#completed;
956
970
 
@@ -961,6 +975,9 @@ export class GPUMeshCardSets {
961
975
  let emissive = graph_import_texture(graph, this.#atlas.texture_at(1), "mesh_card_emissive");
962
976
 
963
977
  if (this.#frame_runs > 0) {
978
+ // what the runs' materials made resident, written before the trace reads it
979
+ materials.commit();
980
+
964
981
  this.#ensure_runs(this.#frame_runs);
965
982
 
966
983
  this.#device.queue.writeBuffer(this.#runs, 0, this.#run_scratch, 0, 4 * this.#frame_runs);