@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,82 @@
1
- import { clamp } from "../../../core/math/clamp.js";
1
+ import { assert } from "../../../core/assert.js";
2
+ import Vector3 from "../../../core/geom/Vector3.js";
3
+ import Script from "../../ecs/components/Script.js";
2
4
  import Entity from "../../ecs/Entity.js";
3
- import { decodeMouseEventButtons } from "../../input/devices/mouse/decodeMouseEventButtons.js";
5
+ import { MouseEventButtons } from "../../input/devices/mouse/MouseEventButtons.js";
4
6
  import InputController from "../../input/ecs/components/InputController.js";
5
7
  import { Camera } from "../ecs/camera/Camera.js";
6
- import TopDownCameraController, { rotate_from_view } from "../ecs/camera/topdown/TopDownCameraController.js";
8
+ import TopDownCameraController from "../ecs/camera/topdown/TopDownCameraController.js";
9
+ import { OrbitalCameraRig } from "./orbital/OrbitalCameraRig.js";
7
10
 
8
11
  /**
12
+ * Pointer navigation for a camera entity's {@link TopDownCameraController}: drag with the primary
13
+ * button (or a touch) to orbit, with the secondary to pan, the wheel to zoom. A drag moves the camera
14
+ * as it happens and throws on release; see {@link OrbitalCameraRig}.
15
+ *
16
+ * The orbit swings all the way round, under the target included, short of turning over at the poles.
9
17
  *
10
18
  * @param {Object} options
11
- * @param {number} options.camera_entity
19
+ * @param {number} options.camera_entity carries the {@link TopDownCameraController} and {@link Camera}
12
20
  * @param {EntityComponentDataset} options.ecd
13
- * @param {HTMLElement} options.dom_element
14
- * @param {number} [options.sensitivity]
15
- * @return {Entity}
21
+ * @param {HTMLElement} options.dom_element the viewport, measured for its height
22
+ * @return {Entity} transient, to be built into the dataset
16
23
  */
