@woosh/meep-engine 3.20.0 → 3.21.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 (701) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/editor/Editor.d.ts.map +1 -1
  3. package/editor/enableEditor.d.ts.map +1 -1
  4. package/editor/particles/effect/ParticleEffectDocument.d.ts.map +1 -1
  5. package/editor/particles/effect/ParticleReferenceSimulation.d.ts.map +1 -1
  6. package/editor/templates/entity_templates.d.ts.map +1 -1
  7. package/editor/tools/v2/GizmoNode.d.ts +1 -1
  8. package/editor/tools/v2/GizmoNode.d.ts.map +1 -1
  9. package/editor/view/ecs/HierarchicalEntityListView.d.ts +3 -3
  10. package/editor/view/ecs/HierarchicalEntityListView.d.ts.map +1 -1
  11. package/editor/view/makeEntityDecorators.d.ts.map +1 -1
  12. package/editor/view/node-graph/NodeGraphClipboard.d.ts.map +1 -1
  13. package/editor/view/tools/ToolSettingsView.d.ts +1 -1
  14. package/editor/view/tools/ToolSettingsView.d.ts.map +1 -1
  15. package/package.json +12 -12
  16. package/src/core/IdPool.d.ts.map +1 -1
  17. package/src/core/binary/32BitEncoder.d.ts.map +1 -1
  18. package/src/core/binary/BinaryBuffer.d.ts +1 -1
  19. package/src/core/binary/BinaryBuffer.d.ts.map +1 -1
  20. package/src/core/bvh2/binary/2/BinaryUint32BVH.d.ts +1 -1
  21. package/src/core/bvh2/binary/2/BinaryUint32BVH.d.ts.map +1 -1
  22. package/src/core/bvh2/bvh3/BVH.d.ts +3 -3
  23. package/src/core/bvh2/bvh3/BVH.d.ts.map +1 -1
  24. package/src/core/bvh2/bvh3/BVH.js +1 -2
  25. package/src/core/bvh2/bvh3/query/bvh_query_user_data_nearest_to_point_filtered.d.ts.map +1 -1
  26. package/src/core/bvh2/traversal/aabb3_detailed_volume_intersection_callback_based.d.ts.map +1 -1
  27. package/src/core/cache/Cache.d.ts +1 -1
  28. package/src/core/cache/Cache.d.ts.map +1 -1
  29. package/src/core/cache/wtinylfu/CacheWTinylfu.d.ts.map +1 -1
  30. package/src/core/collection/list/List.d.ts.map +1 -1
  31. package/src/core/collection/list/ListForwarder.d.ts +1 -1
  32. package/src/core/collection/list/ListForwarder.d.ts.map +1 -1
  33. package/src/core/collection/map/HashMap.d.ts.map +1 -1
  34. package/src/core/collection/set/ArraySet.d.ts.map +1 -1
  35. package/src/core/collection/table/RowFirstTable.d.ts +1 -1
  36. package/src/core/collection/table/RowFirstTable.d.ts.map +1 -1
  37. package/src/core/collection/table/bind/TableRecord.d.ts +1 -1
  38. package/src/core/collection/table/bind/TableRecord.d.ts.map +1 -1
  39. package/src/core/color/Color.d.ts +8 -8
  40. package/src/core/color/Color.d.ts.map +1 -1
  41. package/src/core/color/hsv/hsv_to_rgb_uint8.d.ts.map +1 -1
  42. package/src/core/color/hsv/rgb_to_hsv.d.ts.map +1 -1
  43. package/src/core/events/signal/Signal.d.ts +1 -1
  44. package/src/core/events/signal/Signal.d.ts.map +1 -1
  45. package/src/core/events/signal/signal_aggregate_by_time_window.d.ts.map +1 -1
  46. package/src/core/fsm/simple/SimpleStateMachineDescription.d.ts.map +1 -1
  47. package/src/core/geom/2d/aabb/AABB2.d.ts +4 -4
  48. package/src/core/geom/2d/aabb/AABB2.d.ts.map +1 -1
  49. package/src/core/geom/2d/bvh/BVH2D.d.ts +1 -1
  50. package/src/core/geom/2d/bvh/BVH2D.d.ts.map +1 -1
  51. package/src/core/geom/2d/triangle/tri2_rasterize_conservative.d.ts.map +1 -1
  52. package/src/core/geom/3d/aabb/AABB3.d.ts +6 -6
  53. package/src/core/geom/3d/aabb/AABB3.d.ts.map +1 -1
  54. package/src/core/geom/3d/atlas/atlas_bench_lib.d.ts.map +1 -1
  55. package/src/core/geom/3d/atlas/atlas_compute_charts.d.ts.map +1 -1
  56. package/src/core/geom/3d/atlas/atlas_generate.d.ts.map +1 -1
  57. package/src/core/geom/3d/atlas/pack/atlas_pack_charts.d.ts.map +1 -1
  58. package/src/core/geom/3d/atlas/param/atlas_chart_param_validity.d.ts.map +1 -1
  59. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_bff.d.ts.map +1 -1
  60. package/src/core/geom/3d/atlas/param/atlas_chart_parameterize_lscm.d.ts.map +1 -1
  61. package/src/core/geom/3d/atlas/segment/atlas_compute_planar_regions.d.ts.map +1 -1
  62. package/src/core/geom/3d/atlas/segment/atlas_segment_charts.d.ts.map +1 -1
  63. package/src/core/geom/3d/atlas/segment/atlas_segment_charts_atomic.d.ts.map +1 -1
  64. package/src/core/geom/3d/mat4/m4_decompose.d.ts +7 -1
  65. package/src/core/geom/3d/mat4/m4_decompose.d.ts.map +1 -1
  66. package/src/core/geom/3d/quadric/Quadric3.d.ts +11 -11
  67. package/src/core/geom/3d/quadric/Quadric3.d.ts.map +1 -1
  68. package/src/core/geom/3d/ray/Ray3.d.ts +3 -3
  69. package/src/core/geom/3d/ray/Ray3.d.ts.map +1 -1
  70. package/src/core/geom/3d/shape/TransformedShape3D.d.ts +1 -1
  71. package/src/core/geom/3d/shape/TransformedShape3D.d.ts.map +1 -1
  72. package/src/core/geom/3d/tetrahedra/TetrahedralMesh.d.ts.map +1 -1
  73. package/src/core/geom/3d/tetrahedra/delaunay/debug/push_boundary_with_validation.d.ts.map +1 -1
  74. package/src/core/geom/3d/tetrahedra/delaunay/debug/validate_cavity_boundary.d.ts.map +1 -1
  75. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_carve_outside_surface.d.ts.map +1 -1
  76. package/src/core/geom/3d/tetrahedra/tetrahedral_mesh_improve_quality.d.ts.map +1 -1
  77. package/src/core/geom/3d/tetrahedra/validate_tetrahedral_mesh.d.ts.map +1 -1
  78. package/src/core/geom/3d/tetrahedra/validate_tetrahedron_neighbourhood.d.ts.map +1 -1
  79. package/src/core/geom/3d/topology/struct/binary/io/bt_mesh_to_indexed_geometry.d.ts.map +1 -1
  80. package/src/core/geom/3d/util/aabb3_emit_point_grid.d.ts.map +1 -1
  81. package/src/core/geom/Quaternion.d.ts +4 -4
  82. package/src/core/geom/Quaternion.d.ts.map +1 -1
  83. package/src/core/geom/Vector1.d.ts +1 -1
  84. package/src/core/geom/Vector1.d.ts.map +1 -1
  85. package/src/core/geom/Vector2.d.ts +2 -2
  86. package/src/core/geom/Vector2.d.ts.map +1 -1
  87. package/src/core/geom/Vector3.d.ts +3 -3
  88. package/src/core/geom/Vector3.d.ts.map +1 -1
  89. package/src/core/geom/Vector4.d.ts +4 -4
  90. package/src/core/geom/Vector4.d.ts.map +1 -1
  91. package/src/core/geom/packing/max-rect/find_best_container.d.ts.map +1 -1
  92. package/src/core/geom/vec3/v3_hash.d.ts +12 -0
  93. package/src/core/geom/vec3/v3_hash.d.ts.map +1 -0
  94. package/src/core/geom/vec3/v3_hash.js +19 -0
  95. package/src/core/geom/vec3/v3_lerp.d.ts +3 -1
  96. package/src/core/geom/vec3/v3_lerp.d.ts.map +1 -1
  97. package/src/core/geom/vec3/v3_set.d.ts +14 -0
  98. package/src/core/geom/vec3/v3_set.d.ts.map +1 -0
  99. package/src/core/geom/vec3/v3_set.js +17 -0
  100. package/src/core/geom/vec3/v3_slerp.d.ts +3 -1
  101. package/src/core/geom/vec3/v3_slerp.d.ts.map +1 -1
  102. package/src/core/geom/vec4/v4_equals_array.d.ts +11 -0
  103. package/src/core/geom/vec4/v4_equals_array.d.ts.map +1 -0
  104. package/src/core/geom/vec4/v4_equals_array.js +16 -0
  105. package/src/core/geom/vec4/v4_hash.d.ts +12 -0
  106. package/src/core/geom/vec4/v4_hash.d.ts.map +1 -0
  107. package/src/core/geom/vec4/v4_hash.js +18 -0
  108. package/src/core/geom/vec4/v4_set.d.ts +15 -0
  109. package/src/core/geom/vec4/v4_set.d.ts.map +1 -0
  110. package/src/core/geom/vec4/v4_set.js +19 -0
  111. package/src/core/graph/convert_graph_to_dot_string.d.ts +1 -1
  112. package/src/core/graph/convert_graph_to_dot_string.d.ts.map +1 -1
  113. package/src/core/graph/metis/native/bisection/split_graph_two_way.d.ts.map +1 -1
  114. package/src/core/graph/metis/native/metis_partition_kway.d.ts.map +1 -1
  115. package/src/core/graph/metis/native/refine/fm_kway.d.ts.map +1 -1
  116. package/src/core/json/abstractJSONSerializer.d.ts.map +1 -1
  117. package/src/core/lang/reactive/AbstractCachingParser.d.ts.map +1 -1
  118. package/src/core/localization/Localization.d.ts.map +1 -1
  119. package/src/core/math/linalg/cg/cg_solve.d.ts.map +1 -1
  120. package/src/core/math/noise/create_simplex_noise_2d.d.ts.map +1 -1
  121. package/src/core/math/physics/mie/compute_bhmie_optical_properties.d.ts.map +1 -1
  122. package/src/core/math/physics/mie/compute_mie_particle_properties_rgb.d.ts.map +1 -1
  123. package/src/core/math/random/seededRandom_Mulberry32.d.ts +1 -1
  124. package/src/core/math/random/seededRandom_Mulberry32.d.ts.map +1 -1
  125. package/src/core/model/ModuleRegistry.d.ts.map +1 -1
  126. package/src/core/model/node-graph/visual/layout/layout_assign_coordinates.d.ts.map +1 -1
  127. package/src/core/model/node-graph/visual/layout/layout_node_graph.d.ts.map +1 -1
  128. package/src/core/model/node-graph/visual/layout/layout_order_layers.d.ts.map +1 -1
  129. package/src/core/model/reactive/model/ReactiveExpression.d.ts.map +1 -1
  130. package/src/core/model/validate_enum_schema.d.ts.map +1 -1
  131. package/src/core/process/Future.d.ts.map +1 -1
  132. package/src/core/process/task/Task.d.ts.map +1 -1
  133. package/src/core/process/task/util/countTask.d.ts.map +1 -1
  134. package/src/core/process/task/util/randomCountTask.d.ts.map +1 -1
  135. package/src/core/process/worker/WorkerBuilder.d.ts.map +1 -1
  136. package/src/engine/Clock.d.ts +1 -1
  137. package/src/engine/Clock.d.ts.map +1 -1
  138. package/src/engine/EngineHarness.d.ts.map +1 -1
  139. package/src/engine/animation/Animations.d.ts.map +1 -1
  140. package/src/engine/animation/EntityAnimation.d.ts.map +1 -1
  141. package/src/engine/animation/TransitionFunctions.d.ts.map +1 -1
  142. package/src/engine/animation/Tween.d.ts.map +1 -1
  143. package/src/engine/animation/curve/editor/uploadViaElement.d.ts.map +1 -1
  144. package/src/engine/animation/curve/view/AnimationCurveView.d.ts +1 -1
  145. package/src/engine/animation/curve/view/AnimationCurveView.d.ts.map +1 -1
  146. package/src/engine/asset/AssetManager.d.ts.map +1 -1
  147. package/src/engine/asset/AssetRequest.d.ts.map +1 -1
  148. package/src/engine/asset/loaders/AssetLoader.d.ts.map +1 -1
  149. package/src/engine/asset/loaders/image/avif/encode_image_source.d.ts.map +1 -1
  150. package/src/engine/asset/loaders/image/avif/threaded_image_encoder.d.ts.map +1 -1
  151. package/src/engine/browserInfo.d.ts.map +1 -1
  152. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts +1 -1
  153. package/src/engine/control/first-person/FirstPersonPlayerControllerSystem.d.ts.map +1 -1
  154. package/src/engine/control/first-person/abilities/LedgeGrab.js +9 -9
  155. package/src/engine/control/first-person/abilities/Mantle.js +8 -8
  156. package/src/engine/control/first-person/abilities/ScrambleUp.js +2 -2
  157. package/src/engine/control/first-person/abilities/WallJump.js +2 -2
  158. package/src/engine/control/first-person/abilities/WallRun.js +3 -3
  159. package/src/engine/control/first-person/collision/KinematicMover.d.ts +1 -1
  160. package/src/engine/control/first-person/collision/KinematicMover.d.ts.map +1 -1
  161. package/src/engine/control/first-person/collision/KinematicMover.js +19 -46
  162. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts +17 -5
  163. package/src/engine/control/first-person/sensors/FirstPersonSensors.d.ts.map +1 -1
  164. package/src/engine/control/first-person/sensors/FirstPersonSensors.js +20 -7
  165. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.d.ts.map +1 -1
  166. package/src/engine/control/first-person/sensors/FirstPersonSensorsSystem.js +9 -8
  167. package/src/engine/control/first-person/test/buildTestPlayer.d.ts.map +1 -1
  168. package/src/engine/ecs/EntityComponentDataset.d.ts.map +1 -1
  169. package/src/engine/ecs/EntityManager.d.ts.map +1 -1
  170. package/src/engine/ecs/EntityObserver.d.ts.map +1 -1
  171. package/src/engine/ecs/System.d.ts.map +1 -1
  172. package/src/engine/ecs/animation/Animation.d.ts +1 -1
  173. package/src/engine/ecs/animation/Animation.d.ts.map +1 -1
  174. package/src/engine/ecs/async/SystemWorkerLoopback.d.ts +3 -3
  175. package/src/engine/ecs/async/SystemWorkerLoopback.d.ts.map +1 -1
  176. package/src/engine/ecs/dynamic_actions/DynamicActorSystem.d.ts.map +1 -1
  177. package/src/engine/ecs/grid/pick.d.ts.map +1 -1
  178. package/src/engine/ecs/guid/UUID.d.ts +1 -1
  179. package/src/engine/ecs/guid/UUID.d.ts.map +1 -1
  180. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.d.ts.map +1 -1
  181. package/src/engine/ecs/ik/OneBoneSurfaceAlignmentSolver.js +26 -9
  182. package/src/engine/ecs/parent/EntityNode.d.ts +1 -1
  183. package/src/engine/ecs/parent/EntityNode.d.ts.map +1 -1
  184. package/src/engine/ecs/parent/FaceEditor.d.ts +7 -7
  185. package/src/engine/ecs/parent/FaceEditor.d.ts.map +1 -1
  186. package/src/engine/ecs/storage/binary/collection/BinaryCollectionDeSerializer.d.ts.map +1 -1
  187. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.d.ts +2 -2
  188. package/src/engine/ecs/storage/binary/object/BinaryObjectSerializationAdapter2.d.ts.map +1 -1
  189. package/src/engine/ecs/terrain/TerrainClouds.d.ts +1 -1
  190. package/src/engine/ecs/terrain/ecs/Terrain.d.ts +1 -1
  191. package/src/engine/ecs/terrain/ecs/Terrain.d.ts.map +1 -1
  192. package/src/engine/ecs/terrain/ecs/TerrainSystem.d.ts.map +1 -1
  193. package/src/engine/ecs/terrain/overlay/TerrainOverlay.d.ts +1 -1
  194. package/src/engine/ecs/terrain/overlay/TerrainOverlay.d.ts.map +1 -1
  195. package/src/engine/ecs/terrain/tiles/TerrainTile.d.ts +1 -1
  196. package/src/engine/ecs/terrain/tiles/TerrainTile.d.ts.map +1 -1
  197. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts +1 -1
  198. package/src/engine/ecs/terrain/tiles/TerrainTileManager.d.ts.map +1 -1
  199. package/src/engine/ecs/terrain/util/obtainTerrain.d.ts.map +1 -1
  200. package/src/engine/ecs/transform/Transform64.d.ts +6 -6
  201. package/src/engine/ecs/transform/Transform64.d.ts.map +1 -1
  202. package/src/engine/ecs/transform-attachment/TransformAttachment.d.ts +1 -1
  203. package/src/engine/ecs/transform-attachment/TransformAttachment.d.ts.map +1 -1
  204. package/src/engine/graphics/FrameRunner.d.ts.map +1 -1
  205. package/src/engine/graphics/ecs/camera/camera_traverse_active.d.ts.map +1 -1
  206. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.d.ts +1 -1
  207. package/src/engine/graphics/ecs/camera/pp/PerfectPanner.d.ts.map +1 -1
  208. package/src/engine/graphics/ecs/highlight/HighlightDefinition.d.ts +1 -1
  209. package/src/engine/graphics/ecs/highlight/HighlightDefinition.d.ts.map +1 -1
  210. package/src/engine/graphics/ecs/make_bvh_depth_range_computer.d.ts.map +1 -1
  211. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.d.ts +4 -4
  212. package/src/engine/graphics/ecs/mesh-v2/aggregate/SGMesh.d.ts.map +1 -1
  213. package/src/engine/graphics/ecs/path/tube/TubePathStyle.d.ts +1 -1
  214. package/src/engine/graphics/ecs/path/tube/TubePathStyle.d.ts.map +1 -1
  215. package/src/engine/graphics/ecs/path/tube/build/computeFrenetFrames.d.ts.map +1 -1
  216. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts +3 -3
  217. package/src/engine/graphics/ecs/trail3d/Trail3D.d.ts.map +1 -1
  218. package/src/engine/graphics/geometry/buffered/build_height_field_geometry.d.ts +1 -1
  219. package/src/engine/graphics/geometry/buffered/build_height_field_geometry.d.ts.map +1 -1
  220. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts +1 -1
  221. package/src/engine/graphics/geometry/buffered/query/GeometrySpatialQueryAccelerator.d.ts.map +1 -1
  222. package/src/engine/graphics/make_ray_from_viewport_position.d.ts.map +1 -1
  223. package/src/engine/graphics/particles/particular/engine/emitter/ParticleEmitter.d.ts.map +1 -1
  224. package/src/engine/graphics/particles/particular/engine/emitter/computeEmissionFunction.d.ts.map +1 -1
  225. package/src/engine/graphics/particles/particular/engine/utils/distribute_points_on_indexed_triangles.d.ts.map +1 -1
  226. package/src/engine/graphics/particles/particular/engine/utils/distrubuteParticlesOnMesh.d.ts.map +1 -1
  227. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.d.ts +3 -3
  228. package/src/engine/graphics/particles/particular/engine/utils/volume/AttributeValue.d.ts.map +1 -1
  229. package/src/engine/graphics/render/frame_graph/FrameGraph.d.ts.map +1 -1
  230. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.d.ts +1 -1
  231. package/src/engine/graphics/render/gizmo/GizmoShapeRenderingInterface.d.ts.map +1 -1
  232. package/src/engine/graphics/render/layers/RenderLayer.d.ts +3 -3
  233. package/src/engine/graphics/render/layers/RenderLayer.d.ts.map +1 -1
  234. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts +1 -1
  235. package/src/engine/graphics/render/visibility/IncrementalDeltaSet.d.ts.map +1 -1
  236. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts +2 -2
  237. package/src/engine/graphics/render/visibility/VisibilityComputer.d.ts.map +1 -1
  238. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.d.ts +1 -1
  239. package/src/engine/graphics/sh3/path_tracer/PathTracedMesh.d.ts.map +1 -1
  240. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.d.ts.map +1 -1
  241. package/src/engine/graphics/sh3/path_tracer/populate_path_traced_scene_from_ecd.js +5 -1
  242. package/src/engine/graphics/texture/3d/SingleChannelSampler3D.d.ts +1 -1
  243. package/src/engine/graphics/texture/3d/SingleChannelSampler3D.d.ts.map +1 -1
  244. package/src/engine/graphics/texture/sampler/Sampler2D.d.ts.map +1 -1
  245. package/src/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.d.ts +1 -1
  246. package/src/engine/graphics/texture/sampler/filter/sampler2d_scale_down_generic.d.ts.map +1 -1
  247. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_max.d.ts +1 -1
  248. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_max.d.ts.map +1 -1
  249. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min.d.ts +1 -1
  250. package/src/engine/graphics/texture/sampler/sampler2d_channel_compute_min.d.ts.map +1 -1
  251. package/src/engine/graphics/texture/sampler/sampler2d_combine.d.ts.map +1 -1
  252. package/src/engine/graphics/texture/sampler/sampler2d_compute_texel_value_conversion_scale_to_uint8.d.ts.map +1 -1
  253. package/src/engine/graphics/texture/sampler/search/make_edge_condition_channel_threshold.d.ts.map +1 -1
  254. package/src/engine/graphics/texture/sampler/search/sampler2d_find_pixels.d.ts.map +1 -1
  255. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts +3 -3
  256. package/src/engine/graphics/texture/virtual/VirtualTextureTileLoader.d.ts.map +1 -1
  257. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts +1 -1
  258. package/src/engine/graphics/texture/virtual/VirtualTextureUsage.d.ts.map +1 -1
  259. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts +2 -2
  260. package/src/engine/graphics/texture/virtual/debug/UsageDebugView.d.ts.map +1 -1
  261. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts +1 -1
  262. package/src/engine/graphics/texture/virtual/debug/UsagePyramidDebugView.d.ts.map +1 -1
  263. package/src/engine/graphics/texture/virtual/tile/decompose_finger_print.d.ts.map +1 -1
  264. package/src/engine/graphics3/HighlightOutlineSystem.d.ts.map +1 -1
  265. package/src/engine/graphics3/ParticipatingMedia.d.ts +1 -1
  266. package/src/engine/graphics3/ParticipatingMedia.d.ts.map +1 -1
  267. package/src/engine/graphics3/VolumetricLightMap.d.ts +1 -1
  268. package/src/engine/graphics3/VolumetricLightMap.d.ts.map +1 -1
  269. package/src/engine/graphics3/decal/graph_build_decal_clusters.d.ts.map +1 -1
  270. package/src/engine/graphics3/highlight/pack_highlight_table.d.ts.map +1 -1
  271. package/src/engine/graphics3/preview/make_model_preview_scene.d.ts.map +1 -1
  272. package/src/engine/graphics3/terrain/GPUTerrainSplatRenderer.d.ts.map +1 -1
  273. package/src/engine/graphics3/terrain/pack_terrain_row_table.d.ts.map +1 -1
  274. package/src/engine/grid/obstacle/GridObstacle.d.ts.map +1 -1
  275. package/src/engine/input/devices/GamepadDevice.d.ts +1 -1
  276. package/src/engine/input/devices/GamepadDevice.d.ts.map +1 -1
  277. package/src/engine/input/devices/PointerDevice.d.ts +1 -1
  278. package/src/engine/input/devices/PointerDevice.d.ts.map +1 -1
  279. package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
  280. package/src/engine/input/ecs/controllers/KeyboardCameraController.js +11 -2
  281. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts +1 -1
  282. package/src/engine/intelligence/behavior/ecs/BehaviorComponent.d.ts.map +1 -1
  283. package/src/engine/intelligence/behavior/ecs/SendEventBehavior.d.ts.map +1 -1
  284. package/src/engine/intelligence/behavior/primitive/ActionBehavior.d.ts.map +1 -1
  285. package/src/engine/intelligence/behavior/util/RotationBehavior.d.ts.map +1 -1
  286. package/src/engine/intelligence/behavior/util/RotationBehavior.js +14 -2
  287. package/src/engine/intelligence/blackboard/Blackboard.d.ts.map +1 -1
  288. package/src/engine/intelligence/mcts/MonteCarlo.d.ts +1 -1
  289. package/src/engine/intelligence/mcts/MonteCarlo.d.ts.map +1 -1
  290. package/src/engine/intelligence/mcts/StateNode.d.ts.map +1 -1
  291. package/src/engine/intelligence/optimization/RandomOptimizer.d.ts +1 -1
  292. package/src/engine/intelligence/optimization/RandomOptimizer.d.ts.map +1 -1
  293. package/src/engine/knowledge/database/StaticKnowledgeDataTable.d.ts.map +1 -1
  294. package/src/engine/knowledge/database/StaticKnowledgeDatabase.d.ts +1 -1
  295. package/src/engine/knowledge/database/StaticKnowledgeDatabase.d.ts.map +1 -1
  296. package/src/engine/navigation/ecs/path_following/PathFollower.d.ts +2 -2
  297. package/src/engine/navigation/ecs/path_following/PathFollower.d.ts.map +1 -1
  298. package/src/engine/network/NetworkSession.d.ts.map +1 -1
  299. package/src/engine/network/PriorityFetch.d.ts +2 -2
  300. package/src/engine/network/PriorityFetch.d.ts.map +1 -1
  301. package/src/engine/network/diagnostics/BandwidthMeter.d.ts.map +1 -1
  302. package/src/engine/network/ecs/owner_authorization.d.ts.map +1 -1
  303. package/src/engine/network/orchestrator/NetworkPeer.d.ts.map +1 -1
  304. package/src/engine/network/orchestrator/ServerAuthoritativeServer.d.ts.map +1 -1
  305. package/src/engine/network/replication/Replicator.d.ts +1 -1
  306. package/src/engine/network/replication/Replicator.d.ts.map +1 -1
  307. package/src/engine/network/sim/SimActionExecutor.d.ts +1 -1
  308. package/src/engine/network/sim/SimActionExecutor.d.ts.map +1 -1
  309. package/src/engine/network/time/RenderPlayout.d.ts.map +1 -1
  310. package/src/engine/network/transport/Channel.d.ts.map +1 -1
  311. package/src/engine/network/transport/fragments/FragmentRetention.d.ts.map +1 -1
  312. package/src/engine/physics/body/SolverBodyState.d.ts +11 -11
  313. package/src/engine/physics/body/SolverBodyState.d.ts.map +1 -1
  314. package/src/engine/physics/body/SolverBodyState.js +13 -13
  315. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts +4 -4
  316. package/src/engine/physics/broadphase/compute_fat_world_aabb.d.ts.map +1 -1
  317. package/src/engine/physics/broadphase/compute_fat_world_aabb.js +2 -2
  318. package/src/engine/physics/broadphase/generate_pairs.d.ts +3 -3
  319. package/src/engine/physics/broadphase/generate_pairs.d.ts.map +1 -1
  320. package/src/engine/physics/broadphase/generate_pairs.js +1 -1
  321. package/src/engine/physics/ccd/linear_sweep.d.ts +2 -3
  322. package/src/engine/physics/ccd/linear_sweep.d.ts.map +1 -1
  323. package/src/engine/physics/ccd/linear_sweep.js +4 -5
  324. package/src/engine/physics/constraint/solve_constraints.js +3 -3
  325. package/src/engine/physics/ecs/BodyKind.d.ts +1 -1
  326. package/src/engine/physics/ecs/BodyKind.js +1 -1
  327. package/src/engine/physics/ecs/Collider.d.ts +1 -1
  328. package/src/engine/physics/ecs/Collider.js +1 -1
  329. package/src/engine/physics/ecs/Joint.d.ts +15 -10
  330. package/src/engine/physics/ecs/Joint.d.ts.map +1 -1
  331. package/src/engine/physics/ecs/Joint.js +27 -18
  332. package/src/engine/physics/ecs/JointSerializationAdapter.d.ts.map +1 -1
  333. package/src/engine/physics/ecs/JointSerializationAdapter.js +8 -6
  334. package/src/engine/physics/ecs/PhysicsSystem.d.ts +40 -77
  335. package/src/engine/physics/ecs/PhysicsSystem.d.ts.map +1 -1
  336. package/src/engine/physics/ecs/PhysicsSystem.js +113 -75
  337. package/src/engine/physics/ecs/RigidBody.d.ts +17 -12
  338. package/src/engine/physics/ecs/RigidBody.d.ts.map +1 -1
  339. package/src/engine/physics/ecs/RigidBody.js +58 -24
  340. package/src/engine/physics/ecs/RigidBodySerializationAdapter.d.ts.map +1 -1
  341. package/src/engine/physics/ecs/RigidBodySerializationAdapter.js +13 -12
  342. package/src/engine/physics/ecs/find_non_finite_physics_state.d.ts +1 -1
  343. package/src/engine/physics/ecs/find_non_finite_physics_state.js +1 -1
  344. package/src/engine/physics/fluid/FluidField.d.ts.map +1 -1
  345. package/src/engine/physics/fluid/REVIEW_02_PLAN.md +4 -4
  346. package/src/engine/physics/fluid/SliceVisualiser.d.ts.map +1 -1
  347. package/src/engine/physics/fluid/ecs/FluidComponent.d.ts +10 -10
  348. package/src/engine/physics/fluid/ecs/FluidComponent.js +10 -10
  349. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.d.ts +2 -2
  350. package/src/engine/physics/fluid/ecs/FluidEffectorsComponent.js +2 -2
  351. package/src/engine/physics/fluid/ecs/FluidObstacle.d.ts +3 -3
  352. package/src/engine/physics/fluid/ecs/FluidObstacle.js +3 -3
  353. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +1 -1
  354. package/src/engine/physics/fluid/ecs/FluidObstacleSystem.js +4 -4
  355. package/src/engine/physics/fluid/ecs/FluidSystem.d.ts +2 -2
  356. package/src/engine/physics/fluid/ecs/FluidSystem.js +3 -3
  357. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.d.ts +1 -1
  358. package/src/engine/physics/fluid/ecs/WorkerFluidSystem.js +2 -2
  359. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.d.ts +3 -3
  360. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.d.ts.map +1 -1
  361. package/src/engine/physics/fluid/ecs/fluid_reanchor_field.js +3 -3
  362. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.d.ts +3 -3
  363. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.d.ts.map +1 -1
  364. package/src/engine/physics/fluid/ecs/fluid_sync_effectors_from_transform.js +2 -2
  365. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts +3 -3
  366. package/src/engine/physics/fluid/effector/AbstractFluidEffector.d.ts.map +1 -1
  367. package/src/engine/physics/fluid/effector/AbstractFluidEffector.js +2 -2
  368. package/src/engine/physics/fluid/effector/ImpulseFluidEffector.js +2 -2
  369. package/src/engine/physics/fluid/effector/WakeFluidEffector.d.ts +4 -4
  370. package/src/engine/physics/fluid/effector/WakeFluidEffector.js +8 -8
  371. package/src/engine/physics/inertia/world_inverse_inertia.d.ts +8 -17
  372. package/src/engine/physics/inertia/world_inverse_inertia.d.ts.map +1 -1
  373. package/src/engine/physics/inertia/world_inverse_inertia.js +11 -11
  374. package/src/engine/physics/integration/integrate_position.d.ts +6 -7
  375. package/src/engine/physics/integration/integrate_position.d.ts.map +1 -1
  376. package/src/engine/physics/integration/integrate_position.js +5 -6
  377. package/src/engine/physics/integration/integrate_velocity.d.ts +4 -4
  378. package/src/engine/physics/integration/integrate_velocity.d.ts.map +1 -1
  379. package/src/engine/physics/integration/integrate_velocity.js +7 -7
  380. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.d.ts +4 -4
  381. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.d.ts.map +1 -1
  382. package/src/engine/physics/inverse_kinematics/fabrik/fabrik_solve.js +3 -3
  383. package/src/engine/physics/narrowphase/convex_decomposition.d.ts.map +1 -1
  384. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts +1 -2
  385. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.d.ts.map +1 -1
  386. package/src/engine/physics/narrowphase/decomposition/triangle_buffer_layout.js +1 -2
  387. package/src/engine/physics/narrowphase/narrowphase_step.d.ts +7 -6
  388. package/src/engine/physics/narrowphase/narrowphase_step.d.ts.map +1 -1
  389. package/src/engine/physics/narrowphase/narrowphase_step.js +8 -8
  390. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts +10 -5
  391. package/src/engine/physics/queries/PhysicsSurfacePoint.d.ts.map +1 -1
  392. package/src/engine/physics/queries/PhysicsSurfacePoint.js +10 -6
  393. package/src/engine/physics/queries/overlap_shape.d.ts +5 -14
  394. package/src/engine/physics/queries/overlap_shape.d.ts.map +1 -1
  395. package/src/engine/physics/queries/overlap_shape.js +4 -4
  396. package/src/engine/physics/queries/raycast.d.ts.map +1 -1
  397. package/src/engine/physics/queries/shape_cast.d.ts +9 -1
  398. package/src/engine/physics/queries/shape_cast.d.ts.map +1 -1
  399. package/src/engine/physics/queries/shape_cast.js +2 -2
  400. package/src/engine/physics/solver/solve_contacts.d.ts +2 -2
  401. package/src/engine/physics/solver/solve_contacts.d.ts.map +1 -1
  402. package/src/engine/physics/solver/solve_contacts.js +2 -2
  403. package/src/engine/physics/vehicle/RaycastVehicle.d.ts +4 -8
  404. package/src/engine/physics/vehicle/RaycastVehicle.d.ts.map +1 -1
  405. package/src/engine/physics/vehicle/RaycastVehicle.js +16 -12
  406. package/src/engine/save/Storage.d.ts.map +1 -1
  407. package/src/engine/sound/SoundEngine.d.ts +1 -1
  408. package/src/engine/sound/SoundEngine.d.ts.map +1 -1
  409. package/src/engine/sound/ecs/audio/AudioEmitterSystem.d.ts.map +1 -1
  410. package/src/engine/sound/ecs/audio/AudioEmitterSystem.js +27 -2
  411. package/src/engine/sound/simulation/AcousticSimulator.d.ts +2 -2
  412. package/src/engine/sound/simulation/AcousticSimulator.d.ts.map +1 -1
  413. package/src/engine/sound/simulation/core/VolumeField.d.ts +1 -1
  414. package/src/engine/sound/simulation/core/VolumeField.d.ts.map +1 -1
  415. package/src/engine/sound/simulation/probe/AcousticProbeField.d.ts.map +1 -1
  416. package/src/engine/sound/simulation/probe/probe_delaunay_edges.d.ts.map +1 -1
  417. package/src/engine/sound/simulation/probe/probe_densify_portals.d.ts.map +1 -1
  418. package/src/engine/sound/simulation/probe/probe_detect_portals.d.ts.map +1 -1
  419. package/src/engine/sound/simulation/probe/probe_place_sdf_cover.d.ts.map +1 -1
  420. package/src/engine/sound/simulation/probe/probe_refine_connectivity.d.ts.map +1 -1
  421. package/src/engine/sound/simulation/render/ProbeReverbRenderer.d.ts +1 -1
  422. package/src/engine/sound/simulation/render/ProbeReverbRenderer.d.ts.map +1 -1
  423. package/src/engine/sound/simulation/render/foaReverbImpulseResponse.d.ts.map +1 -1
  424. package/src/engine/sound/sopra/SopraEngine.d.ts.map +1 -1
  425. package/src/engine/sound/sopra/legacy/SoundEmitter.d.ts +3 -3
  426. package/src/engine/sound/sopra/legacy/SoundEmitter.d.ts.map +1 -1
  427. package/src/engine/sound/sopra/legacy/SoundTrack.d.ts +3 -3
  428. package/src/engine/sound/sopra/legacy/SoundTrack.d.ts.map +1 -1
  429. package/src/engine/sound/sopra/util/buildAttenuationCurve.d.ts.map +1 -1
  430. package/src/engine/ui/notification/NotificationManager.d.ts.map +1 -1
  431. package/src/engine/ui/notification/ViewEmitter.d.ts +1 -1
  432. package/src/engine/ui/notification/ViewEmitter.d.ts.map +1 -1
  433. package/src/engine/ui/tiles2d/TileGrid.d.ts.map +1 -1
  434. package/src/extractName.d.ts.map +1 -1
  435. package/src/format/image/avif/api/convert_to_rgba.d.ts.map +1 -1
  436. package/src/format/image/avif/av1/encode/encode_av1_still.d.ts.map +1 -1
  437. package/src/format/image/avif/heif/write_avif_file.d.ts +2 -2
  438. package/src/format/image/avif/heif/write_avif_file.d.ts.map +1 -1
  439. package/src/format/image/jpeg/JpegImage.d.ts.map +1 -1
  440. package/src/format/image/png/PNG.d.ts.map +1 -1
  441. package/src/format/image/png/chunk/png_chunk_decode_iTXt.d.ts.map +1 -1
  442. package/src/format/image/png/chunk/png_chunk_decode_zTXt.d.ts.map +1 -1
  443. package/src/format/scene/gltf/ext/GltfBufferViewExtensionSet.d.ts.map +1 -1
  444. package/src/format/scene/gltf/gltf_node_world_matrices.d.ts.map +1 -1
  445. package/src/format/scene/usd/unpack_usdz.d.ts.map +1 -1
  446. package/src/format/scene/usd/usd_triangulate.d.ts.map +1 -1
  447. package/src/format/texture/basis/astc_integer_sequence.d.ts.map +1 -1
  448. package/src/generation/grid/actions/ContinuousGridCellActionWriteObstacle.d.ts.map +1 -1
  449. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.d.ts.map +1 -1
  450. package/src/generation/markers/actions/placement/MarkerNodeEntityProcessorClingToTerrain.js +22 -3
  451. package/src/generation/markers/transform/MarkerNodeTransformerRecordPropertyClosure.d.ts.map +1 -1
  452. package/src/generation/theme/ThemeEngine.d.ts +2 -2
  453. package/src/generation/theme/ThemeEngine.d.ts.map +1 -1
  454. package/src/shade/descriptor/ObjectDescriptorBase.d.ts +1 -1
  455. package/src/shade/descriptor/ObjectDescriptorBase.d.ts.map +1 -1
  456. package/src/shade/descriptor/texture/TextureDescriptor.d.ts +1 -1
  457. package/src/shade/device/ShadeGPUCommandContext.d.ts +1 -1
  458. package/src/shade/device/ShadeGPUCommandContext.d.ts.map +1 -1
  459. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts +1 -1
  460. package/src/shade/device/pass/ShadeGPUComputePassEncoder.d.ts.map +1 -1
  461. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts +1 -1
  462. package/src/shade/device/pass/ShadeGPURenderPassEncoder.d.ts.map +1 -1
  463. package/src/shade/device/timing/GPUTimerArray.d.ts.map +1 -1
  464. package/src/shade/device/timing/GPUTimerStats.d.ts +1 -1
  465. package/src/shade/device/timing/GPUTimerStats.d.ts.map +1 -1
  466. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +894 -894
  467. package/src/shade/playground/basis_textures/texture_inventory.d.ts.map +1 -1
  468. package/src/shade/playground/bvh_repro/bvh_repro_device.d.ts.map +1 -1
  469. package/src/shade/playground/ground_seam/capture_scene_color.d.ts.map +1 -1
  470. package/src/shade/playground/ground_seam/measure_flicker.d.ts.map +1 -1
  471. package/src/shade/playground/particle_system/index.html +0 -1
  472. package/src/shade/playground/particle_system/main.js +1 -2
  473. package/src/shade/playground/particle_system/particle_prototype.d.ts.map +1 -1
  474. package/src/shade/playground/particle_system/particle_scene.d.ts +5 -6
  475. package/src/shade/playground/particle_system/particle_scene.d.ts.map +1 -1
  476. package/src/shade/playground/particle_system/particle_scene.js +6 -7
  477. package/src/shade/playground/skinned_blas_refit/sweep_views.js +2 -2
  478. package/src/shade/playground/skinned_blas_refit/verify_traversal_reachability.js +1 -1
  479. package/src/shade/playground/vgeo_viewer/README.md +123 -0
  480. package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts +61 -0
  481. package/src/shade/playground/vgeo_viewer/cut_geometry.d.ts.map +1 -0
  482. package/src/shade/playground/vgeo_viewer/cut_geometry.js +497 -0
  483. package/src/shade/playground/vgeo_viewer/index.html +77 -0
  484. package/src/shade/playground/vgeo_viewer/main.d.ts +2 -0
  485. package/src/shade/playground/vgeo_viewer/main.d.ts.map +1 -0
  486. package/src/shade/playground/vgeo_viewer/main.js +1288 -0
  487. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts +18 -0
  488. package/src/shade/playground/vgeo_viewer/sample_asset.d.ts.map +1 -0
  489. package/src/shade/playground/vgeo_viewer/sample_asset.js +117 -0
  490. package/src/shade/playground/vgeo_viewer/select_cut.d.ts +154 -0
  491. package/src/shade/playground/vgeo_viewer/select_cut.d.ts.map +1 -0
  492. package/src/shade/playground/vgeo_viewer/select_cut.js +437 -0
  493. package/src/shade/renderer/DynamicResolutionScaling.d.ts +1 -1
  494. package/src/shade/renderer/DynamicResolutionScaling.d.ts.map +1 -1
  495. package/src/shade/renderer/Renderer.d.ts +5 -5
  496. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  497. package/src/shade/renderer/animation/GPUAnimationManager.d.ts.map +1 -1
  498. package/src/shade/renderer/animation/skin_normalize_mesh_frame.d.ts.map +1 -1
  499. package/src/shade/renderer/camera/Camera.d.ts +3 -3
  500. package/src/shade/renderer/camera/Camera.d.ts.map +1 -1
  501. package/src/shade/renderer/camera/GPUCameraContext.d.ts +1 -1
  502. package/src/shade/renderer/camera/GPUCameraContext.d.ts.map +1 -1
  503. package/src/shade/renderer/camera/OrthographicCamera.d.ts +4 -4
  504. package/src/shade/renderer/camera/OrthographicCamera.d.ts.map +1 -1
  505. package/src/shade/renderer/camera/PerspectiveCamera.d.ts +2 -2
  506. package/src/shade/renderer/camera/PerspectiveCamera.d.ts.map +1 -1
  507. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +11 -3
  508. package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
  509. package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +25 -5
  510. package/src/shade/renderer/extension/FrameContext.d.ts +1 -1
  511. package/src/shade/renderer/extension/FrameContext.d.ts.map +1 -1
  512. package/src/shade/renderer/extension/GBufferTextures.d.ts +4 -4
  513. package/src/shade/renderer/extension/GBufferTextures.d.ts.map +1 -1
  514. package/src/shade/renderer/extension/PresentTarget.d.ts +1 -1
  515. package/src/shade/renderer/extension/PresentTarget.d.ts.map +1 -1
  516. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +918 -918
  517. package/src/shade/renderer/extension/SceneColor.d.ts +1 -1
  518. package/src/shade/renderer/extension/SceneColor.d.ts.map +1 -1
  519. package/src/shade/renderer/extension/ViewTextures.d.ts +4 -4
  520. package/src/shade/renderer/extension/ViewTextures.d.ts.map +1 -1
  521. package/src/shade/renderer/geometry/Attribute.d.ts +1 -1
  522. package/src/shade/renderer/geometry/Attribute.d.ts.map +1 -1
  523. package/src/shade/renderer/geometry/Geometry.d.ts +1 -1
  524. package/src/shade/renderer/geometry/Geometry.d.ts.map +1 -1
  525. package/src/shade/renderer/geometry/bvh/bvh2_check_bounds.d.ts.map +1 -1
  526. package/src/shade/renderer/geometry/bvh/bvh2_derive_topology.d.ts.map +1 -1
  527. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts +3 -3
  528. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
  529. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_collect_geometries.d.ts.map +1 -1
  530. package/src/shade/renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.d.ts.map +1 -1
  531. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_read_frame_extent.d.ts +29 -0
  532. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_read_frame_extent.d.ts.map +1 -0
  533. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_read_frame_extent.js +59 -0
  534. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.d.ts +0 -1
  535. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.d.ts.map +1 -1
  536. package/src/shade/renderer/geometry/virtual/format/frame/vgeo_scan_frames.js +2 -23
  537. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts +94 -0
  538. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.d.ts.map +1 -0
  539. package/src/shade/renderer/geometry/virtual/format/read/VGeoByteSource.js +170 -0
  540. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts +122 -0
  541. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.d.ts.map +1 -0
  542. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerHeader.js +143 -0
  543. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts +185 -0
  544. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.d.ts.map +1 -0
  545. package/src/shade/renderer/geometry/virtual/format/read/VGeoContainerReader.js +572 -0
  546. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts +64 -0
  547. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.d.ts.map +1 -0
  548. package/src/shade/renderer/geometry/virtual/format/read/VGeoDirectory.js +80 -0
  549. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts +198 -0
  550. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.d.ts.map +1 -0
  551. package/src/shade/renderer/geometry/virtual/format/read/VGeoPage.js +232 -0
  552. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageWant.d.ts +51 -0
  553. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageWant.d.ts.map +1 -0
  554. package/src/shade/renderer/geometry/virtual/format/read/VGeoPageWant.js +55 -0
  555. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts +68 -0
  556. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.d.ts.map +1 -0
  557. package/src/shade/renderer/geometry/virtual/format/read/VGeoReadOptions.js +72 -0
  558. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts +28 -0
  559. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.d.ts.map +1 -0
  560. package/src/shade/renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js +108 -0
  561. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts +23 -0
  562. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.d.ts.map +1 -0
  563. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_directory.js +83 -0
  564. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts +53 -0
  565. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.d.ts.map +1 -0
  566. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_header.js +211 -0
  567. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts +26 -0
  568. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -0
  569. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +271 -0
  570. package/src/shade/renderer/global_illumination/brick4/cpu/brick4_bake_for_scene.d.ts.map +1 -1
  571. package/src/shade/renderer/global_illumination/clipmap/GPUClipMap3D.d.ts +2 -2
  572. package/src/shade/renderer/global_illumination/clipmap/GPUClipMap3D.d.ts.map +1 -1
  573. package/src/shade/renderer/global_illumination/lpv/LightProbeVolume.d.ts +1 -1
  574. package/src/shade/renderer/global_illumination/lpv/LightProbeVolume.d.ts.map +1 -1
  575. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts +1 -1
  576. package/src/shade/renderer/global_illumination/lpv/bake/GPULightProbeVolumeRenderer.d.ts.map +1 -1
  577. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts +1 -1
  578. package/src/shade/renderer/global_illumination/sharc/SpatialHashRadianceCache.d.ts.map +1 -1
  579. package/src/shade/renderer/gpu_primitive/bvh/check_bvh_structure.d.ts.map +1 -1
  580. package/src/shade/renderer/light/LightCollection.d.ts +2 -2
  581. package/src/shade/renderer/light/LightCollection.d.ts.map +1 -1
  582. package/src/shade/renderer/light/model/PointLight.d.ts +1 -1
  583. package/src/shade/renderer/light/model/PointLight.d.ts.map +1 -1
  584. package/src/shade/renderer/light/model/SpotLight.d.ts +1 -1
  585. package/src/shade/renderer/light/model/SpotLight.d.ts.map +1 -1
  586. package/src/shade/renderer/loader/gltf/fix_up_material_sides.d.ts.map +1 -1
  587. package/src/shade/renderer/loader/gltf/gltf_create_material.d.ts +1 -1
  588. package/src/shade/renderer/loader/gltf/gltf_create_material.d.ts.map +1 -1
  589. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +2 -2
  590. package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts.map +1 -1
  591. package/src/shade/renderer/loader/usd/usd_decode_image.d.ts +1 -1
  592. package/src/shade/renderer/loader/usd/usd_decode_image.d.ts.map +1 -1
  593. package/src/shade/renderer/material/util/material_convert_metallic_roughness_to_specular_glossiness.d.ts.map +1 -1
  594. package/src/shade/renderer/material/util/material_convert_specular_glossiness_to_metallic_roughness.d.ts.map +1 -1
  595. package/src/shade/renderer/particles/DESIGN.md +18 -7
  596. package/src/shade/renderer/particles/GPUParticleSystem.d.ts +24 -10
  597. package/src/shade/renderer/particles/GPUParticleSystem.d.ts.map +1 -1
  598. package/src/shade/renderer/particles/GPUParticleSystem.js +77 -72
  599. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts +17 -16
  600. package/src/shade/renderer/particles/coherence/graph_particle_bucket.d.ts.map +1 -1
  601. package/src/shade/renderer/particles/coherence/graph_particle_bucket.js +35 -22
  602. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts +6 -6
  603. package/src/shade/renderer/particles/graph/ParticleGroupBuilder.d.ts.map +1 -1
  604. package/src/shade/renderer/particles/graph/ParticleNodeGroup.d.ts.map +1 -1
  605. package/src/shade/renderer/particles/graph/ParticleValueType.d.ts +1 -1
  606. package/src/shade/renderer/particles/graph/ParticleValueType.d.ts.map +1 -1
  607. package/src/shade/renderer/particles/graph/make_particle_group.d.ts.map +1 -1
  608. package/src/shade/renderer/particles/graph/particle_graph_authoring.d.ts.map +1 -1
  609. package/src/shade/renderer/particles/graph/particle_group_json.d.ts.map +1 -1
  610. package/src/shade/renderer/particles/graph_particles.d.ts +11 -0
  611. package/src/shade/renderer/particles/graph_particles.d.ts.map +1 -1
  612. package/src/shade/renderer/particles/graph_particles.js +55 -37
  613. package/src/shade/renderer/particles/graph_particles_billboard.d.ts.map +1 -1
  614. package/src/shade/renderer/particles/isa/ParticleVMISA.d.ts.map +1 -1
  615. package/src/shade/renderer/particles/isa/particle_assembly.d.ts.map +1 -1
  616. package/src/shade/renderer/particles/layout/ParticleLayout.d.ts.map +1 -1
  617. package/src/shade/renderer/particles/optimizer/dag/particle_vector_lift.d.ts.map +1 -1
  618. package/src/shade/renderer/particles/optimizer/dag/particle_vector_pack.d.ts.map +1 -1
  619. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts +1 -1
  620. package/src/shade/renderer/particles/optimizer/optimize_particle_program.d.ts.map +1 -1
  621. package/src/shade/renderer/particles/optimizer/particle_program_equivalence.d.ts.map +1 -1
  622. package/src/shade/renderer/particles/runtime/create_particle_effect.d.ts.map +1 -1
  623. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts +17 -13
  624. package/src/shade/renderer/particles/sort/graph_particle_sort.d.ts.map +1 -1
  625. package/src/shade/renderer/particles/sort/graph_particle_sort.js +43 -33
  626. package/src/shade/renderer/particles/vm/ParticleVMReference.d.ts.map +1 -1
  627. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts +1 -1
  628. package/src/shade/renderer/postprocess/denoise/LigmaDenoiser.d.ts.map +1 -1
  629. package/src/shade/renderer/postprocess/graph_pass_composit_red_as_rgba.d.ts.map +1 -1
  630. package/src/shade/renderer/postprocess/nss/NSS.d.ts +4 -4
  631. package/src/shade/renderer/postprocess/nss/NSS.d.ts.map +1 -1
  632. package/src/shade/renderer/postprocess/ssr/SSR.d.ts +3 -3
  633. package/src/shade/renderer/postprocess/ssr/SSR.d.ts.map +1 -1
  634. package/src/shade/renderer/postprocess/taa/TAA.d.ts +2 -2
  635. package/src/shade/renderer/postprocess/taa/TAA.d.ts.map +1 -1
  636. package/src/shade/renderer/rasterize/bucket/prepare_meshlet_draw_commands_by_material.d.ts.map +1 -1
  637. package/src/shade/renderer/rasterize/native/avboit/AVBOITSideChannel.d.ts.map +1 -1
  638. package/src/shade/renderer/scene/InstanceBatch.d.ts +1 -1
  639. package/src/shade/renderer/scene/InstanceBatch.d.ts.map +1 -1
  640. package/src/shade/renderer/scene/Node3D.d.ts +3 -3
  641. package/src/shade/renderer/scene/Node3D.d.ts.map +1 -1
  642. package/src/shade/renderer/scene/bvh/StaticSceneBVH.d.ts.map +1 -1
  643. package/src/shade/renderer/shader/compiler/CodeChunk.d.ts.map +1 -1
  644. package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.d.ts.map +1 -1
  645. package/src/shade/renderer/shader/graph/graph_prepare_pass_input_data.js +11 -0
  646. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts +1 -1
  647. package/src/shade/renderer/shader/type/WebGPUStruct.d.ts.map +1 -1
  648. package/src/shade/renderer/texture/GPUTextureContext.d.ts +1 -1
  649. package/src/shade/renderer/texture/GPUTextureContext.d.ts.map +1 -1
  650. package/src/shade/renderer/texture/format/sampler_descriptor_unpack.d.ts.map +1 -1
  651. package/src/shade/renderer/texture/source/ShadeImage.d.ts +7 -7
  652. package/src/shade/renderer/texture/source/ShadeImage.d.ts.map +1 -1
  653. package/src/shade/renderer/texture/virtual/VTPageTable.d.ts.map +1 -1
  654. package/src/shade/renderer/view/GPUViewContext.d.ts +2 -2
  655. package/src/shade/renderer/view/GPUViewContext.d.ts.map +1 -1
  656. package/src/shade/renderer/view/GPUViewSkyContext.d.ts +1 -1
  657. package/src/shade/renderer/view/GPUViewSkyContext.d.ts.map +1 -1
  658. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts +2 -2
  659. package/src/shade/renderer/volumetrics/GPUViewVolumetrics.d.ts.map +1 -1
  660. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts +1 -1
  661. package/src/shade/renderer/volumetrics/ParticipatingMediaVolume.d.ts.map +1 -1
  662. package/src/shade/wgsl/emulator/CPUBitmapData.d.ts.map +1 -1
  663. package/src/view/View.d.ts +1 -1
  664. package/src/view/View.d.ts.map +1 -1
  665. package/src/view/elements/button/ButtonView.d.ts +1 -1
  666. package/src/view/elements/button/ButtonView.d.ts.map +1 -1
  667. package/src/view/elements/progress/SmoothProgressBar.d.ts +2 -2
  668. package/src/view/elements/progress/SmoothProgressBar.d.ts.map +1 -1
  669. package/src/view/elements/radial/RadialMenuElement.d.ts +3 -3
  670. package/src/view/elements/radial/RadialMenuElement.d.ts.map +1 -1
  671. package/src/view/elements/windrose/WindRoseDiagram.d.ts.map +1 -1
  672. package/src/view/layout/DockLayoutView.d.ts.map +1 -1
  673. package/src/view/layout/DrawerView.d.ts +2 -2
  674. package/src/view/layout/DrawerView.d.ts.map +1 -1
  675. package/src/view/layout/SplitView.d.ts +9 -9
  676. package/src/view/layout/SplitView.d.ts.map +1 -1
  677. package/src/view/minimap/MinimapMarkerCollection.d.ts +3 -2
  678. package/src/view/minimap/MinimapMarkerCollection.d.ts.map +1 -1
  679. package/src/view/minimap/MinimapMarkerCollection.js +28 -5
  680. package/src/view/minimap/dom/MinimapMarkerView.js +65 -34
  681. package/src/view/minimap/gl/MarkerGL.d.ts +15 -3
  682. package/src/view/minimap/gl/MarkerGL.d.ts.map +1 -1
  683. package/src/view/minimap/gl/MarkerGL.js +31 -4
  684. package/src/engine/physics/BULLET_REVIEW.md +0 -945
  685. package/src/engine/physics/CANNON_REVIEW.md +0 -1300
  686. package/src/engine/physics/CONSTRAINT_SOLVER_BENCH_LOG.md +0 -208
  687. package/src/engine/physics/CONSTRAINT_SOLVER_IMPROVEMENTS_PLAN.md +0 -364
  688. package/src/engine/physics/INTEPOLATION_SYSTEM_PLAN.md +0 -287
  689. package/src/engine/physics/JOLT_REVIEW.md +0 -913
  690. package/src/engine/physics/PLAN.md +0 -1120
  691. package/src/engine/physics/RAPIER_REVIEW.md +0 -934
  692. package/src/engine/physics/REVIEW_001_ACTION_PLAN.md +0 -642
  693. package/src/engine/physics/REVIEW_002.md +0 -151
  694. package/src/engine/physics/REVIEW_003.md +0 -166
  695. package/src/shade/descriptor/util/optional_clone.d.ts +0 -7
  696. package/src/shade/descriptor/util/optional_clone.d.ts.map +0 -1
  697. package/src/shade/descriptor/util/optional_equality.d.ts +0 -10
  698. package/src/shade/descriptor/util/optional_equality.d.ts.map +0 -1
  699. package/src/shade/descriptor/util/optional_hash.d.ts +0 -9
  700. package/src/shade/descriptor/util/optional_hash.d.ts.map +0 -1
  701. package/src/shade/renderer/geometry/virtual/format/prototypeVGEOFormatViewer.js +0 -2063
