@woosh/meep-engine 3.64.1 → 3.65.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (324) hide show
  1. package/CHANGELOG.md +85 -0
  2. package/build/bundle-worker-image-decoder.js +1 -1
  3. package/build/bundle-worker-terrain.js +1 -1
  4. package/package.json +1 -1
  5. package/src/core/binary/BinaryBuffer.d.ts +5 -0
  6. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  7. package/src/core/binary/BinaryBuffer.js +39 -5
  8. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts +65 -6
  9. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.d.ts.map +1 -1
  10. package/src/core/geom/3d/topology/struct/binary/io/bt_boundary_loop.js +451 -101
  11. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts +4 -2
  12. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.d.ts.map +1 -1
  13. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_close_boundary_holes.js +4 -2
  14. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts +8 -1
  15. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.d.ts.map +1 -1
  16. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_fill_small_holes.js +45 -10
  17. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.d.ts.map +1 -1
  18. package/src/core/geom/3d/topology/struct/binary/query/bt_mesh_face_find_path_polyanya.js +237 -119
  19. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts +143 -0
  20. package/src/engine/graphics/ecs/grass/GrassSpecies.d.ts.map +1 -0
  21. package/src/engine/graphics/ecs/grass/GrassSpecies.js +189 -0
  22. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts +25 -0
  23. package/src/engine/graphics/ecs/grass/GrassSurface.d.ts.map +1 -0
  24. package/src/engine/graphics/ecs/grass/GrassSurface.js +32 -0
  25. package/src/engine/graphics/ecs/grass/GroundCover.d.ts +68 -0
  26. package/src/engine/graphics/ecs/grass/GroundCover.d.ts.map +1 -0
  27. package/src/engine/graphics/ecs/grass/GroundCover.js +85 -0
  28. package/src/engine/graphics3/GrassSurfaceSystem.d.ts +153 -0
  29. package/src/engine/graphics3/GrassSurfaceSystem.d.ts.map +1 -0
  30. package/src/engine/graphics3/GrassSurfaceSystem.js +1076 -0
  31. package/src/engine/graphics3/GroundCoverSystem.d.ts +33 -0
  32. package/src/engine/graphics3/GroundCoverSystem.d.ts.map +1 -0
  33. package/src/engine/graphics3/GroundCoverSystem.js +58 -0
  34. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  35. package/src/engine/network/NetworkSession.js +372 -110
  36. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  37. package/src/engine/network/orchestrator/NetworkPeer.js +6 -1
  38. package/src/engine/network/orchestrator/ServerAuthoritativeClient.d.ts.map +1 -1
  39. package/src/engine/network/orchestrator/ServerAuthoritativeClient.js +9 -2
  40. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  41. package/src/engine/network/orchestrator/ServerAuthoritativeServer.js +325 -140
  42. package/src/engine/network/sim/SimActionExecutor.d.ts +4 -1
  43. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  44. package/src/engine/network/sim/SimActionExecutor.js +65 -9
  45. package/src/engine/network/state/PredictionHistory.d.ts.map +1 -1
  46. package/src/engine/network/state/PredictionHistory.js +6 -1
  47. package/src/engine/network/time/AdaptiveRenderDelay.d.ts +25 -14
  48. package/src/engine/network/time/AdaptiveRenderDelay.d.ts.map +1 -1
  49. package/src/engine/network/time/AdaptiveRenderDelay.js +38 -20
  50. package/src/engine/network/time/RenderPlayout.d.ts +23 -3
  51. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  52. package/src/engine/network/time/RenderPlayout.js +40 -4
  53. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
  54. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts +5 -1
  55. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.d.ts.map +1 -1
  56. package/src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js +27 -1
  57. package/src/shade/device/shader/ShaderModuleCompiler.d.ts +2 -0
  58. package/src/shade/device/shader/ShaderModuleCompiler.d.ts.map +1 -1
  59. package/src/shade/device/shader/ShaderModuleCompiler.js +25 -2
  60. package/src/shade/playground/grass_surfaces/index.html +75 -0
  61. package/src/shade/playground/grass_surfaces/main.d.ts +2 -0
  62. package/src/shade/playground/grass_surfaces/main.d.ts.map +1 -0
  63. package/src/shade/playground/grass_surfaces/main.js +593 -0
  64. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts +62 -0
  65. package/src/shade/playground/grass_surfaces/read_grass_surfaces.d.ts.map +1 -0
  66. package/src/shade/playground/grass_surfaces/read_grass_surfaces.js +188 -0
  67. package/src/shade/playground/probe_clipmap_box/README.md +5 -1
  68. package/src/shade/playground/probe_clipmap_box/index.html +12 -0
  69. package/src/shade/playground/probe_clipmap_box/main.d.ts.map +1 -1
  70. package/src/shade/playground/probe_clipmap_box/main.js +15 -0
  71. package/src/shade/playground/probe_clipmap_box/scene.d.ts +8 -1
  72. package/src/shade/playground/probe_clipmap_box/scene.d.ts.map +1 -1
  73. package/src/shade/playground/probe_clipmap_box/scene.js +74 -6
  74. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  75. package/src/shade/renderer/Renderer.js +47 -43
  76. package/src/shade/renderer/extension/ViewTextures.d.ts +12 -5
  77. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  78. package/src/shade/renderer/extension/ViewTextures.js +19 -5
  79. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +3 -1
  80. package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts.map +1 -1
  81. package/src/shade/renderer/fluid/GPUFluidCascadeStack.js +6 -1
  82. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +7 -0
  83. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts.map +1 -1
  84. package/src/shade/renderer/fluid/forcing/GPUFluidForcing.js +10 -0
  85. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +7 -1
  86. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
  87. package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +46 -15
  88. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts +3 -2
  89. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.d.ts.map +1 -1
  90. package/src/shade/renderer/geometry/sdf/bundle/ModelCacheBundle.js +3 -2
  91. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts +22 -0
  92. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.d.ts.map +1 -0
  93. package/src/shade/renderer/geometry/sdf/bundle/model_cache_bundle_sort_morton.js +247 -0
  94. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts +50 -0
  95. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
  96. package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +101 -0
  97. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts +2 -1
  98. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.d.ts.map +1 -1
  99. package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSettings.js +2 -1
  100. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts +8 -0
  101. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.d.ts.map +1 -1
  102. package/src/shade/renderer/global_illumination/probe_clipmap/brick/GPUBrickClipmap.js +12 -0
  103. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts +12 -6
  104. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.d.ts.map +1 -1
  105. package/src/shade/renderer/global_illumination/probe_clipmap/brick/chunk_brick_clipmap_trace.js +35 -29
  106. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.d.ts.map +1 -1
  107. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_clipmap.js +4 -2
  108. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.d.ts.map +1 -1
  109. package/src/shade/renderer/global_illumination/probe_clipmap/debug/graph_probe_clipmap_debug_brick_material.js +6 -4
  110. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.d.ts.map +1 -1
  111. package/src/shade/renderer/global_illumination/probe_clipmap/material/GPUBrickMaterial.js +2 -1
  112. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts +6 -5
  113. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.d.ts.map +1 -1
  114. package/src/shade/renderer/global_illumination/probe_clipmap/material/chunk_brick_material.js +15 -14
  115. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.d.ts.map +1 -1
  116. package/src/shade/renderer/global_illumination/probe_clipmap/material/shader_brick_material_gather.js +4 -2
  117. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +19 -2
  118. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
  119. package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +128 -10
  120. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts +19 -1
  121. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.d.ts.map +1 -1
  122. package/src/shade/renderer/global_illumination/probe_clipmap/probe/PROBE_CLIPMAP.js +27 -2
  123. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts +19 -11
  124. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.d.ts.map +1 -1
  125. package/src/shade/renderer/global_illumination/probe_clipmap/probe/ProbeClipmapScreenWants.js +35 -11
  126. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.d.ts.map +1 -1
  127. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap.js +3 -1
  128. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts +40 -0
  129. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.d.ts.map +1 -0
  130. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_box_cages.js +174 -0
  131. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.d.ts +4 -4
  132. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_material.js +10 -10
  133. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts +31 -0
  134. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.d.ts.map +1 -0
  135. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_parallax.js +54 -0
  136. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts +8 -4
  137. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.d.ts.map +1 -1
  138. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_sample_radiance.js +10 -21
  139. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts +7 -2
  140. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.d.ts.map +1 -1
  141. package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_want.js +33 -29
  142. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts +28 -0
  143. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.d.ts.map +1 -0
  144. package/src/shade/renderer/global_illumination/probe_clipmap/probe/graph_probe_clipmap_want_meshlets.js +138 -0
  145. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts +13 -9
  146. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.d.ts.map +1 -1
  147. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_due.js +18 -11
  148. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_light.js +1 -1
  149. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.d.ts.map +1 -1
  150. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_relocate.js +4 -2
  151. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.d.ts.map +1 -1
  152. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_retire.js +2 -3
  153. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts +5 -3
  154. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.d.ts.map +1 -1
  155. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_schedule.js +15 -30
  156. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -1
  157. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.d.ts.map +1 -1
  158. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_trace.js +4 -2
  159. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts +11 -0
  160. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.d.ts.map +1 -1
  161. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want.js +29 -2
  162. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts +40 -0
  163. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.d.ts.map +1 -0
  164. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_late.js +126 -0
  165. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts +36 -0
  166. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.d.ts.map +1 -0
  167. package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_want_meshlets.js +221 -0
  168. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts +40 -0
  169. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.d.ts.map +1 -0
  170. package/src/shade/renderer/gpu_primitive/age_eviction/chunk_age_eviction.js +86 -0
  171. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts +135 -0
  172. package/src/shade/renderer/grass/blade/GPUGrassBlades.d.ts.map +1 -0
  173. package/src/shade/renderer/grass/blade/GPUGrassBlades.js +676 -0
  174. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts +145 -0
  175. package/src/shade/renderer/grass/blade/GRASS_BLADE.d.ts.map +1 -0
  176. package/src/shade/renderer/grass/blade/GRASS_BLADE.js +179 -0
  177. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts +63 -0
  178. package/src/shade/renderer/grass/blade/chunk_grass_blade.d.ts.map +1 -0
  179. package/src/shade/renderer/grass/blade/chunk_grass_blade.js +244 -0
  180. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts +58 -0
  181. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.d.ts.map +1 -0
  182. package/src/shade/renderer/grass/blade/chunk_grass_blade_wind.js +174 -0
  183. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts +25 -0
  184. package/src/shade/renderer/grass/blade/grass_blade_id_draw.d.ts.map +1 -0
  185. package/src/shade/renderer/grass/blade/grass_blade_id_draw.js +133 -0
  186. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts +80 -0
  187. package/src/shade/renderer/grass/blade/grass_blade_mechanics.d.ts.map +1 -0
  188. package/src/shade/renderer/grass/blade/grass_blade_mechanics.js +92 -0
  189. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts +29 -0
  190. package/src/shade/renderer/grass/blade/grass_blade_resolve.d.ts.map +1 -0
  191. package/src/shade/renderer/grass/blade/grass_blade_resolve.js +175 -0
  192. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts +14 -0
  193. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.d.ts.map +1 -0
  194. package/src/shade/renderer/grass/blade/shader_grass_blade_draw_args.js +45 -0
  195. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts +61 -0
  196. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.d.ts.map +1 -0
  197. package/src/shade/renderer/grass/blade/shader_grass_blade_expand.js +340 -0
  198. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts +46 -0
  199. package/src/shade/renderer/grass/blade/shader_grass_cell_count.d.ts.map +1 -0
  200. package/src/shade/renderer/grass/blade/shader_grass_cell_count.js +280 -0
  201. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts +60 -0
  202. package/src/shade/renderer/grass/population/chunk_grass_population.d.ts.map +1 -0
  203. package/src/shade/renderer/grass/population/chunk_grass_population.js +171 -0
  204. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts +99 -0
  205. package/src/shade/renderer/grass/press/GPUGrassPress.d.ts.map +1 -0
  206. package/src/shade/renderer/grass/press/GPUGrassPress.js +436 -0
  207. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts +179 -0
  208. package/src/shade/renderer/grass/press/GRASS_PRESS.d.ts.map +1 -0
  209. package/src/shade/renderer/grass/press/GRASS_PRESS.js +217 -0
  210. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts +65 -0
  211. package/src/shade/renderer/grass/press/chunk_grass_press.d.ts.map +1 -0
  212. package/src/shade/renderer/grass/press/chunk_grass_press.js +296 -0
  213. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts +31 -0
  214. package/src/shade/renderer/grass/press/shader_grass_press_mark.d.ts.map +1 -0
  215. package/src/shade/renderer/grass/press/shader_grass_press_mark.js +169 -0
  216. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts +27 -0
  217. package/src/shade/renderer/grass/press/shader_grass_press_stamp.d.ts.map +1 -0
  218. package/src/shade/renderer/grass/press/shader_grass_press_stamp.js +183 -0
  219. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts +193 -0
  220. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.d.ts.map +1 -0
  221. package/src/shade/renderer/grass/surface/GPUGrassSurfaces.js +1253 -0
  222. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts +211 -0
  223. package/src/shade/renderer/grass/surface/GRASS_SURFACE.d.ts.map +1 -0
  224. package/src/shade/renderer/grass/surface/GRASS_SURFACE.js +241 -0
  225. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts +82 -0
  226. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.d.ts.map +1 -0
  227. package/src/shade/renderer/grass/surface/GRASS_SURFACE_VIEW.js +111 -0
  228. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts +39 -0
  229. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.d.ts.map +1 -0
  230. package/src/shade/renderer/grass/surface/chunk_grass_column_cross.js +85 -0
  231. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts +29 -0
  232. package/src/shade/renderer/grass/surface/chunk_grass_directory.d.ts.map +1 -0
  233. package/src/shade/renderer/grass/surface/chunk_grass_directory.js +112 -0
  234. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts +27 -0
  235. package/src/shade/renderer/grass/surface/chunk_grass_slot.d.ts.map +1 -0
  236. package/src/shade/renderer/grass/surface/chunk_grass_slot.js +50 -0
  237. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts +21 -0
  238. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.d.ts.map +1 -0
  239. package/src/shade/renderer/grass/surface/chunk_grass_surface_frame.js +41 -0
  240. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts +32 -0
  241. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.d.ts.map +1 -0
  242. package/src/shade/renderer/grass/surface/chunk_grass_surface_window.js +136 -0
  243. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts +37 -0
  244. package/src/shade/renderer/grass/surface/chunk_grass_surfel.d.ts.map +1 -0
  245. package/src/shade/renderer/grass/surface/chunk_grass_surfel.js +85 -0
  246. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts +25 -0
  247. package/src/shade/renderer/grass/surface/chunk_grass_tile.d.ts.map +1 -0
  248. package/src/shade/renderer/grass/surface/chunk_grass_tile.js +52 -0
  249. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts +23 -0
  250. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.d.ts.map +1 -0
  251. package/src/shade/renderer/grass/surface/shader_grass_directory_fill.js +87 -0
  252. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts +43 -0
  253. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.d.ts.map +1 -0
  254. package/src/shade/renderer/grass/surface/shader_grass_surface_bake.js +265 -0
  255. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts +13 -0
  256. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.d.ts.map +1 -0
  257. package/src/shade/renderer/grass/surface/shader_grass_surface_bake_command.js +49 -0
  258. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts +62 -0
  259. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.d.ts.map +1 -0
  260. package/src/shade/renderer/grass/surface/shader_grass_surface_invalidate.js +162 -0
  261. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts +40 -0
  262. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.d.ts.map +1 -0
  263. package/src/shade/renderer/grass/surface/shader_grass_surface_retire.js +155 -0
  264. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts +19 -0
  265. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.d.ts.map +1 -0
  266. package/src/shade/renderer/grass/surface/shader_grass_surface_schedule.js +58 -0
  267. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts +30 -0
  268. package/src/shade/renderer/grass/surface/shader_grass_surface_want.d.ts.map +1 -0
  269. package/src/shade/renderer/grass/surface/shader_grass_surface_want.js +251 -0
  270. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts +21 -0
  271. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.d.ts.map +1 -0
  272. package/src/shade/renderer/grass/surface/shader_grass_surface_window_count.js +75 -0
  273. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.d.ts.map +1 -1
  274. package/src/shade/renderer/postprocess/velocity/graph_add_per_object_velocity.js +4 -23
  275. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts +12 -0
  276. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.d.ts.map +1 -0
  277. package/src/shade/renderer/postprocess/velocity/view_velocity_matrices.js +29 -0
  278. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  279. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +22 -0
  280. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  281. package/src/shade/renderer/scene/GPUSceneContext.js +3 -0
  282. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts +27 -0
  283. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.d.ts.map +1 -0
  284. package/src/shade/renderer/scene/GRASS_SURFACE_PARAMS_STRUCT.js +38 -0
  285. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts +28 -0
  286. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.d.ts.map +1 -0
  287. package/src/shade/renderer/scene/MESH_GROUND_COVER_STRUCT.js +58 -0
  288. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.d.ts.map +1 -1
  289. package/src/shade/renderer/scene/SCENE_DATABASE_SPEC.js +8 -0
  290. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts +37 -0
  291. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.d.ts.map +1 -0
  292. package/src/shade/renderer/shader/chunk/geometry/ray/chunk_ray_query_nearest_among.js +148 -0
  293. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts +20 -0
  294. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.d.ts.map +1 -0
  295. package/src/shade/renderer/shader/chunk/sdf/chunk_shape_record_line_span.js +169 -0
  296. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts +18 -0
  297. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.d.ts.map +1 -1
  298. package/src/shade/renderer/texture/atlas/chunk_tile_atlas_slot_origin.js +28 -0
  299. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts +13 -0
  300. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.d.ts.map +1 -0
  301. package/src/shade/renderer/texture/atlas/tile_atlas_slot_shift.js +22 -0
  302. package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
  303. package/src/shade/renderer/water/GPUWaterRenderer.js +4 -0
  304. package/src/shade/renderer/wind/GPUSceneWind.d.ts +52 -5
  305. package/src/shade/renderer/wind/GPUSceneWind.d.ts.map +1 -1
  306. package/src/shade/renderer/wind/GPUSceneWind.js +164 -8
  307. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts +3 -1
  308. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.d.ts.map +1 -1
  309. package/src/shade/renderer/wind/WIND_FIELD_UNIFORM.js +3 -1
  310. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts +2 -1
  311. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.d.ts.map +1 -1
  312. package/src/shade/renderer/wind/chunk_wind_field_sample_cascades.js +18 -13
  313. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts +13 -0
  314. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.d.ts.map +1 -0
  315. package/src/shade/renderer/wind/chunk_wind_field_sample_previous.js +23 -0
  316. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts +1 -0
  317. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.d.ts.map +1 -1
  318. package/src/shade/renderer/wind/chunk_wind_field_sample_uniform.js +6 -1
  319. package/src/shade/renderer/wind/wind_field_add_resources.d.ts +11 -0
  320. package/src/shade/renderer/wind/wind_field_add_resources.d.ts.map +1 -1
  321. package/src/shade/renderer/wind/wind_field_add_resources.js +15 -0
  322. package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +1 -1
  323. package/src/shade/wgsl/emulator/WGSLLanguageCore.d.ts.map +1 -1
  324. package/src/shade/wgsl/emulator/WGSLLanguageCore.js +2 -0