17
24
  export function makeOrbitalCameraController({
18
25
  camera_entity,
19
26
  ecd,
20
27
  dom_element,
21
- sensitivity = 1
22
28
  }) {
23
- /**
24
- *
25
- * @returns {TopDownCameraController}
26
- */
27
- function getCameraController() {
28
- return ecd.getComponent(camera_entity, TopDownCameraController)
29
- }
30
-
31
- function getCamera() {
32
- return ecd.getComponent(camera_entity, Camera)
33
- }
34
-
35
- /**
36
- *
37
- * @param {Vector2} delta
38
- */
39
- function orbit(delta) {
40
-
41
- const cameraController = getCameraController();
42
-
43
- const scale = sensitivity * 2 * Math.PI / dom_element.clientHeight;
44
-
45
- rotate_from_view(delta.x * scale, delta.y * scale, cameraController, cameraController);
46
- }
47
-
48
- /**
49
- *
50
- * @param {Vector2} delta
51
- */
52
- function pan(delta) {
53
-
54
- const cameraController = getCameraController();
55
- const camera = getCamera();
56
-
57
- TopDownCameraController.pan(delta, cameraController, dom_element.clientHeight, camera.fov.getValue());
29
+ const controller = ecd.getComponent(camera_entity, TopDownCameraController);
30
+ const camera = ecd.getComponent(camera_entity, Camera);
58
31
 
59
- }
32
+ assert.defined(controller, 'controller');
33
+ assert.defined(camera, 'camera');
60
34
 
61
- function zoom(delta) {
62
- const cameraController = getCameraController();
63
-
64
- const new_distance = cameraController.distance + delta;
65
- cameraController.distance = clamp(new_distance, cameraController.distanceMin, cameraController.distanceMax);
66
- }
35
+ const rig = new OrbitalCameraRig(controller, {
36
+ orbit_buttons: MouseEventButtons.primary,
37
+ pan_buttons: MouseEventButtons.secondary,
38
+ pitch_min: -Math.PI / 2,
39
+ pitch_max: Math.PI / 2,
40
+ pan_axes: Vector3.one
41
+ });
67
42
 
68
43
  const inputController = new InputController([
69
44
  {
70
- path: 'pointer/on/tap',
71
- listener(position, event) {
72
- // event.preventDefault();
73
- }
74
- },
75
- {
76
- path: 'pointer/on/down',
77
- listener(position, event) {
78
- // event.preventDefault();
45
+ path: 'pointer/on/dragStart',
46
+ listener(origin, event) {
47
+ rig.begin(event.buttons);
79
48
  }
80
49
  },
81
50
  {
82
51
  path: 'pointer/on/drag',
83
- listener: function (position, origin, lastDragPosition, event) {
84
- const delta = lastDragPosition.clone().sub(position);
85
-
86
- const buttons = decodeMouseEventButtons(event.buttons);
87
-
88
- if (buttons[0]) {
89
- pan(delta);
90
- } else {
91
- orbit(delta);
92
- }
52
+ listener(position, origin, lastDragPosition, event) {
53
+ rig.move(
54
+ position.x - lastDragPosition.x,
55
+ position.y - lastDragPosition.y,
56
+ dom_element.clientHeight,
57
+ camera.fov.getValue()
58
+ );
93
59
 
94
60
  event.preventDefault();
95
61
  }
96
62
  },
63
+ {
64
+ path: 'pointer/on/dragEnd',
65
+ listener() {
66
+ rig.end();
67
+ }
68
+ },
97
69
  {
98
70
  path: 'pointer/on/wheel',
99
- listener(delta, event) {
100
- zoom(delta.y);
71
+ listener(delta) {
72
+ rig.dolly(delta.y);
101
73
  }
102
74
  }
103
75
  ]);
104
76
 
105
77
  const eb = new Entity();
106
78
  eb.add(inputController);
79
+ eb.add(new Script(time_delta => rig.update(time_delta)));
107
80
 
108
81
  return eb;
109
82
  }
@@ -0,0 +1,64 @@
1
+ /**
2
+ * The velocity of one degree of freedom under **direct drive + release momentum** — the "throw" of
3
+ * Google Earth / Maps / Cesium, not a spring.
4
+ *
5
+ * The axis holds no position. While a gesture is engaged the caller applies each drag to whatever it
6
+ * is moving and {@link record}s it here, so the drag itself has no lag. On {@link release} the
7
+ * average velocity over the recent window becomes the throw; averaging the velocity rather than the
8
+ * position rejects one jittery last frame without adding lag to the live drag. From then on
9
+ * {@link update} hands back how far the coast moves each frame, decaying exponentially, and the caller
10
+ * adds that to the value — so anyone else writing the same value keeps their write, and the coast
11
+ * carries on from it.
12
+ *
13
+ * Holding still before letting go fills the window with frames that did not move, so a slow,
14
+ * deliberate drag stops where it was left while a flick throws — no click-versus-drag gate.
15
+ *
16
+ * @author Alex Goldring
17
+ * @copyright Company Named Limited (c) 2026
18
+ */
19
+ export class MomentumAxis {
20
+ /**
21
+ * units per second; non-zero while coasting
22
+ * @type {number}
23
+ */
24
+ velocity: number;
25
+ /**
26
+ * true while a gesture is driving this axis
27
+ * @type {boolean}
28
+ */
29
+ engaged: boolean;
30
+ /**
31
+ * Begin direct control: stop any coast and forget earlier motion.
32
+ */
33
+ engage(): void;
34
+ /**
35
+ * Note motion the caller has just applied directly, for the release estimate.
36
+ * @param {number} delta
37
+ */
38
+ record(delta: number): void;
39
+ /**
40
+ * End the gesture, throwing with the average velocity over the most recent `window_seconds` of it.
41
+ * @param {number} window_seconds
42
+ */
43
+ release(window_seconds: number): void;
44
+ /**
45
+ * No motion, no gesture, no history.
46
+ */
47
+ stop(): void;
48
+ /**
49
+ * Advance one frame.
50
+ *
51
+ * Engaged, this samples the frame's recorded motion and moves nothing, since the drag was applied
52
+ * when it happened. Coasting, it integrates the decaying velocity analytically — over `dt` the
53
+ * coast covers `v·τ·(1 − e^(−dt/τ))` and the velocity falls by `e^(−dt/τ)` — so the distance
54
+ * thrown is the same at any frame rate.
55
+ *
56
+ * @param {number} dt seconds
57
+ * @param {number} half_life seconds for the coast velocity to halve
58
+ * @param {number} stop_speed at or below this speed the coast ends
59
+ * @returns {number} how far the value moves this frame
60
+ */
61
+ update(dt: number, half_life: number, stop_speed: number): number;
62
+ #private;
63
+ }
64
+ //# sourceMappingURL=MomentumAxis.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"MomentumAxis.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/camera/orbital/MomentumAxis.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;GAiBG;AACH;IACI;;;OAGG;IACH,UAFU,MAAM,CAEH;IAEb;;;OAGG;IACH,SAFU,OAAO,CAED;IA+BhB;;OAEG;IACH,eAGC;IAED;;;OAGG;IACH,cAFW,MAAM,QAIhB;IAED;;;OAGG;IACH,wBAFW,MAAM,QAehB;IAED;;OAEG;IACH,aAMC;IAED;;;;;;;;;;;;OAYG;IACH,WALW,MAAM,aACN,MAAM,cACN,MAAM,GACJ,MAAM,CAoClB;;CAuBJ"}
@@ -0,0 +1,187 @@
1
+ const LN2 = 0.6931471805599453;
2
+
3
+ /**
4
+ * Frames of drag history kept for the release estimate. The estimate reads back over a window of
5
+ * about a tenth of a second, so this covers it at up to 900 frames a second; beyond that the oldest
6
+ * part of the window is simply not seen.
7
+ * @type {number}
8
+ */
9
+ const HISTORY_CAPACITY = 90;
10
+
11
+ /**
12
+ * The velocity of one degree of freedom under **direct drive + release momentum** — the "throw" of
13
+ * Google Earth / Maps / Cesium, not a spring.
14
+ *
15
+ * The axis holds no position. While a gesture is engaged the caller applies each drag to whatever it
16
+ * is moving and {@link record}s it here, so the drag itself has no lag. On {@link release} the
17
+ * average velocity over the recent window becomes the throw; averaging the velocity rather than the
18
+ * position rejects one jittery last frame without adding lag to the live drag. From then on
19
+ * {@link update} hands back how far the coast moves each frame, decaying exponentially, and the caller
20
+ * adds that to the value — so anyone else writing the same value keeps their write, and the coast
21
+ * carries on from it.
22
+ *
23
+ * Holding still before letting go fills the window with frames that did not move, so a slow,
24
+ * deliberate drag stops where it was left while a flick throws — no click-versus-drag gate.
25
+ *
26
+ * @author Alex Goldring
27
+ * @copyright Company Named Limited (c) 2026
28
+ */
29
+ export class MomentumAxis {
30
+ /**
31
+ * units per second; non-zero while coasting
32
+ * @type {number}
33
+ */
34
+ velocity = 0;
35
+
36
+ /**
37
+ * true while a gesture is driving this axis
38
+ * @type {boolean}
39
+ */
40
+ engaged = false;
41
+
42
+ /**
43
+ * motion recorded since the last frame sample
44
+ * @type {number}
45
+ */
46
+ #pending = 0;
47
+
48
+ /**
49
+ * per-frame motion, a ring of {@link HISTORY_CAPACITY}
50
+ * @type {Float64Array}
51
+ */
52
+ #history_motion = new Float64Array(HISTORY_CAPACITY);
53
+
54
+ /**
55
+ * duration of each frame in {@link #history_motion}, seconds
56
+ * @type {Float64Array}
57
+ */
58
+ #history_duration = new Float64Array(HISTORY_CAPACITY);
59
+
60
+ /**
61
+ * slot the next frame is written to
62
+ * @type {number}
63
+ */
64
+ #history_head = 0;
65
+
66
+ /**
67
+ * @type {number}
68
+ */
69
+ #history_count = 0;
70
+
71
+ /**
72
+ * Begin direct control: stop any coast and forget earlier motion.
73
+ */
74
+ engage() {
75
+ this.stop();
76
+ this.engaged = true;
77
+ }
78
+
79
+ /**
80
+ * Note motion the caller has just applied directly, for the release estimate.
81
+ * @param {number} delta
82
+ */
83
+ record(delta) {
84
+ this.#pending += delta;
85
+ }
86
+
87
+ /**
88
+ * End the gesture, throwing with the average velocity over the most recent `window_seconds` of it.
89
+ * @param {number} window_seconds
90
+ */
91
+ release(window_seconds) {
92
+ if (this.#pending !== 0 && this.#history_count > 0) {
93
+ // motion that arrived after the last frame sample belongs to the frame that just ended
94
+ const last = (this.#history_head + HISTORY_CAPACITY - 1) % HISTORY_CAPACITY;
95
+
96
+ this.#history_motion[last] += this.#pending;
97
+ }
98
+
99
+ const velocity = this.#windowed_velocity(window_seconds);
100
+
101
+ this.stop();
102
+
103
+ this.velocity = velocity;
104
+ }
105
+
106
+ /**
107
+ * No motion, no gesture, no history.
108
+ */
109
+ stop() {
110
+ this.velocity = 0;
111
+ this.engaged = false;
112
+ this.#pending = 0;
113
+ this.#history_head = 0;
114
+ this.#history_count = 0;
115
+ }
116
+
117
+ /**
118
+ * Advance one frame.
119
+ *
120
+ * Engaged, this samples the frame's recorded motion and moves nothing, since the drag was applied
121
+ * when it happened. Coasting, it integrates the decaying velocity analytically — over `dt` the
122
+ * coast covers `v·τ·(1 − e^(−dt/τ))` and the velocity falls by `e^(−dt/τ)` — so the distance
123
+ * thrown is the same at any frame rate.
124
+ *
125
+ * @param {number} dt seconds
126
+ * @param {number} half_life seconds for the coast velocity to halve
127
+ * @param {number} stop_speed at or below this speed the coast ends
128
+ * @returns {number} how far the value moves this frame
129
+ */
130
+ update(dt, half_life, stop_speed) {
131
+ if (this.engaged) {
132
+ const head = this.#history_head;
133
+
134
+ this.#history_motion[head] = this.#pending;
135
+ this.#history_duration[head] = dt;
136
+
137
+ this.#history_head = (head + 1) % HISTORY_CAPACITY;
138
+
139
+ if (this.#history_count < HISTORY_CAPACITY) {
140
+ this.#history_count++;
141
+ }
142
+
143
+ this.#pending = 0;
144
+
145
+ return 0;
146
+ }
147
+
148
+ const velocity = this.velocity;
149
+
150
+ if (velocity === 0) {
151
+ return 0;
152
+ }
153
+
154
+ const tau = half_life / LN2;
155
+ const decay = Math.exp(-dt / tau);
156
+
157
+ this.velocity = velocity * decay;
158
+
159
+ if (Math.abs(this.velocity) <= stop_speed) {
160
+ this.velocity = 0;
161
+ }
162
+
163
+ return velocity * tau * (1 - decay);
164
+ }
165
+
166
+ /**
167
+ * @param {number} window_seconds
168
+ * @returns {number}
169
+ */
170
+ #windowed_velocity(window_seconds) {
171
+ let motion = 0;
172
+ let duration = 0;
173
+
174
+ for (let i = 1; i <= this.#history_count; i++) {
175
+ const slot = (this.#history_head + HISTORY_CAPACITY - i) % HISTORY_CAPACITY;
176
+
177
+ motion += this.#history_motion[slot];
178
+ duration += this.#history_duration[slot];
179
+
180
+ if (duration >= window_seconds) {
181
+ break;
182
+ }
183
+ }
184
+
185
+ return duration > 0 ? motion / duration : 0;
186
+ }
187
+ }
@@ -0,0 +1,86 @@
1
+ /**
2
+ * Orbit, pan and zoom of a {@link TopDownCameraController}, with the feel of **direct drive + release
3
+ * momentum**: the "throw" of Google Earth / Cesium, not a spring chasing a goal.
4
+ *
5
+ * - **A drag moves the controller as it happens**, one to one, so the view keeps up with the hand.
6
+ * - **Letting go throws**: the average velocity over the last {@link VELOCITY_WINDOW} carries on and
7
+ * decays with a half life of {@link MOMENTUM_HALF_LIFE}, at the same distance whatever the frame
8
+ * rate. Holding still before letting go throws nothing. Grabbing again stops every throw.
9
+ * - **Zoom is instant and multiplicative**: a wheel notch is a discrete step with nothing to catch up.
10
+ *
11
+ * The rig keeps velocities, not a pose. Each frame the coast is added to the controller as it finds
12
+ * it, so a writer that adds to the controller composes with a throw, and one that sets its values
13
+ * outright wins. A teleport should {@link stop} the rig, or the remains of a throw carry on from the
14
+ * new pose.
15
+ *
16
+ * The rig subscribes to nothing. Its host hands it the gesture — {@link begin}, {@link move},
17
+ * {@link end}, {@link dolly} — from whatever input it listens to, and calls {@link update} once a frame.
18
+ * A drag the device abandons without an end leaves the rig engaged and still, which the next
19
+ * {@link begin} clears.
20
+ *
21
+ * @author Alex Goldring
22
+ * @copyright Company Named Limited (c) 2026
23
+ */
24
+ export class OrbitalCameraRig {
25
+ /**
26
+ * @param {TopDownCameraController} controller moved by the rig; a host that filters the camera
27
+ * hands over the controller its input is meant to drive
28
+ * @param {Object} options
29
+ * @param {number} options.orbit_buttons {@link MouseEvent.buttons} bits that start an orbit, see
30
+ * {@link MouseEventButtons}
31
+ * @param {number} options.pan_buttons {@link MouseEvent.buttons} bits that start a pan; orbit wins
32
+ * when both are held
33
+ * @param {number} options.pitch_min radians; 0 looks along the horizon
34
+ * @param {number} options.pitch_max radians; π/2 looks straight down
35
+ * @param {Vector3} options.pan_axes per-axis scale on a pan's world displacement, as
36
+ * {@link TopDownCameraController.pan} takes it; zero Y to keep the target on the ground
37
+ */
38
+ constructor(controller: TopDownCameraController, { orbit_buttons, pan_buttons, pitch_min, pitch_max, pan_axes }: {
39
+ orbit_buttons: number;
40
+ pan_buttons: number;
41
+ pitch_min: number;
42
+ pitch_max: number;
43
+ pan_axes: Vector3;
44
+ });
45
+ /**
46
+ * Start a drag. Stops every throw, then takes direct control of orbit or pan, chosen by the
47
+ * buttons held; with neither, the drag moves nothing.
48
+ *
49
+ * @param {number} buttons {@link MouseEvent.buttons} of the event that started the drag
50
+ */
51
+ begin(buttons: number): void;
52
+ /**
53
+ * The pointer moved during a drag, applied to the controller at once.
54
+ *
55
+ * An orbit turns the view a full turn per viewport height of travel, pitch clamped to the rig's
56
+ * range; a pan carries the world under the pointer along with it.
57
+ *
58
+ * @param {number} delta_x pixels, the pointer's position less where it was
59
+ * @param {number} delta_y pixels, the pointer's position less where it was, down positive
60
+ * @param {number} viewport_height pixels
61
+ * @param {number} fov vertical field of view, in degrees
62
+ */
63
+ move(delta_x: number, delta_y: number, viewport_height: number, fov: number): void;
64
+ /**
65
+ * End the drag, throwing with its recent velocity.
66
+ */
67
+ end(): void;
68
+ /**
69
+ * Drop any drag and every throw, leaving the controller where it is.
70
+ */
71
+ stop(): void;
72
+ /**
73
+ * Zoom by wheel notches, within the controller's distance range.
74
+ * @param {number} notches positive away from the target, as a wheel scrolled down reports it
75
+ */
76
+ dolly(notches: number): void;
77
+ /**
78
+ * Advance one frame: sample an engaged drag for its throw, or carry a throw on.
79
+ * @param {number} dt seconds
80
+ */
81
+ update(dt: number): void;
82
+ #private;
83
+ }
84
+ import TopDownCameraController from "../../ecs/camera/topdown/TopDownCameraController.js";
85
+ import Vector3 from "../../../../core/geom/Vector3.js";
86
+ //# sourceMappingURL=OrbitalCameraRig.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"OrbitalCameraRig.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/graphics/camera/orbital/OrbitalCameraRig.js"],"names":[],"mappings":"AAuCA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA0CI;;;;;;;;;;;;OAYG;IACH,wBAZW,uBAAuB;QAGP,aAAa,EAA7B,MAAM;QAEU,WAAW,EAA3B,MAAM;QAEU,SAAS,EAAzB,MAAM;QACU,SAAS,EAAzB,MAAM;QACW,QAAQ,EAAzB,OAAO;OAkBjB;IAED;;;;;OAKG;IACH,eAFW,MAAM,QAiBhB;IAED;;;;;;;;;;OAUG;IACH,cALW,MAAM,WACN,MAAM,mBACN,MAAM,OACN,MAAM,QAQhB;IAED;;OAEG;IACH,YAWC;IAED;;OAEG;IACH,aAQC;IAED;;;OAGG;IACH,eAFW,MAAM,QAUhB;IAED;;;OAGG;IACH,WAFW,MAAM,QAyChB;;CAwDJ;oCAzTmC,qDAAqD;oBAFrE,kCAAkC"}