@@ -0,0 +1,1288 @@
1
+ import Vector3 from "../../../core/geom/Vector3.js";
2
+ import { DEG_TO_RAD } from "../../../core/math/DEG_TO_RAD.js";
3
+ import { OrbitalCameraController } from "../../renderer/camera/orbital/index.js";
4
+ import { PerspectiveCamera } from "../../renderer/camera/PerspectiveCamera.js";
5
+ import { create_frame_loop } from "../../renderer/create_frame_loop.js";
6
+ import { DEFAULT_DEPTH_TEXTURE_VIEW } from "../../renderer/depth/DEFAULT_DEPTH_TEXTURE_VIEW.js";
7
+ import { DEPTH_BACKGROUND_VALUE } from "../../renderer/depth/DEPTH_BACKGROUND_VALUE.js";
8
+ import { GPUDynamicMeshRenderer } from "../../renderer/dynamic/GPUDynamicMeshRenderer.js";
9
+ import { FramePhase } from "../../renderer/extension/FramePhase.js";
10
+ import { RenderExtension } from "../../renderer/extension/RenderExtension.js";
11
+ import { SceneColor } from "../../renderer/extension/SceneColor.js";
12
+ import { ViewTextures } from "../../renderer/extension/ViewTextures.js";
13
+ import {
14
+ vgeo_codec_name
15
+ } from "../../renderer/geometry/virtual/format/frame/vgeo_codec_name.js";
16
+ import {
17
+ VGeoByteSource
18
+ } from "../../renderer/geometry/virtual/format/read/VGeoByteSource.js";
19
+ import {
20
+ VGeoContainerReader
21
+ } from "../../renderer/geometry/virtual/format/read/VGeoContainerReader.js";
22
+ import {
23
+ vgeo_fetch_byte_source
24
+ } from "../../renderer/geometry/virtual/format/read/vgeo_fetch_byte_source.js";
25
+ import {
26
+ VGeoReadOptions
27
+ } from "../../renderer/geometry/virtual/format/read/VGeoReadOptions.js";
28
+ import { make_sunlight } from "../../renderer/light/make_sunlight.js";
29
+ import { Renderer } from "../../renderer/Renderer.js";
30
+ import { DynamicMesh } from "../../renderer/scene/DynamicMesh.js";
31
+ import { DynamicMeshBatch } from "../../renderer/scene/DynamicMeshBatch.js";
32
+ import { Scene } from "../../renderer/scene/Scene.js";
33
+ import { VGEO_COLOR_MODE, vgeo_build_cut_geometry } from "./cut_geometry.js";
34
+ import { vgeo_sample_source } from "./sample_asset.js";
35
+ import { VGeoCut, VGeoCutView, vgeo_select_cut } from "./select_cut.js";
36
+
37
+ /**
38
+ * An interactive viewer for the `.vgeo` container.
39
+ *
40
+ * Point it at a file and it is opened *incrementally* — the header, the level table and the root
41
+ * page, and after that only the pages a cut actually asks for. What is drawn is not the asset but
42
+ * the **cut**: the clusters the container's own metric selects for where the camera is standing,
43
+ * coloured so the seams between them are visible.
44
+ *
45
+ * Two things are therefore on screen at once, and telling them apart is the point of the tool:
46
+ *
47
+ * - **The cut is frozen until you ask for a new one.** "Adapt to view" re-runs the traversal at
48
+ * wherever the camera is now; everything after that is you flying around a decision taken from
49
+ * somewhere else, which is the only way to see what a cut actually selected. Turn `follow the
50
+ * camera` on to watch it chase instead.
51
+ * - **A cut taken from a partly-arrived file is clamped, not wrong.** Where the page holding a
52
+ * refinement is missing, the coarser cluster is drawn and a want is recorded — a watertight
53
+ * surface either way. `colour by clamp` paints exactly those regions, and `stream wanted pages`
54
+ * fetches them and re-adapts until the count reaches zero.
55
+ *
56
+ * Drawing goes through Shade's **direct geometry path** — a {@link DynamicMesh} drawn straight from
57
+ * its attributes, no meshlet encode — because a cut is rebuilt from scratch every time it is
58
+ * adapted, and a meshlet build per adapt would price the tool out of being interactive. It is drawn
59
+ * *opaque* on that path ({@link GPUDynamicMeshRenderer.opaque}), so the depth buffer orders the
60
+ * cut's own triangles: a cut is a solid surface and nothing on the CPU can order one correctly.
61
+ *
62
+ * The reader under it is not a debug reader. It is `format/read/`, it is what a runtime would use,
63
+ * and everything above — the traversal, the clamp, the wants — is the page's own. See README.md.
64
+ *
65
+ * @author Alex Goldring
66
+ * @copyright Company Named Limited (c) 2026
67
+ */
68
+
69
+ /**
70
+ * How many wanted pages one streaming round installs before the cut is retaken and the panel
71
+ * redrawn.
72
+ *
73
+ * Small on purpose. A round that installed every want would arrive as one step from coarse to final
74
+ * and show nothing of the process; this is what makes refinement visible while it happens, which is
75
+ * the only reason to look at a streaming reader rather than read its numbers.
76
+ *
77
+ * @type {number}
78
+ */
79
+ const STREAM_BATCH = 8;
80
+
81
+ /**
82
+ * The head prefixes the panel offers, in bytes.
83
+ *
84
+ * §10 gives a reader two cold starts and this is the dial between them: the header alone, and then
85
+ * one exact range per page it decides it wants — or one speculative prefix that brings the head and
86
+ * whatever else it happens to cover. Both are correct and they cost very differently, and which is
87
+ * better depends entirely on how big the asset is against how much of it a view needs. Being able to
88
+ * flip between them on one file, and watch `read` and `requests` move, is most of what there is to
89
+ * learn about the front of this format.
90
+ *
91
+ * @type {[string, number][]}
92
+ */
93
+ const HEAD_PREFIXES = [
94
+ ['256 B — header only', 256],
95
+ ['16 KB', 16 * 1024],
96
+ ['64 KB', 64 * 1024],
97
+ ['256 KB — the default', 256 * 1024],
98
+ ['1 MB', 1024 * 1024],
99
+ ];
100
+
101
+ /**
102
+ * @param {number} value
103
+ * @returns {string}
104
+ */
105
+ function thousands(value) {
106
+ return value.toLocaleString('en-US');
107
+ }
108
+
109
+ /**
110
+ * @param {[string, string][]} entries
111
+ * @returns {string} one label/value row apiece
112
+ */
113
+ function panel_table(entries) {
114
+ return entries
115
+ .map(([key, value]) => `<div class="row"><span class="muted">${key}</span><span>${value}</span></div>`)
116
+ .join('');
117
+ }
118
+
119
+ /**
120
+ * @param {number} bytes
121
+ * @returns {string}
122
+ */
123
+ function human_bytes(bytes) {
124
+ if (bytes < 1024) {
125
+ return `${bytes} B`;
126
+ }
127
+
128
+ if (bytes < 1024 * 1024) {
129
+ return `${(bytes / 1024).toFixed(1)} KB`;
130
+ }
131
+
132
+ if (bytes < 1024 * 1024 * 1024) {
133
+ return `${(bytes / (1024 * 1024)).toFixed(1)} MB`;
134
+ }
135
+
136
+ return `${(bytes / (1024 * 1024 * 1024)).toFixed(2)} GB`;
137
+ }
138
+
139
+ /**
140
+ * @param {string} text
141
+ * @returns {string}
142
+ */
143
+ function escape_html(text) {
144
+ return String(text).replace(/[&<>]/g, (c) => ({ '&': '&amp;', '<': '&lt;', '>': '&gt;' })[c]);
145
+ }
146
+
147
+ /**
148
+ * What the resident pages cost stored against what they cost decoded, and under which codec.
149
+ *
150
+ * Stored is the number that gets fetched and the number that sits on disk; decoded is the number a
151
+ * resident page costs in RAM. The codec is per frame, so a file can genuinely be a mixture — the
152
+ * encoder stores a page raw whenever compressing it would not have shrunk it — and naming all of
153
+ * them is more honest than naming whichever one happened to come first.
154
+ *
155
+ * @param {VGeoPage[]} pages
156
+ * @returns {string}
157
+ */
158
+ function page_storage(pages) {
159
+ if (pages.length === 0) {
160
+ return '—';
161
+ }
162
+
163
+ let stored = 0;
164
+ let decoded = 0;
165
+
166
+ for (const page of pages) {
167
+ stored += page.stored_size;
168
+ decoded += page.decoded_size;
169
+ }
170
+
171
+ const codec = Array.from(new Set(pages.map((page) => page.codec)))
172
+ .map(vgeo_codec_name)
173
+ .join(' + ');
174
+
175
+ return `${human_bytes(stored)} stored · ${human_bytes(decoded)} decoded`
176
+ + ` · ${codec} ${(decoded / Math.max(stored, 1)).toFixed(2)}x`;
177
+ }
178
+
179
+ /**
180
+ * The viewer draws its clusters into the scene, at the phase a full-screen effect that should be
181
+ * tonemapped with the rest of the frame belongs at.
182
+ */
183
+ class VGEOViewerExtension extends RenderExtension {
184
+ name = "vgeo viewer";
185
+
186
+ phase = FramePhase.AfterTransparency;
187
+
188
+ /**
189
+ * @type {VGeoViewer}
190
+ */
191
+ #viewer;
192
+
193
+ /**
194
+ * @param {VGeoViewer} viewer
195
+ */
196
+ constructor(viewer) {
197
+ super();
198
+
199
+ this.#viewer = viewer;
200
+ }
201
+
202
+ record(frame) {
203
+ this.#viewer.record(frame);
204
+ }
205
+ }
206
+
207
+ /**
208
+ * Clear the frame's depth, so that the cut is the only thing in it.
209
+ *
210
+ * **The renderer does not do this when there is nothing to rasterize.** Depth is cleared as a side
211
+ * effect of drawing the first opaque bucket, and this viewer's `Scene` holds a light and no meshes,
212
+ * so that draw never happens. The renderer also ping-pongs two depth textures frame to frame — so
213
+ * left alone, the cut is depth-tested against *its own depth from two frames ago*, and dissolves
214
+ * into holes wherever the camera has moved since. It reads as missing geometry and it is not.
215
+ *
216
+ * A real scene needs none of this and must not have it: the cut has to be occluded by whatever the
217
+ * scene put in the depth buffer, which is why the draw itself loads rather than clears.
218
+ *
219
+ * It runs immediately before the draw rather than at the top of the frame, so everything earlier
220
+ * that reads depth still sees the previous frame's. With nothing in the scene there is nothing for
221
+ * those passes to occlude, and the alternative is a second registration on another phase to save a
222
+ * result that is empty either way.
223
+ *
224
+ * @param {FrameGraph} graph
225
+ * @param {number} depth
226
+ * @returns {number} the depth handle to draw against
227
+ */
228
+ function vgeo_graph_clear_depth(graph, depth) {
229
+ const data = {};
230
+
231
+ const pass = graph.add('vgeo/clear depth', data, (data, resources, context) => {
232
+ const texture = resources.get(data.depth);
233
+
234
+ // no draws — the clear is the load op, and ending the pass immediately is what performs it
235
+ context.encoder.beginRenderPass({
236
+ label: "vgeo/clear depth",
237
+ colorAttachments: [],
238
+ depthStencilAttachment: {
239
+ view: texture.obtainView(DEFAULT_DEPTH_TEXTURE_VIEW),
240
+ depthLoadOp: "clear",
241
+ depthStoreOp: "store",
242
+ depthClearValue: DEPTH_BACKGROUND_VALUE,
243
+ },
244
+ }).end();
245
+ });
246
+
247
+ data.depth = pass.write(depth);
248
+
249
+ return data.depth;
250
+ }
251
+
252
+ /**
253
+ * The viewer. One container at a time, one cut at a time, and the cut only changes when asked.
254
+ */
255
+ class VGeoViewer {
256
+ /**
257
+ * @type {VGeoContainerReader|undefined}
258
+ */
259
+ #reader = undefined;
260
+
261
+ /**
262
+ * The source the current container was opened over, kept so that changing a read option can
263
+ * re-open it rather than ask for the file again.
264
+ * @type {VGeoByteSource|undefined}
265
+ */
266
+ #source = undefined;
267
+
268
+ /**
269
+ * @type {VGeoCutGeometry|undefined}
270
+ */
271
+ #cut_geometry = undefined;
272
+
273
+ /**
274
+ * @type {VGeoCut}
275
+ */
276
+ #cut = new VGeoCut();
277
+
278
+ /**
279
+ * @type {VGeoCutView}
280
+ */
281
+ #view = new VGeoCutView();
282
+
283
+ /**
284
+ * @type {VGeoReadOptions}
285
+ */
286
+ #read_options = new VGeoReadOptions();
287
+
288
+ /**
289
+ * Whether `?head=` named a prefix, in which case nothing here overrides it.
290
+ * @type {boolean}
291
+ */
292
+ #head_pinned = false;
293
+
294
+ /**
295
+ * @type {DynamicMeshBatch}
296
+ */
297
+ #batch = new DynamicMeshBatch();
298
+
299
+ /**
300
+ * @type {DynamicMesh|undefined}
301
+ */
302
+ #mesh = undefined;
303
+
304
+ /**
305
+ * A cut is a solid surface, so it is drawn as one: opaque, writing depth, and ordered by the
306
+ * depth buffer rather than by anything this file does.
307
+ *
308
+ * @type {GPUDynamicMeshRenderer}
309
+ */
310
+ #dynamic = new GPUDynamicMeshRenderer();
311
+
312
+ /**
313
+ * Where the camera stood when the current cut was taken, so the panel can say how far you have
314
+ * wandered from the decision you are looking at.
315
+ * @type {Float32Array}
316
+ */
317
+ #cut_eye = new Float32Array(3);
318
+
319
+ /**
320
+ * @type {Float32Array}
321
+ */
322
+ #eye = new Float32Array(3);
323
+
324
+ /**
325
+ * @type {boolean}
326
+ */
327
+ #auto_adapt = false;
328
+
329
+ /**
330
+ * Whether a clamped cut chases its own wants until there are none left.
331
+ * @type {boolean}
332
+ */
333
+ #auto_stream = true;
334
+
335
+ /**
336
+ * One streaming loop at a time — the loop retakes the cut between rounds, and two of them would
337
+ * be fetching against each other's want lists.
338
+ * @type {boolean}
339
+ */
340
+ #streaming = false;
341
+
342
+ /**
343
+ * @type {VGEO_COLOR_MODE}
344
+ */
345
+ #color_mode = VGEO_COLOR_MODE.Cluster;
346
+
347
+ /**
348
+ * @type {string}
349
+ */
350
+ #status = 'drop a .vgeo file anywhere on the page';
351
+
352
+ /**
353
+ * @type {string}
354
+ */
355
+ #file_label = '';
356
+
357
+ /**
358
+ * @type {number}
359
+ */
360
+ #open_ms = 0;
361
+
362
+ /**
363
+ * Bytes the source had served by the time the container was open — the cold start, measured.
364
+ * @type {number}
365
+ */
366
+ #open_bytes = 0;
367
+
368
+ /**
369
+ * @type {number}
370
+ */
371
+ #build_ms = 0;
372
+
373
+ /**
374
+ * What the last {@link VGeoContainerReader.validate} came to, or `undefined` while it has never
375
+ * been asked for — which is the default and the ordinary state.
376
+ * @type {VGeoDefect[]|undefined}
377
+ */
378
+ #defects = undefined;
379
+
380
+ /**
381
+ * @type {string}
382
+ */
383
+ #validation_status = 'not run';
384
+
385
+ constructor() {
386
+ this.canvas = document.createElement('canvas');
387
+ this.renderer = new Renderer();
388
+ this.camera = new PerspectiveCamera();
389
+ this.scene = new Scene();
390
+
391
+ this.#dynamic.opaque = true;
392
+ }
393
+
394
+ /**
395
+ * @returns {VGeoContainerReader|undefined}
396
+ */
397
+ get reader() {
398
+ return this.#reader;
399
+ }
400
+
401
+ /**
402
+ * @returns {VGeoCut}
403
+ */
404
+ get cut() {
405
+ return this.#cut;
406
+ }
407
+
408
+ /**
409
+ * Whether a clamped cut chases its own wants until there are none left.
410
+ *
411
+ * Setting it does not start a run — a caller that wants one calls {@link stream} and holds the
412
+ * promise, which is what a scripted session needs in order to wait for the end of it.
413
+ *
414
+ * @param {boolean} value
415
+ */
416
+ set_auto_stream(value) {
417
+ this.#auto_stream = value;
418
+ }
419
+
420
+ /**
421
+ * @returns {Promise<void>}
422
+ */
423
+ async start() {
424
+ document.body.style.margin = '0';
425
+ document.body.style.overflow = 'hidden';
426
+ document.body.style.background = '#070b10';
427
+
428
+ this.canvas.style.position = 'absolute';
429
+ this.canvas.style.inset = '0';
430
+ this.canvas.style.outline = 'none';
431
+
432
+ // the orbital controller attaches a KeyboardDevice, and a canvas cannot receive key events
433
+ // without being focusable
434
+ this.canvas.tabIndex = 0;
435
+
436
+ document.body.appendChild(this.canvas);
437
+
438
+ this.canvas.focus();
439
+
440
+ await this.renderer.initialize({ context: this.canvas.getContext('webgpu') });
441
+
442
+ /*
443
+ Everything that would move the image for reasons unrelated to the cut is off. Automatic
444
+ exposure in particular: it adapts to whatever is on screen, so the same cluster would read a
445
+ different colour depending on how much of the model is in frame, which is exactly the signal
446
+ this tool is trying to show.
447
+ */
448
+ this.renderer.feature_automatic_exposure_enabled = false;
449
+ this.renderer.feature_taa_enabled = true;
450
+ this.renderer.feature_bloom_enabled = false;
451
+ this.renderer.feature_ssr_enabled = false;
452
+ this.renderer.feature_ssao_enabled = true;
453
+ this.renderer.feature_shadows_enabled = false;
454
+ this.renderer.feature_lpv_enabled = false;
455
+ this.renderer.pixel_ratio = 1;
456
+
457
+ this.scene.lights.add(make_sunlight({ intensity: 3 }));
458
+
459
+ this.camera.near = 0.05;
460
+ this.camera.far = 500;
461
+ this.camera.fov = 55 * DEG_TO_RAD;
462
+ this.camera.transform.setTranslation(0, 0.5, 2);
463
+ this.camera.transform.lookAt(Vector3.zero);
464
+
465
+ this.controller = new OrbitalCameraController(this.camera, this.canvas);
466
+ this.controller.distanceLimits.min = 1e-4;
467
+ this.controller.distanceLimits.max = 1e5;
468
+
469
+ this.#build_interface();
470
+ this.#fit_to_window();
471
+
472
+ window.addEventListener('resize', () => this.#fit_to_window());
473
+
474
+ this.renderer.add_extension(new VGEOViewerExtension(this));
475
+
476
+ create_frame_loop((dt) => this.#frame(dt));
477
+
478
+ const query = new URL(window.location.href).searchParams;
479
+
480
+ const head = query.get('head');
481
+
482
+ if (head !== null) {
483
+ this.#read_options.head_prefix_bytes = Number(head);
484
+ this.#head_pinned = true;
485
+ }
486
+
487
+ this.#read_options.validate = query.get('validate') !== null;
488
+ this.#read_options.verify_frames = query.get('verify') !== null;
489
+
490
+ const requested = query.get('file');
491
+
492
+ if (requested !== null) {
493
+ await this.load_url(requested);
494
+ } else if (query.get('sample') !== null) {
495
+ await this.open_sample();
496
+ }
497
+ }
498
+
499
+ /**
500
+ * @param {FrameContext} frame
501
+ */
502
+ record(frame) {
503
+ const graph = frame.graph;
504
+ const scene = frame.get(SceneColor);
505
+
506
+ scene.color = this.#dynamic.graph_draw({
507
+ graph,
508
+ batch: this.#batch,
509
+ color: scene.color,
510
+ depth: vgeo_graph_clear_depth(graph, frame.get(ViewTextures).depth),
511
+ camera: frame.view.camera.buffer,
512
+ });
513
+ }
514
+
515
+ #fit_to_window() {
516
+ const width = window.innerWidth;
517
+ const height = window.innerHeight;
518
+
519
+ this.canvas.width = width;
520
+ this.canvas.height = height;
521
+
522
+ this.renderer.resize(width, height);
523
+
524
+ this.camera.aspect = this.renderer.aspect_ratio;
525
+
526
+ this.#view.screen_height = height;
527
+ this.#view.fov_y = this.camera.fov;
528
+ }
529
+
530
+ /**
531
+ * @param {number} dt seconds
532
+ */
533
+ #frame(dt) {
534
+ this.controller.update(dt);
535
+
536
+ const position = this.camera.transform;
537
+
538
+ const moved = position.translation_x !== this.#eye[0]
539
+ || position.translation_y !== this.#eye[1]
540
+ || position.translation_z !== this.#eye[2];
541
+
542
+ this.#eye[0] = position.translation_x;
543
+ this.#eye[1] = position.translation_y;
544
+ this.#eye[2] = position.translation_z;
545
+
546
+ if (moved && this.#auto_adapt) {
547
+ this.adapt();
548
+ }
549
+
550
+ this.renderer.render(this.camera, this.scene, dt);
551
+
552
+ if (moved) {
553
+ this.#refresh_cut();
554
+ }
555
+ }
556
+
557
+ /**
558
+ * Re-render the cut readout alone.
559
+ *
560
+ * Every number under it moves as the camera does — the drift on every frame, and the whole lot on
561
+ * every adapt when `follow the camera` is on. Rebuilding the *whole* panel at that rate would
562
+ * also rebuild the controls, which is how a slider stops being draggable mid-drag; this section
563
+ * holds no controls, so replacing it is free of that.
564
+ */
565
+ #refresh_cut() {
566
+ const host = this.panel.querySelector('#vgeo-cut');
567
+
568
+ if (host === null) {
569
+ return;
570
+ }
571
+
572
+ host.innerHTML = this.#cut_html();
573
+ }
574
+
575
+ /**
576
+ * The cut readout — the cluster count first, because it is the number the tool exists to show,
577
+ * and the clamp count second, because it is the one that says the picture is still arriving.
578
+ *
579
+ * @returns {string}
580
+ */
581
+ #cut_html() {
582
+ const cut = this.#cut;
583
+
584
+ const clamped = cut.clamped === 0
585
+ ? `<span class="good">0 — this is the cut the file selects</span>`
586
+ : `<span class="warn">${thousands(cut.clamped)} waiting on ${cut.wants.length} page(s)</span>`;
587
+
588
+ const rows = [
589
+ ['triangles', thousands(cut.triangle_count)],
590
+ ['clamped', clamped],
591
+ ['groups', thousands(cut.groups_visited)],
592
+ ['pages read', thousands(cut.pages_touched)],
593
+ ['clusters tested', thousands(cut.clusters_tested)],
594
+ ['culled subtrees', thousands(cut.culled)],
595
+ ['select / build', `${cut.duration_ms.toFixed(1)} / ${this.#build_ms.toFixed(1)} ms`],
596
+ ['camera drift', `${this.#drift().toExponential(2)} u`],
597
+ ];
598
+
599
+ if (cut.broken_child_refs > 0) {
600
+ rows.push(['broken child refs', `<span class="bad">${thousands(cut.broken_child_refs)}</span>`]);
601
+ }
602
+
603
+ return `<div class="count">${thousands(cut.clusters.length)}</div>`
604
+ + `<div class="muted" style="margin-bottom:6px">clusters in the current cut</div>`
605
+ + panel_table(rows);
606
+ }
607
+
608
+ /**
609
+ * How far the camera has moved since the cut on screen was selected.
610
+ * @returns {number}
611
+ */
612
+ #drift() {
613
+ return Math.hypot(
614
+ this.#eye[0] - this.#cut_eye[0],
615
+ this.#eye[1] - this.#cut_eye[1],
616
+ this.#eye[2] - this.#cut_eye[2]
617
+ );
618
+ }
619
+
620
+ /**
621
+ * Take a fresh cut at wherever the camera is standing, from whatever the reader currently holds,
622
+ * and build the geometry for it.
623
+ */
624
+ adapt() {
625
+ if (this.#reader === undefined) {
626
+ return;
627
+ }
628
+
629
+ // the frustum is derived from matrices the renderer refreshes during its own frame, and an
630
+ // adapt can land before one has run — a cut culled against last frame's planes would be a
631
+ // silent, hard-to-see wrong answer
632
+ this.camera.update();
633
+
634
+ this.#view.eye.set(this.#eye);
635
+ this.#view.screen_height = this.canvas.height;
636
+ this.#view.fov_y = this.camera.fov;
637
+ this.#view.frustum.set(this.camera.frustum);
638
+
639
+ this.#cut = vgeo_select_cut(this.#reader, this.#view);
640
+
641
+ const started = performance.now();
642
+
643
+ const previous = this.#cut_geometry;
644
+
645
+ this.#cut_geometry = vgeo_build_cut_geometry(this.#cut, this.#color_mode);
646
+
647
+ this.#build_ms = performance.now() - started;
648
+
649
+ this.#batch.clear();
650
+
651
+ // Residency is keyed on the geometry and deliberately survives leaving the batch, so the cut
652
+ // that was just replaced would hold its buffers forever otherwise — and this tool replaces
653
+ // one on every drag of the tau slider.
654
+ if (previous !== undefined) {
655
+ this.#dynamic.release(previous.geometry);
656
+ }
657
+
658
+ this.#mesh = DynamicMesh.from(this.#cut_geometry.geometry);
659
+ this.#mesh.updateMatrices();
660
+
661
+ this.#batch.add(this.#mesh);
662
+
663
+ this.#cut_eye.set(this.#eye);
664
+ }
665
+
666
+ /**
667
+ * Fetch the pages the current cut is clamped against, a batch at a time, retaking the cut after
668
+ * each — until nothing is clamped, or the loop is turned off, or a round installs nothing.
669
+ *
670
+ * Note what is *not* here: any handling for the cut being wrong in the meantime. It is not. Every
671
+ * intermediate cut this loop draws is a complete watertight surface at some level of detail, so
672
+ * there is nothing to hide while it converges and nothing to reconcile when it does.
673
+ *
674
+ * @returns {Promise<void>}
675
+ */
676
+ async stream() {
677
+ if (this.#streaming || this.#reader === undefined) {
678
+ return;
679
+ }
680
+
681
+ this.#streaming = true;
682
+
683
+ try {
684
+ while (this.#cut.wants.length > 0) {
685
+ const before = this.#reader.resident_page_count;
686
+
687
+ this.#status = `fetching ${Math.min(this.#cut.wants.length, STREAM_BATCH)}`
688
+ + ` of ${this.#cut.wants.length} wanted page(s)`;
689
+
690
+ this.#refresh_panel();
691
+
692
+ await this.#reader.install_wants(this.#cut.wants, STREAM_BATCH);
693
+
694
+ // A round that installed nothing means every want is unfetchable, and continuing
695
+ // would be a spin against the same list forever.
696
+ if (this.#reader.resident_page_count === before) {
697
+ this.#status = 'the wanted pages could not be installed';
698
+ break;
699
+ }
700
+
701
+ this.#status = '';
702
+
703
+ this.adapt();
704
+ this.#refresh_panel();
705
+
706
+ if (!this.#auto_stream) {
707
+ break;
708
+ }
709
+ }
710
+ } catch (e) {
711
+ this.#status = String(e.message ?? e);
712
+
713
+ throw e;
714
+ } finally {
715
+ this.#streaming = false;
716
+ this.#refresh_panel();
717
+ }
718
+ }
719
+
720
+ /**
721
+ * Open a container over a byte source, and take the first cut.
722
+ *
723
+ * @param {VGeoByteSource} source
724
+ * @returns {Promise<void>}
725
+ */
726
+ async open(source) {
727
+ this.#source = source;
728
+ this.#file_label = source.name;
729
+ this.#defects = undefined;
730
+ this.#validation_status = 'not run';
731
+ this.#status = `opening ${source.name}`;
732
+
733
+ source.reset_counters();
734
+
735
+ this.#refresh_panel();
736
+
737
+ const started = performance.now();
738
+
739
+ try {
740
+ this.#reader = await VGeoContainerReader.open(source, this.#read_options);
741
+ } catch (e) {
742
+ this.#reader = undefined;
743
+ this.#cut = new VGeoCut();
744
+ this.#cut_geometry = undefined;
745
+ this.#batch.clear();
746
+ this.#status = String(e.message ?? e);
747
+ this.#refresh_panel();
748
+
749
+ throw e;
750
+ }
751
+
752
+ this.#open_ms = performance.now() - started;
753
+ this.#open_bytes = source.bytes_read;
754
+ this.#status = '';
755
+
756
+ this.#frame_camera();
757
+ this.adapt();
758
+ this.#refresh_panel();
759
+
760
+ if (this.#auto_stream) {
761
+ await this.stream();
762
+ }
763
+ }
764
+
765
+ /**
766
+ * @param {Blob} blob a dropped `File`
767
+ * @returns {Promise<void>}
768
+ */
769
+ open_blob(blob) {
770
+ return this.open(VGeoByteSource.from_blob(blob));
771
+ }
772
+
773
+ /**
774
+ * Build a container in the page and open it, so there is something to look at without a file.
775
+ *
776
+ * The source is over bytes already in memory, which changes nothing above it: the reader still
777
+ * opens on the head and installs a page at a time, and the panel's `read` still says what
778
+ * fraction of the container this view actually cost.
779
+ *
780
+ * @returns {Promise<void>}
781
+ */
782
+ async open_sample() {
783
+ this.#status = 'building a sample asset';
784
+ this.#refresh_panel();
785
+
786
+ // yielded so the status paints before the builder takes the thread for a second
787
+ await new Promise((resolve) => setTimeout(resolve, 0));
788
+
789
+ const sample = vgeo_sample_source();
790
+
791
+ /*
792
+ The default prefix is one nominal page plus the head, and a *default* build has 256 KB
793
+ pages. The sample's are 8 KB, so the same prefix would swallow most of it and there would be
794
+ nothing left to stream — a demonstration of the head prefix rather than of the reader. Sized
795
+ to the sample's own pages instead, unless the address bar has already made the choice.
796
+ */
797
+ if (!this.#head_pinned) {
798
+ this.#read_options.head_prefix_bytes = 16 * 1024;
799
+ }
800
+
801
+ await this.open(sample.source);
802
+
803
+ this.#status = `built in ${sample.build_ms.toFixed(0)} ms`;
804
+ this.#refresh_panel();
805
+ }
806
+
807
+ /**
808
+ * Open the current source again, from cold, under whatever the read options now say.
809
+ *
810
+ * Which is the point of it: the head prefix and frame verification are decisions taken at open
811
+ * time, and comparing two of them means comparing two opens. Nothing is re-fetched that the
812
+ * source would not have re-fetched anyway — a URL source really does go back to the network,
813
+ * which is what makes the cold-start number honest.
814
+ *
815
+ * @returns {Promise<void>}
816
+ */
817
+ async reopen() {
818
+ if (this.#source === undefined) {
819
+ return;
820
+ }
821
+
822
+ await this.open(this.#source);
823
+ }
824
+
825
+ /**
826
+ * @param {string} url
827
+ * @returns {Promise<void>}
828
+ */
829
+ async load_url(url) {
830
+ this.#status = `probing ${url}`;
831
+ this.#refresh_panel();
832
+
833
+ try {
834
+ await this.open(await vgeo_fetch_byte_source(url));
835
+ } catch (e) {
836
+ this.#status = `${url} — ${e.message ?? e}`;
837
+ this.#refresh_panel();
838
+ }
839
+ }
840
+
841
+ /**
842
+ * Run the whole-file audit, which is the one thing here that reads every byte.
843
+ *
844
+ * @returns {Promise<VGeoDefect[]>}
845
+ */
846
+ async validate() {
847
+ if (this.#reader === undefined) {
848
+ return [];
849
+ }
850
+
851
+ this.#validation_status = 'reading the whole file…';
852
+ this.#refresh_panel();
853
+
854
+ const started = performance.now();
855
+
856
+ try {
857
+ this.#defects = await this.#reader.validate();
858
+ } catch (e) {
859
+ this.#defects = undefined;
860
+ this.#validation_status = String(e.message ?? e);
861
+ this.#refresh_panel();
862
+
863
+ throw e;
864
+ }
865
+
866
+ this.#validation_status = `${(performance.now() - started).toFixed(0)} ms`;
867
+ this.#refresh_panel();
868
+
869
+ return this.#defects;
870
+ }
871
+
872
+ /**
873
+ * Install every page the directory lists — the opposite of what this reader is for, and what a
874
+ * question about the file rather than about a view of it wants.
875
+ *
876
+ * @returns {Promise<void>}
877
+ */
878
+ async load_all_pages() {
879
+ if (this.#reader === undefined) {
880
+ return;
881
+ }
882
+
883
+ this.#status = 'installing every page';
884
+ this.#refresh_panel();
885
+
886
+ await this.#reader.install_all_pages((done, total) => {
887
+ this.#status = `installing every page — ${done} / ${total}`;
888
+ });
889
+
890
+ this.#status = '';
891
+
892
+ this.adapt();
893
+ this.#refresh_panel();
894
+ }
895
+
896
+ /**
897
+ * Drop everything but the root page, so the file arrives again from cold.
898
+ */
899
+ reset_residency() {
900
+ if (this.#reader === undefined) {
901
+ return;
902
+ }
903
+
904
+ this.#reader.evict_all();
905
+
906
+ this.adapt();
907
+ this.#refresh_panel();
908
+
909
+ if (this.#auto_stream) {
910
+ this.stream();
911
+ }
912
+ }
913
+
914
+ /**
915
+ * Put the camera where the whole asset is on screen, and scale the clip range to it — vgeo
916
+ * assets are authored at whatever scale the source used, and the Stanford models are a tenth of a
917
+ * unit across.
918
+ */
919
+ #frame_camera() {
920
+ const sphere = this.#reader.header.object_sphere;
921
+
922
+ const radius = Math.max(sphere[3], 1e-6);
923
+ const center = new Vector3(sphere[0], sphere[1], sphere[2]);
924
+
925
+ const distance = radius / Math.tan(this.camera.fov * 0.5) * 1.15;
926
+
927
+ const eye = new Vector3(0.55, 0.42, 0.72);
928
+
929
+ eye.normalize();
930
+ eye.multiplyScalar(distance);
931
+ eye.add(center);
932
+
933
+ this.camera.near = radius * 0.005;
934
+ this.camera.far = radius * 200;
935
+
936
+ this.controller.distanceLimits.min = radius * 0.02;
937
+ this.controller.distanceLimits.max = radius * 200;
938
+ this.controller.movement_speed_scale = radius;
939
+
940
+ this.controller.look(eye, center);
941
+
942
+ this.#eye[0] = eye.x;
943
+ this.#eye[1] = eye.y;
944
+ this.#eye[2] = eye.z;
945
+ }
946
+
947
+ #build_interface() {
948
+ const drop = document.getElementById('vgeo-drop');
949
+
950
+ let drag_depth = 0;
951
+
952
+ window.addEventListener('dragenter', (event) => {
953
+ event.preventDefault();
954
+ drag_depth++;
955
+ drop.classList.add('active');
956
+ });
957
+
958
+ window.addEventListener('dragover', (event) => event.preventDefault());
959
+
960
+ window.addEventListener('dragleave', () => {
961
+ drag_depth = Math.max(0, drag_depth - 1);
962
+
963
+ if (drag_depth === 0) {
964
+ drop.classList.remove('active');
965
+ }
966
+ });
967
+
968
+ window.addEventListener('drop', async (event) => {
969
+ event.preventDefault();
970
+
971
+ drag_depth = 0;
972
+ drop.classList.remove('active');
973
+
974
+ const file = event.dataTransfer.files[0];
975
+
976
+ if (file === undefined) {
977
+ return;
978
+ }
979
+
980
+ await this.open_blob(file);
981
+ });
982
+
983
+ this.panel = document.getElementById('vgeo-panel');
984
+
985
+ this.#refresh_panel();
986
+ }
987
+
988
+ /**
989
+ * @param {string} id
990
+ * @param {function(HTMLElement): void} bind
991
+ */
992
+ #wire(id, bind) {
993
+ const element = this.panel.querySelector(`#${id}`);
994
+
995
+ if (element !== null) {
996
+ bind(element);
997
+ }
998
+ }
999
+
1000
+ /**
1001
+ * The container section: what the header said, and what has actually been read.
1002
+ *
1003
+ * The second half is the point of the whole exercise. `read` against `file` is the fraction of
1004
+ * the asset this view cost, and on anything larger than a toy it is a small one.
1005
+ *
1006
+ * @returns {string}
1007
+ */
1008
+ #container_html() {
1009
+ const reader = this.#reader;
1010
+ const header = reader.header;
1011
+ const source = reader.source;
1012
+
1013
+ const pages = reader.pages;
1014
+
1015
+ /*
1016
+ Cumulative for the session, and deliberately allowed past the file's own size: evicting and
1017
+ re-streaming really does fetch those pages again, and the audit really does read every byte.
1018
+ Rendered as a multiple rather than a percentage once it passes one, because "151.8%" reads
1019
+ as a broken counter and "1.52× the file" reads as what it is.
1020
+ */
1021
+ const read_share = source.byte_length === 0
1022
+ ? ''
1023
+ : source.bytes_read < source.byte_length
1024
+ ? ` (${(100 * source.bytes_read / source.byte_length).toFixed(1)}% of the file)`
1025
+ : ` (${(source.bytes_read / source.byte_length).toFixed(2)}× the file)`;
1026
+
1027
+ return panel_table([
1028
+ ['file', `${escape_html(this.#file_label)} · ${human_bytes(source.byte_length)}`],
1029
+ ['format', `v${header.format_version} · encoding ${header.payload_encoding}`],
1030
+ ['asset id', header.asset_id.slice(0, 16)],
1031
+ ['source', `${thousands(header.source_face_count)} tris / ${thousands(header.source_vertex_count)} verts`],
1032
+ ['contents', `${thousands(header.total_clusters)} clusters · ${thousands(header.total_pages)} pages · ${header.levels.length} levels`],
1033
+ ])
1034
+ + `<h2>streaming</h2>`
1035
+ + panel_table([
1036
+ ['read so far', `${human_bytes(source.bytes_read)}${read_share}`],
1037
+ ['requests', thousands(source.request_count)],
1038
+ ['cold start', `${human_bytes(this.#open_bytes)} · ${this.#open_ms.toFixed(1)} ms`],
1039
+ ['resident', `${thousands(reader.resident_page_count)} / ${thousands(header.total_pages)} pages · ${human_bytes(reader.resident_bytes)}`],
1040
+ ['page storage', page_storage(pages)],
1041
+ ['per-vertex normals', this.#normal_share(pages)],
1042
+ ]);
1043
+ }
1044
+
1045
+ /**
1046
+ * How many resident clusters store a normal per vertex, against how many are resident at all.
1047
+ *
1048
+ * Worth saying outright because the alternative reads as a broken viewer: a source that carried
1049
+ * no normals encodes the engine default everywhere, every cluster compresses to one constant
1050
+ * word, and `colour by stored normal` comes out one flat colour across the whole model.
1051
+ *
1052
+ * @param {VGeoPage[]} pages
1053
+ * @returns {string}
1054
+ */
1055
+ #normal_share(pages) {
1056
+ let per_vertex = 0;
1057
+ let total = 0;
1058
+
1059
+ for (const page of pages) {
1060
+ per_vertex += page.per_vertex_normal_cluster_count;
1061
+ total += page.cluster_count;
1062
+ }
1063
+
1064
+ return `${thousands(per_vertex)} / ${thousands(total)} clusters`;
1065
+ }
1066
+
1067
+ /**
1068
+ * @returns {string}
1069
+ */
1070
+ #validation_html() {
1071
+ const defects = this.#defects;
1072
+
1073
+ const note = `<div class="muted" style="margin-bottom:4px">`
1074
+ + `off by default — it reads the whole file</div>`;
1075
+
1076
+ if (defects === undefined) {
1077
+ return note
1078
+ + `<div class="muted">${escape_html(this.#validation_status)}</div>`
1079
+ + `<button id="vgeo-validate">validate the whole file</button>`;
1080
+ }
1081
+
1082
+ const verdict = defects.length === 0
1083
+ ? `<div class="good">container valid — every invariant holds</div>`
1084
+ : `<div class="bad">${defects.length} defect(s)</div><ol class="bad">${
1085
+ defects.slice(0, 12).map((d) => `<li>${escape_html(d.toString())}</li>`).join('')
1086
+ }</ol>`;
1087
+
1088
+ return note
1089
+ + verdict
1090
+ + `<div class="row"><span class="muted">took</span><span>${escape_html(this.#validation_status)}</span></div>`
1091
+ + `<button id="vgeo-validate">validate again</button>`;
1092
+ }
1093
+
1094
+ #refresh_panel() {
1095
+ const reader = this.#reader;
1096
+
1097
+ const header = [`<h1>.vgeo viewer</h1>`];
1098
+
1099
+ if (this.#status !== '') {
1100
+ header.push(`<div class="muted">${escape_html(this.#status)}</div>`);
1101
+ }
1102
+
1103
+ if (reader === undefined) {
1104
+ this.panel.innerHTML = header.join('')
1105
+ + `<div class="muted" style="margin-top:8px">`
1106
+ + `or open <code>?file=/some/asset.vgeo</code></div>`
1107
+ + `<button id="vgeo-sample">build a sample asset</button>`;
1108
+
1109
+ this.#wire('vgeo-sample', (element) => {
1110
+ element.onclick = () => this.open_sample();
1111
+ });
1112
+
1113
+ return;
1114
+ }
1115
+
1116
+ this.panel.innerHTML = header.join('')
1117
+ + `<h2>container</h2>${this.#container_html()}`
1118
+ + `<button id="vgeo-stream" ${this.#cut.wants.length === 0 ? 'disabled' : ''}>`
1119
+ + `stream ${this.#cut.wants.length} wanted page(s)</button>`
1120
+ + `<label><input id="vgeo-auto-stream" type="checkbox" ${this.#auto_stream ? 'checked' : ''}> stream until nothing is clamped</label>`
1121
+ + `<label><input id="vgeo-verify" type="checkbox" ${this.#read_options.verify_frames ? 'checked' : ''}> verify each frame's checksum</label>`
1122
+ + `<button id="vgeo-load-all">install every page</button>`
1123
+ + `<button id="vgeo-evict">evict everything but the root</button>`
1124
+ + `<div class="row" style="margin-top:8px"><span class="muted">head prefix</span>`
1125
+ + `<span class="muted">re-opens from cold</span></div>`
1126
+ + `<select id="vgeo-head">`
1127
+ + HEAD_PREFIXES.map(([label, size]) =>
1128
+ `<option value="${size}" ${size === this.#read_options.head_prefix_bytes ? 'selected' : ''}>${label}</option>`
1129
+ ).join('')
1130
+ + `</select>`
1131
+ + `<h2>cut</h2>`
1132
+ + `<div id="vgeo-cut">${this.#cut_html()}</div>`
1133
+ + `<h2>selection</h2>`
1134
+ + `<div class="row"><span class="muted">tau</span><span id="vgeo-tau-value">${this.#view.tau.toFixed(2)} px</span></div>`
1135
+ + `<input id="vgeo-tau" type="range" min="-1.3" max="1.7" step="0.01" value="${Math.log10(this.#view.tau)}">`
1136
+ + `<button id="vgeo-adapt">adapt to view</button>`
1137
+ + `<label><input id="vgeo-auto" type="checkbox" ${this.#auto_adapt ? 'checked' : ''}> follow the camera</label>`
1138
+ + `<label><input id="vgeo-cull" type="checkbox" ${this.#view.cull_enabled ? 'checked' : ''}> frustum cull while selecting</label>`
1139
+ + `<h2>display</h2>`
1140
+ + `<select id="vgeo-color">`
1141
+ + Object.values(VGEO_COLOR_MODE).map((mode) =>
1142
+ `<option value="${mode}" ${mode === this.#color_mode ? 'selected' : ''}>colour by ${mode}</option>`
1143
+ ).join('')
1144
+ + `</select>`
1145
+ + `<h2>validation</h2>${this.#validation_html()}`;
1146
+
1147
+ this.#wire('vgeo-adapt', (element) => {
1148
+ element.onclick = () => {
1149
+ this.adapt();
1150
+ this.#refresh_panel();
1151
+ };
1152
+ });
1153
+
1154
+ this.#wire('vgeo-stream', (element) => {
1155
+ element.onclick = () => this.stream();
1156
+ });
1157
+
1158
+ this.#wire('vgeo-auto-stream', (element) => {
1159
+ element.onchange = () => {
1160
+ this.set_auto_stream(element.checked);
1161
+
1162
+ if (element.checked) {
1163
+ this.stream();
1164
+ }
1165
+ };
1166
+ });
1167
+
1168
+ this.#wire('vgeo-verify', (element) => {
1169
+ // read per fetch, so this takes effect on the next page rather than on a reopen
1170
+ element.onchange = () => {
1171
+ this.#read_options.verify_frames = element.checked;
1172
+ };
1173
+ });
1174
+
1175
+ this.#wire('vgeo-head', (element) => {
1176
+ element.onchange = () => {
1177
+ this.#read_options.head_prefix_bytes = Number(element.value);
1178
+
1179
+ this.reopen();
1180
+ };
1181
+ });
1182
+
1183
+ this.#wire('vgeo-load-all', (element) => {
1184
+ element.onclick = () => this.load_all_pages();
1185
+ });
1186
+
1187
+ this.#wire('vgeo-evict', (element) => {
1188
+ element.onclick = () => this.reset_residency();
1189
+ });
1190
+
1191
+ this.#wire('vgeo-validate', (element) => {
1192
+ element.onclick = () => this.validate();
1193
+ });
1194
+
1195
+ this.#wire('vgeo-tau', (element) => {
1196
+ element.oninput = () => {
1197
+ this.#view.tau = Math.pow(10, Number(element.value));
1198
+
1199
+ this.adapt();
1200
+ this.#refresh_panel();
1201
+
1202
+ if (this.#auto_stream) {
1203
+ this.stream();
1204
+ }
1205
+ };
1206
+ });
1207
+
1208
+ this.#wire('vgeo-auto', (element) => {
1209
+ element.onchange = () => {
1210
+ this.#auto_adapt = element.checked;
1211
+ };
1212
+ });
1213
+
1214
+ this.#wire('vgeo-cull', (element) => {
1215
+ element.onchange = () => {
1216
+ this.#view.cull_enabled = element.checked;
1217
+
1218
+ this.adapt();
1219
+ this.#refresh_panel();
1220
+ };
1221
+ });
1222
+
1223
+ this.#wire('vgeo-color', (element) => {
1224
+ element.onchange = () => {
1225
+ this.#color_mode = element.value;
1226
+
1227
+ this.adapt();
1228
+ this.#refresh_panel();
1229
+ };
1230
+ });
1231
+ }
1232
+ }
1233
+
1234
+ const viewer = new VGeoViewer();
1235
+
1236
+ /*
1237
+ Everything a session might want to reach for, and the handles a scripted one needs. A page that can
1238
+ be driven from the console is one that can be driven from a headless browser, which is what makes
1239
+ this verifiable without a person watching it.
1240
+ */
1241
+ Object.assign(globalThis, {
1242
+ __vgeo: viewer,
1243
+
1244
+ __open_url: (url) => viewer.load_url(url),
1245
+ __open_sample: () => viewer.open_sample().then(__state),
1246
+ __adapt: () => {
1247
+ viewer.adapt();
1248
+
1249
+ return __state();
1250
+ },
1251
+ __stream: () => viewer.stream().then(__state),
1252
+ __validate: () => viewer.validate().then((defects) => defects.map(String)),
1253
+ __state,
1254
+ });
1255
+
1256
+ /**
1257
+ * Everything a scripted session asks about, in one object.
1258
+ *
1259
+ * @returns {object}
1260
+ */
1261
+ function __state() {
1262
+ const reader = viewer.reader;
1263
+ const cut = viewer.cut;
1264
+
1265
+ return {
1266
+ open: reader !== undefined,
1267
+ asset_id: reader?.header.asset_id,
1268
+ total_pages: reader?.header.total_pages,
1269
+ total_clusters: reader?.header.total_clusters,
1270
+ resident_pages: reader?.resident_page_count ?? 0,
1271
+ resident_bytes: reader?.resident_bytes ?? 0,
1272
+ file_bytes: reader?.source.byte_length ?? 0,
1273
+ bytes_read: reader?.source.bytes_read ?? 0,
1274
+ requests: reader?.source.request_count ?? 0,
1275
+ clusters: cut.clusters.length,
1276
+ triangles: cut.triangle_count,
1277
+ clamped: cut.clamped,
1278
+ wants: cut.wants.length,
1279
+ broken_child_refs: cut.broken_child_refs,
1280
+ };
1281
+ }
1282
+
1283
+ viewer.start().catch((e) => {
1284
+ console.error(e);
1285
+
1286
+ document.getElementById('vgeo-panel').innerHTML =
1287
+ `<h1>.vgeo viewer</h1><div class="bad">${e.message ?? e}</div>`;
1288
+ });