@@ -1 +1 @@
1
- {"version":3,"file":"SimActionExecutor.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/SimActionExecutor.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,2BAFU,MAAM,CAEiB;AAEjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,6BAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;GAUG;AACH,8BAFU,MAAM,CAEoB;AAEpC;;;;;;;;;;;;GAYG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;GAMG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA2EI;;;;;;;;;OASG;IACH,sGATW;QACV,KAAS,yBAAyB;QAClC,UAAc,YAAY;QAC1B,eAAmB,oBAAoB;QACvC,kBAAsB,8BAA8B;QACpD,UAAc,uBAAuB;QACrC,gBAAoB,CAAC,mBAAmB;KACrC,EAyFH;IAjKD;;;;;;;;;OASG;IACH,gBAFU,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEP;IAEtB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,KAAK,OAAO,CAAC,GAAG,IAAI,CAEtE;IAEjB;;;;;;;;;;;;;;;OAeG;IACH,UAFU,OAAO,CAEA;IAEjB;;;;;;;OAOG;IACH,sBAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAE7C;IAaxB;;OAEG;IACH,8BAAkB;IAElB;;OAEG;IACH,sBAA4B;IAE5B;;OAEG;IACH,mCAAsC;IAEtC;;OAEG;IACH,gDAA4C;IAE5C;;;;OAIG;IACH,iCAA4B;IAE5B;;;;;;;;;;;OAWG;IACH,kBAFU,mBAAiB,IAAI,CAES;IA4BxC;;;;;;;OAOG;IACH,mBAFU,MAAM,CAEqB;IAErC;;;;;;;OAOG;IACH,kBAFU,MAAM,CAEoB;IAGxC;;;;;;;;;;;;;;OAcG;IACH,uCAPW,MAAM,GAGJ,OAAO,CA0KnB;IAkCD;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gCAwCC;IAED;;;;;;;;;;;;;OAaG;IACH,4BAFW,MAAM,QAqChB;IAED;;;;;;;;OAQG;IACH,sBAJW,UAAU,UACV,MAAM,UACN,MAAM,QAchB;;CACJ;mBAjnBkB,uCAAuC"}
1
+ {"version":3,"file":"SimActionExecutor.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/sim/SimActionExecutor.js"],"names":[],"mappings":"AAGA;;;;;;;GAOG;AACH,2BAFU,MAAM,CAEiB;AAEjC;;;;;;;;;;;;;;;;;;;;;;;GAuBG;AACH,6BAFU,MAAM,CAEmB;AAEnC;;;;;;;;;;GAUG;AACH,8BAFU,MAAM,CAEoB;AAEpC;;;;;;;;;;;;GAYG;AACH,+BAFU,MAAM,CAEqB;AAErC;;;;;;GAMG;AACH,0BAFU,MAAM,CAEgB;AAEhC;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH;IA0FI;;;;;;;;;OASG;IACH,sGATW;QACV,KAAS,yBAAyB;QAClC,UAAc,YAAY;QAC1B,eAAmB,oBAAoB;QACvC,kBAAsB,8BAA8B;QACpD,UAAc,uBAAuB;QACrC,gBAAoB,CAAC,mBAAmB;KACrC,EA6FH;IArKD;;;;;;;;;OASG;IACH,gBAFU,CAAC,MAAM,IAAI,CAAC,GAAG,IAAI,CAEP;IAEtB;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,WAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,MAAM,WAAW,KAAK,OAAO,CAAC,GAAG,IAAI,CAEtE;IAEjB;;;;;;;;;;;;;;;OAeG;IACH,UAFU,OAAO,CAEA;IAEjB;;;;;;;OAOG;IACH,sBAFU,CAAC,CAAC,SAAS,EAAE,MAAM,EAAE,eAAe,UAAU,KAAK,IAAI,CAAC,GAAG,IAAI,CAE7C;IAaxB;;OAEG;IACH,8BAAkB;IAElB;;OAEG;IACH,sBAA4B;IAE5B;;OAEG;IACH,mCAAsC;IAEtC;;OAEG;IACH,gDAA4C;IAE5C;;;;OAIG;IACH,iCAA4B;IAE5B;;;;;;;;;;;OAWG;IACH,kBAFU,mBAAiB,IAAI,CAES;IAgCxC;;;;;;;OAOG;IACH,mBAFU,MAAM,CAEqB;IAErC;;;;;;;OAOG;IACH,kBAFU,MAAM,CAEoB;IAGxC;;;;;;;;;;;;;;;;;OAiBG;IACH,uCAPW,MAAM,GAGJ,OAAO,CAcnB;IAgND;;;;;;;;;;;;;;;;;;;;;;OAsBG;IACH,gCAUC;IAgDD;;;;;;;;;;;;;OAaG;IACH,4BAFW,MAAM,QAqChB;IAED;;;;;;;;OAQG;IACH,sBAJW,UAAU,UACV,MAAM,UACN,MAAM,QAchB;;CACJ;mBAzqBkB,uCAAuC"}
@@ -102,6 +102,21 @@ export class SimActionExecutor {
102
102
  #scratch_classes;
103
103
  #collect_cb;
104
104
 
105
+ /**
106
+ * How many of the scratch pairs belong to the action being executed. The arrays are never
107
+ * truncated: an array cut to length 0 gives up its storage, and the next action's first pair
108
+ * allocates it again.
109
+ * @type {number}
110
+ */
111
+ #scratch_count = 0;
112
+
113
+ /**
114
+ * Inside {@link execute} or {@link record}. The scratch pairs are the running action's, so a
115
+ * second action started before the first returns would take them over.
116
+ * @type {boolean}
117
+ */
118
+ #executing = false;
119
+
105
120
  /**
106
121
  * Between {@link begin_correction} and {@link end_correction}.
107
122
  * @type {boolean}
@@ -246,8 +261,12 @@ export class SimActionExecutor {
246
261
  * @private
247
262
  */
248
263
  this.#collect_cb = (entity_id, component_class) => {
249
- this.#scratch_entities.push(entity_id);
250
- this.#scratch_classes.push(component_class);
264
+ const index = this.#scratch_count;
265
+
266
+ this.#scratch_entities[index] = entity_id;
267
+ this.#scratch_classes[index] = component_class;
268
+
269
+ this.#scratch_count = index + 1;
251
270
  };
252
271
 
253
272
  /**
@@ -276,7 +295,10 @@ export class SimActionExecutor {
276
295
  *
277
296
  * Not re-entrant: calling `execute` or {@link record} from inside `affected_components`,
278
297
  * {@link authorize}, `apply`, `announce` or {@link on_component_written} is illegal (the
279
- * executor is passed to actions for `slot_table` / `current_sender_id` reads only).
298
+ * executor is passed to actions for `slot_table` / `current_sender_id` reads only), and
299
+ * asserted. Unchecked, the inner action takes over the outer one's list of affected components:
300
+ * started from `affected_components`, the outer action's prior state is captured for the inner
301
+ * action's entity and a rewind no longer restores its own.
280
302
  *
281
303
  * @param {SimAction} action
282
304
  * @param {number} [sender_id] peer that originated this action.
@@ -287,6 +309,25 @@ export class SimActionExecutor {
287
309
  * logged).
288
310
  */
289
311
  execute(action, sender_id = SENDER_LOCAL) {
312
+ assert.equal(this.#executing, false, 'execute: called from inside execute or record; the executor is not re-entrant');
313
+
314
+ this.#executing = true;
315
+
316
+ try {
317
+ return this.#execute(action, sender_id);
318
+ } finally {
319
+ this.#executing = false;
320
+ }
321
+ }
322
+
323
+ /**
324
+ * {@link execute}, once it is known that no other action is running.
325
+ *
326
+ * @param {SimAction} action
327
+ * @param {number} sender_id
328
+ * @returns {boolean}
329
+ */
330
+ #execute(action, sender_id) {
290
331
  assert.ok(action && action.isSimAction, 'execute: action must be a SimAction');
291
332
  // A class that was never registered still carries SimAction's default
292
333
  // type_id of -1, and step 5 writes that into the log as a uint8 the
@@ -324,11 +365,10 @@ export class SimActionExecutor {
324
365
  // 1. Collect affected (entity, component_class) pairs.
325
366
  // Pass the executor as context so actions can translate network_id → entity_id
326
367
  // via this.slot_table inside affected_components.
327
- this.#scratch_entities.length = 0;
328
- this.#scratch_classes.length = 0;
368
+ this.#scratch_count = 0;
329
369
  action.affected_components(this.#collect_cb, this);
330
370
 
331
- const affected_count = this.#scratch_entities.length;
371
+ const affected_count = this.#scratch_count;
332
372
 
333
373
  // 1a. Authorization gate for remote-originated actions. A peer may only
334
374
  // mutate entities it is authorized for; reject the whole action before
@@ -510,16 +550,32 @@ export class SimActionExecutor {
510
550
  * @param {SimAction} action
511
551
  */
512
552
  record(action) {
553
+ assert.equal(this.#executing, false, 'record: called from inside execute or record; the executor is not re-entrant');
554
+
555
+ this.#executing = true;
556
+
557
+ try {
558
+ this.#record(action);
559
+ } finally {
560
+ this.#executing = false;
561
+ }
562
+ }
563
+
564
+ /**
565
+ * {@link record}, once it is known that no other action is running.
566
+ *
567
+ * @param {SimAction} action
568
+ */
569
+ #record(action) {
513
570
  assert.ok(action && action.isSimAction, 'record: action must be a SimAction');
514
571
  assert.ok(
515
572
  action.constructor.type_id >= 0,
516
573
  `record: action class '${action.constructor.action_type_name ?? action.constructor.name}' has no wire type_id — register it before recording it`,
517
574
  );
518
575
 
519
- this.#scratch_entities.length = 0;
520
- this.#scratch_classes.length = 0;
576
+ this.#scratch_count = 0;
521
577
  action.affected_components(this.#collect_cb, this);
522
- const affected_count = this.#scratch_entities.length;
578
+ const affected_count = this.#scratch_count;
523
579
 
524
580
  for (let i = 0; i < affected_count; i++) {
525
581
  if (this.component_registry.type_id_of(this.#scratch_classes[i]) < 0) {
@@ -1 +1 @@
1
- {"version":3,"file":"PredictionHistory.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/state/PredictionHistory.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH;IAMI;;OAEG;IACH,uBAFW,MAAM,EAOhB;IAFG,+BAA+B;IAC/B,mBADqB,MAAM,CACH;IAkB5B;;;;;;;;;OASG;IACH,eANW,MAAM,SACN,MAAM,WACN,MAAM,UACN,UAAU,UACV,MAAM,QAwBhB;IAED;;;;;OAKG;IACH,YALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,eALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;;OASG;IACH,cALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,UAAU,GAAC,IAAI,CAK3B;IAED;;OAEG;IACH,eAFW,MAAM,QAIhB;IAED,cAEC;;CACJ"}
1
+ {"version":3,"file":"PredictionHistory.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/state/PredictionHistory.js"],"names":[],"mappings":"AAcA;;;;;;;;;;;;;GAaG;AACH;IAMI;;OAEG;IACH,uBAFW,MAAM,EAOhB;IAFG,+BAA+B;IAC/B,mBADqB,MAAM,CACH;IAkB5B;;;;;;;;;OASG;IACH,eANW,MAAM,SACN,MAAM,WACN,MAAM,UACN,UAAU,UACV,MAAM,QA6BhB;IAED;;;;;OAKG;IACH,YALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,OAAO,CAInB;IAED;;;;;;;OAOG;IACH,eALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,MAAM,CAQlB;IAED;;;;;;;;;OASG;IACH,cALW,MAAM,SACN,MAAM,WACN,MAAM,GACJ,UAAU,GAAC,IAAI,CAK3B;IAED;;OAEG;IACH,eAFW,MAAM,QAIhB;IAED,cAEC;;CACJ"}
@@ -87,7 +87,12 @@ export class PredictionHistory {
87
87
  target = new Uint8Array(Math.max(length, 32));
88
88
  slot.bytes[type_id] = target;
89
89
  }
90
- target.set(source.subarray(0, length), 0);
90
+ // byte by byte: a view of the source would be an allocation per component per frame, and a
91
+ // component's wire state is a few tens of bytes
92
+ for (let i = 0; i < length; i++) {
93
+ target[i] = source[i];
94
+ }
95
+
91
96
  slot.lengths[type_id] = length;
92
97
  }
93
98
 
@@ -19,11 +19,18 @@
19
19
  * 2. The rolling window holds the last N lateness samples; the recommended
20
20
  * target delay (ms) = `(max(window) - min(window)) * safety_multiplier`.
21
21
  * 3. Output ramps UP to a higher target instantly (so a jitter spike is
22
- * absorbed at the next sample), and DOWN at most `decay_per_sample_ms`
23
- * ms per arrival (so we don't flap when one calm packet follows a spike).
22
+ * absorbed at the next sample), and comes DOWN to a lower one by
23
+ * `decay_rate` of the time that passes between arrivals. A delay that
24
+ * comes down plays what is drawn from it that much faster than real time,
25
+ * so the rate is also the most a calming link speeds the playout up.
24
26
  * 4. The output is clamped to `[min_delay_frames, max_delay_frames]` and
25
27
  * converted to an integer frame count.
26
28
  *
29
+ * How long a spike is remembered: for as long as it is among the last N
30
+ * samples, and after that for as long as the decay takes to shed it — its
31
+ * height over `decay_rate`. A spike that comes again within that is covered
32
+ * when it does.
33
+ *
27
34
  * Why not inter-arrival time: in a tick-driven receiver (e.g. JS engine
28
35
  * polling a transport queue at 60 Hz), arrivals are quantized to tick
29
36
  * boundaries. Bursts of frames in one packet share the same arrival time;
@@ -55,7 +62,7 @@ export class AdaptiveRenderDelay {
55
62
  * max_delay_frames?: number,
56
63
  * history_size?: number,
57
64
  * safety_multiplier?: number,
58
- * decay_per_sample_ms?: number,
65
+ * decay_rate?: number,
59
66
  * initial_delay_frames?: number,
60
67
  * }} options
61
68
  *
@@ -64,19 +71,22 @@ export class AdaptiveRenderDelay {
64
71
  * should cover 2× the observed jitter spread" and reproduces visibly
65
72
  * smooth motion in practice.
66
73
  *
67
- * `decay_per_sample_ms`: how aggressively the recommendation drops once
68
- * conditions improve. Smaller = stickier (the delay stays high even after
69
- * a calm period), larger = snappier (the delay drops faster, possibly
70
- * stuttering if jitter recurs). Default 1 ms / sample is a calm decay
71
- * that takes ~1 s to drop by 60 ms at 60 Hz arrivals.
74
+ * `decay_rate`: how fast the recommendation drops once conditions improve,
75
+ * in milliseconds of delay per millisecond between arrivals — a ratio.
76
+ * Smaller = stickier (the delay stays high for longer after a calm
77
+ * period), larger = snappier (the delay drops faster, the playout speeds
78
+ * up by more while it does, and a spike that recurs is less likely to
79
+ * find the delay still up). The default 0.05 takes 20 s to shed a second
80
+ * of delay, at any tick rate and however many frames arrive in that time.
81
+ * 0 never comes down.
72
82
  */
73
- constructor({ tick_period_ms, min_delay_frames, max_delay_frames, history_size, safety_multiplier, decay_per_sample_ms, initial_delay_frames, }: {
83
+ constructor({ tick_period_ms, min_delay_frames, max_delay_frames, history_size, safety_multiplier, decay_rate, initial_delay_frames, }: {
74
84
  tick_period_ms: number;
75
85
  min_delay_frames?: number;
76
86
  max_delay_frames?: number;
77
87
  history_size?: number;
78
88
  safety_multiplier?: number;
79
- decay_per_sample_ms?: number;
89
+ decay_rate?: number;
80
90
  initial_delay_frames?: number;
81
91
  });
82
92
  /** @readonly @type {number} */
@@ -88,7 +98,7 @@ export class AdaptiveRenderDelay {
88
98
  /** @readonly @type {number} */
89
99
  readonly safety_multiplier: number;
90
100
  /** @readonly @type {number} */
91
- readonly decay_per_sample_ms: number;
101
+ readonly decay_rate: number;
92
102
  /**
93
103
  * Record an arrival. Call this when a new frame from the sender has been
94
104
  * applied locally.
@@ -118,9 +128,10 @@ export class AdaptiveRenderDelay {
118
128
  */
119
129
  last_interval_ms(): number;
120
130
  /**
121
- * Drop all observed history. Useful after a reconnect or a level transition.
122
- * Leaves `current_delay_ms` as-is so the displayed delay doesn't snap; it
123
- * will adjust to new conditions over the next few samples.
131
+ * Start over, as constructed: no history, and the initial delay. For a
132
+ * stream that begins again — a reconnect, a level transition, a receiver
133
+ * that was away — where what was observed before, or across the gap, says
134
+ * nothing of how late the frames to come will run.
124
135
  */
125
136
  reset(): void;
126
137
  #private;
@@ -1 +1 @@
1
- {"version":3,"file":"AdaptiveRenderDelay.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/time/AdaptiveRenderDelay.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAgDG;AACH;IAqBI;;;;;;;;;;;;;;;;;;;;;OAqBG;IACH,iJArBW;QACV,cAAkB,EAAE,MAAM,CAAC;QAC3B,gBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,gBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,YAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,iBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,mBAAuB,CAAC,EAAE,MAAM,CAAC;QACjC,oBAAwB,CAAC,EAAE,MAAM,CAAC;KAC/B,EA4DH;IA1BG,+BAA+B;IAC/B,yBADqB,MAAM,CACS;IACpC,+BAA+B;IAC/B,2BADqB,MAAM,CACa;IACxC,+BAA+B;IAC/B,2BADqB,MAAM,CACa;IACxC,+BAA+B;IAC/B,4BADqB,MAAM,CACe;IAC1C,+BAA+B;IAC/B,8BADqB,MAAM,CACmB;IAmBlD;;;;;;OAMG;IACH,uBAHW,MAAM,gBACN,MAAM,QAkDhB;IAED;;;;;OAKG;IACH,gBAFa,MAAM,CAKlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAQlB;IAED;;;;;OAKG;IACH,oBAFa,MAAM,CAKlB;IAED;;;;OAIG;IACH,cAOC;;CACJ"}
1
+ {"version":3,"file":"AdaptiveRenderDelay.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/time/AdaptiveRenderDelay.js"],"names":[],"mappings":"AAGA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAuDG;AACH;IAuBI;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,wIAxBW;QACV,cAAkB,EAAE,MAAM,CAAC;QAC3B,gBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,gBAAoB,CAAC,EAAE,MAAM,CAAC;QAC9B,YAAgB,CAAC,EAAE,MAAM,CAAC;QAC1B,iBAAqB,CAAC,EAAE,MAAM,CAAC;QAC/B,UAAc,CAAC,EAAE,MAAM,CAAC;QACxB,oBAAwB,CAAC,EAAE,MAAM,CAAC;KAC/B,EAgEH;IA3BG,+BAA+B;IAC/B,yBADqB,MAAM,CACS;IACpC,+BAA+B;IAC/B,2BADqB,MAAM,CACa;IACxC,+BAA+B;IAC/B,2BADqB,MAAM,CACa;IACxC,+BAA+B;IAC/B,4BADqB,MAAM,CACe;IAC1C,+BAA+B;IAC/B,qBADqB,MAAM,CACC;IAoBhC;;;;;;OAMG;IACH,uBAHW,MAAM,gBACN,MAAM,QAqDhB;IAED;;;;;OAKG;IACH,gBAFa,MAAM,CAKlB;IAED;;;;OAIG;IACH,YAFa,MAAM,CAQlB;IAED;;;;;OAKG;IACH,oBAFa,MAAM,CAKlB;IAED;;;;;OAKG;IACH,cAQC;;CACJ"}
@@ -22,11 +22,18 @@ import { clamp } from "../../../core/math/clamp.js";
22
22
  * 2. The rolling window holds the last N lateness samples; the recommended
23
23
  * target delay (ms) = `(max(window) - min(window)) * safety_multiplier`.
24
24
  * 3. Output ramps UP to a higher target instantly (so a jitter spike is
25
- * absorbed at the next sample), and DOWN at most `decay_per_sample_ms`
26
- * ms per arrival (so we don't flap when one calm packet follows a spike).
25
+ * absorbed at the next sample), and comes DOWN to a lower one by
26
+ * `decay_rate` of the time that passes between arrivals. A delay that
27
+ * comes down plays what is drawn from it that much faster than real time,
28
+ * so the rate is also the most a calming link speeds the playout up.
27
29
  * 4. The output is clamped to `[min_delay_frames, max_delay_frames]` and
28
30
  * converted to an integer frame count.
29
31
  *
32
+ * How long a spike is remembered: for as long as it is among the last N
33
+ * samples, and after that for as long as the decay takes to shed it — its
34
+ * height over `decay_rate`. A spike that comes again within that is covered
35
+ * when it does.
36
+ *
30
37
  * Why not inter-arrival time: in a tick-driven receiver (e.g. JS engine
31
38
  * polling a transport queue at 60 Hz), arrivals are quantized to tick
32
39
  * boundaries. Bursts of frames in one packet share the same arrival time;
@@ -70,6 +77,8 @@ export class AdaptiveRenderDelay {
70
77
  /** @private @type {number} */
71
78
  #last_frame = -1;
72
79
  #current_delay_ms;
80
+ /** @private @type {number} */
81
+ #initial_delay_ms;
73
82
 
74
83
  /**
75
84
  * @param {{
@@ -78,7 +87,7 @@ export class AdaptiveRenderDelay {
78
87
  * max_delay_frames?: number,
79
88
  * history_size?: number,
80
89
  * safety_multiplier?: number,
81
- * decay_per_sample_ms?: number,
90
+ * decay_rate?: number,
82
91
  * initial_delay_frames?: number,
83
92
  * }} options
84
93
  *
@@ -87,11 +96,14 @@ export class AdaptiveRenderDelay {
87
96
  * should cover 2× the observed jitter spread" and reproduces visibly
88
97
  * smooth motion in practice.
89
98
  *
90
- * `decay_per_sample_ms`: how aggressively the recommendation drops once
91
- * conditions improve. Smaller = stickier (the delay stays high even after
92
- * a calm period), larger = snappier (the delay drops faster, possibly
93
- * stuttering if jitter recurs). Default 1 ms / sample is a calm decay
94
- * that takes ~1 s to drop by 60 ms at 60 Hz arrivals.
99
+ * `decay_rate`: how fast the recommendation drops once conditions improve,
100
+ * in milliseconds of delay per millisecond between arrivals — a ratio.
101
+ * Smaller = stickier (the delay stays high for longer after a calm
102
+ * period), larger = snappier (the delay drops faster, the playout speeds
103
+ * up by more while it does, and a spike that recurs is less likely to
104
+ * find the delay still up). The default 0.05 takes 20 s to shed a second
105
+ * of delay, at any tick rate and however many frames arrive in that time.
106
+ * 0 never comes down.
95
107
  */
96
108
  constructor({
97
109
  tick_period_ms,
@@ -99,7 +111,7 @@ export class AdaptiveRenderDelay {
99
111
  max_delay_frames = 30,
100
112
  history_size = 30,
101
113
  safety_multiplier = 2.0,
102
- decay_per_sample_ms = 1.0,
114
+ decay_rate = 0.05,
103
115
  initial_delay_frames = 2,
104
116
  }) {
105
117
  assert.isNumber(tick_period_ms, 'tick_period_ms');
@@ -111,8 +123,8 @@ export class AdaptiveRenderDelay {
111
123
  assert.ok(history_size >= 1, 'history_size must be >= 1');
112
124
  assert.isNumber(safety_multiplier, 'safety_multiplier');
113
125
  assert.ok(safety_multiplier >= 1, 'safety_multiplier must be >= 1');
114
- assert.isNumber(decay_per_sample_ms, 'decay_per_sample_ms');
115
- assert.ok(decay_per_sample_ms >= 0, 'decay_per_sample_ms must be >= 0');
126
+ assert.isNumber(decay_rate, 'decay_rate');
127
+ assert.ok(decay_rate >= 0, 'decay_rate must be >= 0');
116
128
 
117
129
  /** @readonly @type {number} */
118
130
  this.tick_period_ms = tick_period_ms;
@@ -123,7 +135,7 @@ export class AdaptiveRenderDelay {
123
135
  /** @readonly @type {number} */
124
136
  this.safety_multiplier = safety_multiplier;
125
137
  /** @readonly @type {number} */
126
- this.decay_per_sample_ms = decay_per_sample_ms;
138
+ this.decay_rate = decay_rate;
127
139
 
128
140
  /**
129
141
  * Rolling window of recent lateness samples in ms (`now - frame*tick`).
@@ -139,7 +151,8 @@ export class AdaptiveRenderDelay {
139
151
  * is cheap.
140
152
  * @private @type {number}
141
153
  */
142
- this.#current_delay_ms = initial_delay_frames * tick_period_ms;
154
+ this.#initial_delay_ms = initial_delay_frames * tick_period_ms;
155
+ this.#current_delay_ms = this.#initial_delay_ms;
143
156
  }
144
157
 
145
158
  /**
@@ -161,6 +174,10 @@ export class AdaptiveRenderDelay {
161
174
  this.#index = (this.#index + 1) % cap;
162
175
  if (this.#filled < cap) this.#filled++;
163
176
 
177
+ // Time since the arrival before this one: what the delay may have come down by. Frames
178
+ // that arrive together are one moment.
179
+ const elapsed_ms = this.#last_arrival_ms < 0 ? 0 : Math.max(0, now_ms - this.#last_arrival_ms);
180
+
164
181
  this.#prev_arrival_ms = this.#last_arrival_ms;
165
182
  this.#last_arrival_ms = now_ms;
166
183
  this.#last_frame = frame_number;
@@ -186,16 +203,15 @@ export class AdaptiveRenderDelay {
186
203
  // this, a single huge lateness sample (a tab going to background for 30
187
204
  // seconds, a long GC pause, an OS suspend) pins `__current_delay_ms` to
188
205
  // an arbitrarily large value. The public delay() accessors clamp on
189
- // read, but the internal state would then take `(stored - cap) /
190
- // decay_per_sample_ms` more samples to decay back into range than the
191
- // configuration nominally allows.
206
+ // read, but the internal state would then take that much longer to
207
+ // decay back into range than the configuration nominally allows.
192
208
  const cap_ms = this.max_delay_frames * this.tick_period_ms;
193
209
 
194
210
  // Snap up immediately, decay down.
195
211
  if (target_delay_ms > this.#current_delay_ms) {
196
212
  this.#current_delay_ms = Math.min(target_delay_ms, cap_ms);
197
213
  } else {
198
- this.#current_delay_ms = Math.max(target_delay_ms, this.#current_delay_ms - this.decay_per_sample_ms);
214
+ this.#current_delay_ms = Math.max(target_delay_ms, this.#current_delay_ms - this.decay_rate * elapsed_ms);
199
215
  }
200
216
  }
201
217
 
@@ -235,9 +251,10 @@ export class AdaptiveRenderDelay {
235
251
  }
236
252
 
237
253
  /**
238
- * Drop all observed history. Useful after a reconnect or a level transition.
239
- * Leaves `current_delay_ms` as-is so the displayed delay doesn't snap; it
240
- * will adjust to new conditions over the next few samples.
254
+ * Start over, as constructed: no history, and the initial delay. For a
255
+ * stream that begins again — a reconnect, a level transition, a receiver
256
+ * that was away — where what was observed before, or across the gap, says
257
+ * nothing of how late the frames to come will run.
241
258
  */
242
259
  reset() {
243
260
  this.#lateness.fill(0);
@@ -246,5 +263,6 @@ export class AdaptiveRenderDelay {
246
263
  this.#last_arrival_ms = -1;
247
264
  this.#prev_arrival_ms = -1;
248
265
  this.#last_frame = -1;
266
+ this.#current_delay_ms = this.#initial_delay_ms;
249
267
  }
250
268
  }
@@ -9,6 +9,16 @@
9
9
  * arrived. Extracted from `NetworkSession` so any fixed-period stream — a peer's netcode frames, a
10
10
  * remote editor's presence samples — plays out the same way.
11
11
  *
12
+ * The head, `latest_frame`, is the newest frame the sender is known to have reached. A sender that
13
+ * sends nothing for a frame in which nothing changed must still say where it is
14
+ * ({@link advance_head}): otherwise the head stops with the stream, and the first frame after the
15
+ * pause is as far ahead of the playhead as the pause was long.
16
+ *
17
+ * A playhead further behind its target than the delay's largest value has not fallen behind by
18
+ * anything a delay covers — the receiver drew nothing while the sender ran on — and starts again as
19
+ * it did at the first frame: the delay is reset, since the frames that landed across the gap say
20
+ * nothing of how late frames run, and the playhead is put at its target. Anything nearer is pulled.
21
+ *
12
22
  * No allocation per call: {@link window} fills and returns one reused object.
13
23
  *
14
24
  * @author Alex Goldring
@@ -33,17 +43,27 @@ export class RenderPlayout {
33
43
  readonly delay: AdaptiveRenderDelay;
34
44
  /** @readonly @type {number} */
35
45
  readonly pull_per_ms: number;
36
- /** @type {number} highest frame number recorded; -1 before the first */
46
+ /** @type {number} newest frame the sender is known to have reached; -1 before the first */
37
47
  latest_frame: number;
38
48
  /**
39
- * A frame from the sender has been applied locally. Frames at or below the latest are
40
- * accepted data (a reordered or retransmitted frame) but do not move the head.
49
+ * A frame from the sender has been applied locally. Its lateness is a sample for the delay,
50
+ * whether or not the head has already passed it. A frame at or below the newest one recorded
51
+ * (a reordered or retransmitted frame) is accepted data, and is no sample.
41
52
  *
42
53
  * @param {number} now_ms wall clock
43
54
  * @param {number} frame_number the sender's frame index
44
55
  * @returns {boolean} true when this frame advanced the head
45
56
  */
46
57
  record_arrival(now_ms: number, frame_number: number): boolean;
58
+ /**
59
+ * The sender has reached `frame_number`, whatever it sent of it. Moves the head and nothing
60
+ * else: this is the sender's word of where it is, not a frame's arrival, and it is no sample
61
+ * for the delay.
62
+ *
63
+ * @param {number} frame_number the sender's frame index
64
+ * @returns {boolean} true when the head advanced
65
+ */
66
+ advance_head(frame_number: number): boolean;
47
67
  /**
48
68
  * @returns {boolean} whether anything has arrived yet
49
69
  */
@@ -1 +1 @@
1
- {"version":3,"file":"RenderPlayout.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/time/RenderPlayout.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;GAeG;AACH;IAsBI;;;;;;OAMG;IACH,oDANW;QACV,cAAkB,EAAE,MAAM,CAAC;QAC3B,KAAS,CAAC,EAAE,mBAAmB,CAAC;QAChC,WAAe,CAAC,EAAE,MAAM,CAAA;KACrB,EAWH;IArCD,+BAA+B;IAC/B,yBADqB,MAAM,CACZ;IAEf,4CAA4C;IAC5C,gBADqB,mBAAmB,CAClC;IAEN,+BAA+B;IAC/B,sBADqB,MAAM,CACf;IAEZ,wEAAwE;IACxE,cADW,MAAM,CACC;IA6BlB;;;;;;;OAOG;IACH,uBAJW,MAAM,gBACN,MAAM,GACJ,OAAO,CAWnB;IAED;;OAEG;IACH,0BAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;;;;;;OAQG;IACH,eAHW,MAAM,GACJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,CAAC,EAAC,MAAM,CAAA;KAAC,CAsDpD;IAED;;OAEG;IACH,cAKC;;CACJ;oCA5KmC,0BAA0B"}
1
+ {"version":3,"file":"RenderPlayout.d.ts","sourceRoot":"","sources":["../../../../../src/engine/network/time/RenderPlayout.js"],"names":[],"mappings":"AAWA;;;;;;;;;;;;;;;;;;;;;;;;;GAyBG;AACH;IAyBI;;;;;;OAMG;IACH,oDANW;QACV,cAAkB,EAAE,MAAM,CAAC;QAC3B,KAAS,CAAC,EAAE,mBAAmB,CAAC;QAChC,WAAe,CAAC,EAAE,MAAM,CAAA;KACrB,EAWH;IAxCD,+BAA+B;IAC/B,yBADqB,MAAM,CACZ;IAEf,4CAA4C;IAC5C,gBADqB,mBAAmB,CAClC;IAEN,+BAA+B;IAC/B,sBADqB,MAAM,CACf;IAEZ,2FAA2F;IAC3F,cADW,MAAM,CACC;IAgClB;;;;;;;;OAQG;IACH,uBAJW,MAAM,gBACN,MAAM,GACJ,OAAO,CASnB;IAED;;;;;;;OAOG;IACH,2BAHW,MAAM,GACJ,OAAO,CAUnB;IAED;;OAEG;IACH,0BAEC;IAED;;;OAGG;IACH,uBAEC;IAED;;;;;;;;OAQG;IACH,eAHW,MAAM,GACJ;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,MAAM,EAAC,MAAM,CAAC;QAAC,CAAC,EAAC,MAAM,CAAA;KAAC,CA2DpD;IAED;;OAEG;IACH,cAMC;;CACJ;oCAhNmC,0BAA0B"}
@@ -20,6 +20,16 @@ const PULL_PER_MS = 0.0005;
20
20
  * arrived. Extracted from `NetworkSession` so any fixed-period stream — a peer's netcode frames, a
21
21
  * remote editor's presence samples — plays out the same way.
22
22
  *
23
+ * The head, `latest_frame`, is the newest frame the sender is known to have reached. A sender that
24
+ * sends nothing for a frame in which nothing changed must still say where it is
25
+ * ({@link advance_head}): otherwise the head stops with the stream, and the first frame after the
26
+ * pause is as far ahead of the playhead as the pause was long.
27
+ *
28
+ * A playhead further behind its target than the delay's largest value has not fallen behind by
29
+ * anything a delay covers — the receiver drew nothing while the sender ran on — and starts again as
30
+ * it did at the first frame: the delay is reset, since the frames that landed across the gap say
31
+ * nothing of how late frames run, and the playhead is put at its target. Anything nearer is pulled.
32
+ *
23
33
  * No allocation per call: {@link window} fills and returns one reused object.
24
34
  *
25
35
  * @author Alex Goldring
@@ -35,9 +45,12 @@ export class RenderPlayout {
35
45
  /** @readonly @type {number} */
36
46
  pull_per_ms;
37
47
 
38
- /** @type {number} highest frame number recorded; -1 before the first */
48
+ /** @type {number} newest frame the sender is known to have reached; -1 before the first */
39
49
  latest_frame = -1;
40
50
 
51
+ /** @private @type {number} newest frame recorded as an arrival; -1 before the first */
52
+ #latest_arrival = -1;
53
+
41
54
  /** @private @type {number} smoothed playhead in frames; -1 until the first window */
42
55
  #smooth_frame = -1;
43
56
 
@@ -66,19 +79,36 @@ export class RenderPlayout {
66
79
  }
67
80
 
68
81
  /**
69
- * A frame from the sender has been applied locally. Frames at or below the latest are
70
- * accepted data (a reordered or retransmitted frame) but do not move the head.
82
+ * A frame from the sender has been applied locally. Its lateness is a sample for the delay,
83
+ * whether or not the head has already passed it. A frame at or below the newest one recorded
84
+ * (a reordered or retransmitted frame) is accepted data, and is no sample.
71
85
  *
72
86
  * @param {number} now_ms wall clock
73
87
  * @param {number} frame_number the sender's frame index
74
88
  * @returns {boolean} true when this frame advanced the head
75
89
  */
76
90
  record_arrival(now_ms, frame_number) {
91
+ if (frame_number > this.#latest_arrival) {
92
+ this.#latest_arrival = frame_number;
93
+ this.delay.record_arrival(now_ms, frame_number);
94
+ }
95
+
96
+ return this.advance_head(frame_number);
97
+ }
98
+
99
+ /**
100
+ * The sender has reached `frame_number`, whatever it sent of it. Moves the head and nothing
101
+ * else: this is the sender's word of where it is, not a frame's arrival, and it is no sample
102
+ * for the delay.
103
+ *
104
+ * @param {number} frame_number the sender's frame index
105
+ * @returns {boolean} true when the head advanced
106
+ */
107
+ advance_head(frame_number) {
77
108
  if (frame_number <= this.latest_frame) {
78
109
  return false;
79
110
  }
80
111
 
81
- this.delay.record_arrival(now_ms, frame_number);
82
112
  this.latest_frame = frame_number;
83
113
 
84
114
  return true;
@@ -140,6 +170,11 @@ export class RenderPlayout {
140
170
  frame += dt_ms / period;
141
171
  const alpha = 1 - Math.exp(-this.pull_per_ms * dt_ms);
142
172
  frame += (target - frame) * alpha;
173
+
174
+ if (target - frame > this.delay.max_delay_frames) {
175
+ this.delay.reset();
176
+ frame = latest - this.delay.delay_ms() / period;
177
+ }
143
178
  }
144
179
 
145
180
  this.#last_wall_ms = now_ms;
@@ -167,6 +202,7 @@ export class RenderPlayout {
167
202
  */
168
203
  reset() {
169
204
  this.latest_frame = -1;
205
+ this.#latest_arrival = -1;
170
206
  this.#smooth_frame = -1;
171
207
  this.#last_wall_ms = -1;
172
208
  this.delay.reset();
@@ -66,11 +66,11 @@ export class FluidObstacleSystem extends System<any> {
66
66
  /**
67
67
  * @param {FluidComponent} fluid
68
68
  */
69
- static "__#490@#refresh_masks"(fluid: FluidComponent): void;
69
+ static "__#497@#refresh_masks"(fluid: FluidComponent): void;
70
70
  /**
71
71
  * @param {FluidComponent} fluid
72
72
  */
73
- static "__#490@#clear_field"(fluid: FluidComponent): void;
73
+ static "__#497@#clear_field"(fluid: FluidComponent): void;
74
74
  /**
75
75
  * Mark every cell of `fluid` whose centre lies within `inflation` of the
76
76
  * posed shape as solid. Iteration is clipped to the shape's world AABB
@@ -82,7 +82,7 @@ export class FluidObstacleSystem extends System<any> {
82
82
  * @param {number} inflation world-units SDF threshold
83
83
  * @param {Float64Array} point length-3 scratch
84
84
  */
85
- static "__#490@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
85
+ static "__#497@#voxelize"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array): void;
86
86
  /**
87
87
  * Write the obstacle's translation velocity onto every face of every cell
88
88
  * it voxelized — the moving-wall boundary condition. Runs AFTER the mask
@@ -102,7 +102,7 @@ export class FluidObstacleSystem extends System<any> {
102
102
  * @param {number} wvy
103
103
  * @param {number} wvz
104
104
  */
105
- static "__#490@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
105
+ static "__#497@#stamp_wall_velocity"(fluid: FluidComponent, posed: PosedShape3D, aabb: Float64Array, inflation: number, point: Float64Array, wvx: number, wvy: number, wvz: number): void;
106
106
  constructor();
107
107
  dependencies: (typeof FluidObstacle)[];
108
108
  components_used: (ResourceAccessSpecification<typeof Transform64> | ResourceAccessSpecification<typeof FluidObstacle> | ResourceAccessSpecification<typeof Collider> | ResourceAccessSpecification<typeof RigidBody> | ResourceAccessSpecification<typeof FluidComponent>)[];
@@ -4,7 +4,11 @@
4
4
  * - `fluid_obstacle_record_signed_distance(record, global, x) -> f32`: signed distance to its
5
5
  * surface, negative inside; the point is solid when it is at most `record.inflation`;
6
6
  * - `fluid_obstacle_record_wall_velocity(record, global, x) -> vec3<f32>`: the wall's velocity there,
7
- * `rigid_velocity_at_point(v, ω, t, x)` with `t` the node's translation.
7
+ * `rigid_velocity_at_point(v, ω, t, x)` with `t` the node's translation;
8
+ * - `fluid_obstacle_record_line_span(record, global, origin, direction) -> vec2<f32>`: the part of the
9
+ * world line `origin + t · direction` (`direction` unit) inside its surface, as the `t` it enters at
10
+ * and the `t` it leaves at, the first greater than the second for a line that misses
11
+ * (`shape_record_line_span`). The inflation is not part of it.
8
12
  *
9
13
  * The node poses the record rigidly: its translation, and its matrix's rotation with each column
10
14
  * normalised, scale ignored, as the physics narrowphase and the CPU fluid pose a collider; then the
@@ -1 +1 @@
1
- {"version":3,"file":"chunk_fluid_obstacle_record.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js"],"names":[],"mappings":"AAMA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,0CAFU,SAAS,CAmCjB;0BAzDwB,yDAAyD"}
1
+ {"version":3,"file":"chunk_fluid_obstacle_record.d.ts","sourceRoot":"","sources":["../../../../../../src/engine/physics/fluid/obstacle/chunk_fluid_obstacle_record.js"],"names":[],"mappings":"AAOA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,0CAFU,SAAS,CAwDjB;0BAlFwB,yDAAyD"}