@woosh/meep-engine 3.27.0 → 3.28.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 (255) hide show
  1. package/build/bundle-worker-terrain.js +1 -1
  2. package/package.json +1 -1
  3. package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts +15 -0
  4. package/src/core/geom/3d/mat4/m4_linear_determinant.d.ts.map +1 -0
  5. package/src/core/geom/3d/mat4/m4_linear_determinant.js +24 -0
  6. package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts +4 -2
  7. package/src/core/geom/3d/mat4/m4_normal_matrix3.d.ts.map +1 -1
  8. package/src/core/geom/3d/mat4/m4_normal_matrix3.js +21 -11
  9. package/src/engine/Engine.d.ts.map +1 -1
  10. package/src/engine/Engine.js +38 -1
  11. package/src/engine/graphics3/GraphicsEngine.d.ts +5 -1
  12. package/src/engine/graphics3/GraphicsEngine.d.ts.map +1 -1
  13. package/src/engine/graphics3/GraphicsEngine.js +834 -830
  14. package/src/shade/RENDERER_CONTRACT.md +19 -10
  15. package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +1 -1
  16. package/src/shade/playground/vgeo_runtime/README.md +27 -13
  17. package/src/shade/playground/vgeo_runtime/main.js +18 -5
  18. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts +18 -0
  19. package/src/shade/playground/vgeo_runtime/sample_asset.d.ts.map +1 -0
  20. package/src/shade/playground/{vgeo_viewer → vgeo_runtime}/sample_asset.js +9 -8
  21. package/src/shade/playground/vgeo_scene/README.md +408 -0
  22. package/src/shade/playground/vgeo_scene/index.html +144 -0
  23. package/src/shade/playground/vgeo_scene/main.d.ts +2 -0
  24. package/src/shade/playground/vgeo_scene/main.d.ts.map +1 -0
  25. package/src/shade/playground/vgeo_scene/main.js +1716 -0
  26. package/src/shade/renderer/Renderer.d.ts +4 -1
  27. package/src/shade/renderer/Renderer.d.ts.map +1 -1
  28. package/src/shade/renderer/Renderer.js +5 -2
  29. package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +1 -2
  30. package/src/shade/renderer/geometry/meshlet/MeshletBatch.d.ts.map +1 -1
  31. package/src/shade/renderer/geometry/meshlet/MeshletBatch.js +3 -29
  32. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts +22 -0
  33. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.d.ts.map +1 -0
  34. package/src/shade/renderer/geometry/meshlet/encoding/ENCODED_ATTRIBUTE_DEFAULT_VALUES.js +49 -0
  35. package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +4 -2
  36. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +10 -8
  37. package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +12 -11
  38. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts +1 -1
  39. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.d.ts.map +1 -1
  40. package/src/shade/renderer/geometry/virtual/build/VGeoBuildOptions.js +1 -1
  41. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.d.ts.map +1 -1
  42. package/src/shade/renderer/geometry/virtual/build/gltf/gltf_open_document.js +5 -9
  43. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts +32 -0
  44. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevel.d.ts.map +1 -0
  45. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts +59 -0
  46. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelOptions.d.ts.map +1 -0
  47. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts +44 -0
  48. package/src/shade/renderer/geometry/virtual/build/level/VGeoLevelSummary.d.ts.map +1 -0
  49. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts +36 -0
  50. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_levels.d.ts.map +1 -0
  51. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_levels.js → level/vgeo_build_levels.js} +61 -95
  52. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts +19 -0
  53. package/src/shade/renderer/geometry/virtual/build/level/vgeo_build_root_group.d.ts.map +1 -0
  54. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_root_group.js → level/vgeo_build_root_group.js} +1 -1
  55. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts +73 -0
  56. package/src/shade/renderer/geometry/virtual/build/mesh/VirtualGeometryMesh.d.ts.map +1 -0
  57. package/src/shade/renderer/geometry/virtual/build/{VirtualGeometryMesh.js → mesh/VirtualGeometryMesh.js} +7 -7
  58. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts +29 -0
  59. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_normals.d.ts.map +1 -0
  60. package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_normals.js → mesh/vgeo_compute_vertex_normals.js} +3 -3
  61. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts +31 -0
  62. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_compute_vertex_tangents.d.ts.map +1 -0
  63. package/src/shade/renderer/geometry/virtual/build/{vgeo_compute_vertex_tangents.js → mesh/vgeo_compute_vertex_tangents.js} +5 -5
  64. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts +46 -0
  65. package/src/shade/renderer/geometry/virtual/build/mesh/vgeo_normalize_source.d.ts.map +1 -0
  66. package/src/shade/renderer/geometry/virtual/build/{vgeo_normalize_source.js → mesh/vgeo_normalize_source.js} +9 -9
  67. package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts +13 -0
  68. package/src/shade/renderer/geometry/virtual/build/page/vgeo_assemble_pages.d.ts.map +1 -0
  69. package/src/shade/renderer/geometry/virtual/build/{vgeo_assemble_pages.js → page/vgeo_assemble_pages.js} +9 -9
  70. package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts +13 -0
  71. package/src/shade/renderer/geometry/virtual/build/page/vgeo_build_page_nodes.d.ts.map +1 -0
  72. package/src/shade/renderer/geometry/virtual/build/{vgeo_build_page_nodes.js → page/vgeo_build_page_nodes.js} +4 -4
  73. package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts +22 -0
  74. package/src/shade/renderer/geometry/virtual/build/page/vgeo_page_node_count.d.ts.map +1 -0
  75. package/src/shade/renderer/geometry/virtual/build/{vgeo_page_node_count.js → page/vgeo_page_node_count.js} +2 -2
  76. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts +52 -0
  77. package/src/shade/renderer/geometry/virtual/build/partition/VGeoFaceGraph.d.ts.map +1 -0
  78. package/src/shade/renderer/geometry/virtual/build/{VGeoFaceGraph.js → partition/VGeoFaceGraph.js} +1 -1
  79. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts +14 -0
  80. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_graph_components.d.ts.map +1 -0
  81. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts +29 -0
  82. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_graph.d.ts.map +1 -0
  83. package/src/shade/renderer/geometry/virtual/build/{vgeo_partition_graph.js → partition/vgeo_partition_graph.js} +2 -2
  84. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts +41 -0
  85. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.d.ts.map +1 -0
  86. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_partition_subgraph.js +92 -0
  87. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts +10 -0
  88. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set.d.ts.map +1 -0
  89. package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set.js → partition/vgeo_split_face_set.js} +12 -55
  90. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts +15 -0
  91. package/src/shade/renderer/geometry/virtual/build/partition/vgeo_split_face_set_packed.d.ts.map +1 -0
  92. package/src/shade/renderer/geometry/virtual/build/{vgeo_split_face_set_packed.js → partition/vgeo_split_face_set_packed.js} +3 -3
  93. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts +12 -0
  94. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_bounding_sphere.d.ts.map +1 -0
  95. package/src/shade/renderer/geometry/virtual/build/{vgeo_bounding_sphere.js → sphere/vgeo_bounding_sphere.js} +3 -3
  96. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts +18 -0
  97. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_containing_sphere.d.ts.map +1 -0
  98. package/src/shade/renderer/geometry/virtual/build/{vgeo_containing_sphere.js → sphere/vgeo_containing_sphere.js} +3 -3
  99. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts +9 -0
  100. package/src/shade/renderer/geometry/virtual/build/sphere/vgeo_sphere_inflate_to_contain.d.ts.map +1 -0
  101. package/src/shade/renderer/geometry/virtual/build/{vgeo_sphere_inflate_to_contain.js → sphere/vgeo_sphere_inflate_to_contain.js} +1 -1
  102. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts +24 -0
  103. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoGatheredFaces.d.ts.map +1 -0
  104. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts +20 -0
  105. package/src/shade/renderer/geometry/virtual/build/submesh/VGeoSubmesh.d.ts.map +1 -0
  106. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts +14 -0
  107. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_extract_submesh.d.ts.map +1 -0
  108. package/src/shade/renderer/geometry/virtual/build/{vgeo_extract_submesh.js → submesh/vgeo_extract_submesh.js} +5 -5
  109. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts +12 -0
  110. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_gather_faces.d.ts.map +1 -0
  111. package/src/shade/renderer/geometry/virtual/build/{vgeo_gather_faces.js → submesh/vgeo_gather_faces.js} +2 -2
  112. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts +11 -0
  113. package/src/shade/renderer/geometry/virtual/build/submesh/vgeo_narrow_indices.d.ts.map +1 -0
  114. package/src/shade/renderer/geometry/virtual/build/{vgeo_narrow_indices.js → submesh/vgeo_narrow_indices.js} +3 -3
  115. package/src/shade/renderer/geometry/virtual/build/vgeo_build.d.ts.map +1 -1
  116. package/src/shade/renderer/geometry/virtual/build/vgeo_build.js +9 -11
  117. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts +8 -2
  118. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.d.ts.map +1 -1
  119. package/src/shade/renderer/geometry/virtual/format/attribute/vgeo_attributes_read.js +8 -2
  120. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts +15 -0
  121. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.d.ts.map +1 -0
  122. package/src/shade/renderer/geometry/virtual/format/page/VGEO_GROUP_OFFSET.js +15 -0
  123. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts +28 -0
  124. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.d.ts.map +1 -1
  125. package/src/shade/renderer/geometry/virtual/format/payload/vgeo_encode_cluster_payload.js +7 -3
  126. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.d.ts.map +1 -1
  127. package/src/shade/renderer/geometry/virtual/format/read/vgeo_read_page.js +9 -4
  128. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.d.ts.map +1 -1
  129. package/src/shade/renderer/geometry/virtual/format/vgeo_validate_container.js +18 -5
  130. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.d.ts.map +1 -1
  131. package/src/shade/renderer/geometry/virtual/format/vgeo_write_container.js +9 -1
  132. package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +21 -2
  133. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts +52 -2
  134. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.d.ts.map +1 -1
  135. package/src/shade/renderer/geometry/virtual/runtime/GPUVirtualGeometryRuntime.js +97 -1
  136. package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +4 -4
  137. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.d.ts.map +1 -1
  138. package/src/shade/renderer/geometry/virtual/runtime/VGeoFeedbackLoop.js +10 -0
  139. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.d.ts.map +1 -1
  140. package/src/shade/renderer/geometry/virtual/runtime/VGeoResidency.js +59 -34
  141. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts +8 -8
  142. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.d.ts.map +1 -1
  143. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_access.js +11 -88
  144. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts +19 -0
  145. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.d.ts.map +1 -0
  146. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_arena.js +98 -0
  147. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts +31 -0
  148. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.d.ts.map +1 -0
  149. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_claim.js +99 -0
  150. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts +17 -0
  151. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.d.ts.map +1 -0
  152. package/src/shade/renderer/geometry/virtual/runtime/cut/chunk_vgeo_cut_queue.js +39 -0
  153. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.d.ts.map +1 -1
  154. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_reseed.js +7 -63
  155. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.d.ts.map +1 -1
  156. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_seed.js +13 -30
  157. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.d.ts.map +1 -1
  158. package/src/shade/renderer/geometry/virtual/runtime/cut/shader_vgeo_cut_traverse.js +6 -52
  159. package/src/shade/renderer/loader/gltf/load_gltf.d.ts.map +1 -1
  160. package/src/shade/renderer/loader/gltf/load_gltf.js +0 -19
  161. package/src/shade/renderer/material/chunk_material_draw_side.d.ts +14 -0
  162. package/src/shade/renderer/material/chunk_material_draw_side.d.ts.map +1 -0
  163. package/src/shade/renderer/material/chunk_material_draw_side.js +34 -0
  164. package/src/shade/renderer/material/standard/fragment_gbuffer.d.ts.map +1 -1
  165. package/src/shade/renderer/material/standard/fragment_gbuffer.js +8 -1
  166. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.d.ts.map +1 -1
  167. package/src/shade/renderer/path_tracer/shader/chunk_sample_material_data.js +13 -1
  168. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts +19 -5
  169. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.d.ts.map +1 -1
  170. package/src/shade/renderer/rasterize/bucket/construct_primitive_state.js +23 -5
  171. package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.d.ts.map +1 -1
  172. package/src/shade/renderer/rasterize/bucket/filter_materials_by_bucket.js +12 -5
  173. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts +22 -0
  174. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.d.ts.map +1 -0
  175. package/src/shade/renderer/rasterize/bucket/rasterization_opaque_buckets.js +36 -0
  176. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts +15 -0
  177. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.d.ts.map +1 -0
  178. package/src/shade/renderer/rasterize/chunk_triangle_winding_is_reversed.js +35 -0
  179. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts +10 -1
  180. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.d.ts.map +1 -1
  181. package/src/shade/renderer/rasterize/expand/bucket/RASTERIZATION_BUCKET_LIMIT.js +38 -29
  182. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts +5 -0
  183. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.d.ts.map +1 -1
  184. package/src/shade/renderer/rasterize/expand/bucket/chunk_rasterization_material_bucket.js +63 -55
  185. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.d.ts.map +1 -1
  186. package/src/shade/renderer/rasterize/expand/graph_meshlets_rasterize.js +1 -0
  187. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.d.ts.map +1 -1
  188. package/src/shade/renderer/rasterize/fast/graph_rasterize_scene_fast.js +44 -53
  189. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.d.ts.map +1 -1
  190. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_brick4.js +6 -2
  191. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.d.ts.map +1 -1
  192. package/src/shade/renderer/rasterize/forward/chunk_forward_shade_standard_fragment_ibl.js +6 -2
  193. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.d.ts.map +1 -1
  194. package/src/shade/renderer/rasterize/forward/vertex_shader_chunk.js +19 -2
  195. package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +7 -4
  196. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.d.ts.map +1 -1
  197. package/src/shade/renderer/rasterize/native/avboit/graph_rasterize_meshes_transparent_avboit.js +3 -2
  198. package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.d.ts.map +1 -1
  199. package/src/shade/renderer/rasterize/native/chunk_rasterize_triangle.js +15 -4
  200. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  201. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_alpha_tested_pass_descriptor.js +16 -5
  202. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.d.ts.map +1 -1
  203. package/src/shade/renderer/rasterize/native/depth/shadow_rasterization_pass_descriptor.js +16 -5
  204. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.d.ts.map +1 -1
  205. package/src/shade/renderer/rasterize/native/oit/graph_rasterize_meshes_transparent_oit.js +2 -1
  206. package/src/shade/renderer/rasterize/native/rasterization_shader_resources.d.ts.map +1 -1
  207. package/src/shade/renderer/rasterize/native/rasterization_shader_resources.js +4 -0
  208. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.d.ts.map +1 -1
  209. package/src/shade/renderer/rasterize/native/viz/viz_rasterization_alpha_tested_pass_descriptor.js +16 -7
  210. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.d.ts.map +1 -1
  211. package/src/shade/renderer/rasterize/standard/graph_rasterize_partial_opaque.js +78 -88
  212. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.d.ts.map +1 -1
  213. package/src/shade/renderer/rasterize/standard/graph_rasterize_remaining_opaque.js +21 -31
  214. package/src/shade/renderer/scene/GPUSceneContext.d.ts.map +1 -1
  215. package/src/shade/renderer/scene/GPUSceneContext.js +2 -0
  216. package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts +19 -0
  217. package/src/shade/renderer/scene/NODE3D_STRUCT.d.ts.map +1 -1
  218. package/src/shade/renderer/scene/NODE3D_STRUCT.js +34 -0
  219. package/src/shade/renderer/scene/chunk_node3d_flags.d.ts +9 -0
  220. package/src/shade/renderer/scene/chunk_node3d_flags.d.ts.map +1 -0
  221. package/src/shade/renderer/scene/chunk_node3d_flags.js +23 -0
  222. package/src/shade/renderer/scene/chunk_scene_database_access.d.ts.map +1 -1
  223. package/src/shade/renderer/scene/chunk_scene_database_access.js +15 -1
  224. package/src/shade/renderer/scene/rows/GPUSceneRows.d.ts.map +1 -1
  225. package/src/shade/renderer/scene/rows/GPUSceneRows.js +9 -1
  226. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts +7 -0
  227. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.d.ts.map +1 -1
  228. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_compute_normal_matrix_from_m4.js +16 -4
  229. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts +12 -0
  230. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.d.ts.map +1 -0
  231. package/src/shade/renderer/shader/chunk/geometry/mat4/chunk_mat4_linear_determinant.js +18 -0
  232. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts +24 -0
  233. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.d.ts.map +1 -0
  234. package/src/shade/renderer/shader/chunk/geometry/triangle/chunk_triangle_list_reverse_winding.js +33 -0
  235. package/src/shade/playground/vgeo_viewer/README.md +0 -150
  236. package/src/shade/playground/vgeo_viewer/cut_geometry.js +0 -460
  237. package/src/shade/playground/vgeo_viewer/index.html +0 -77
  238. package/src/shade/playground/vgeo_viewer/main.js +0 -1343
  239. package/src/shade/playground/vgeo_viewer/select_cut.js +0 -481
  240. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts +0 -258
  241. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyManager.d.ts.map +0 -1
  242. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts +0 -49
  243. package/src/shade/renderer/geometry/virtual/residency/VGeoResidencyOptions.d.ts.map +0 -1
  244. package/src/shade/renderer/loader/gltf/fix_up_material_sides.js +0 -109
  245. package/src/shade/renderer/rasterize/expand/graph_triangles_filter_by_material_side.js +0 -78
  246. package/src/shade/renderer/rasterize/expand/shader_filter_triangle_by_material_side.js +0 -100
  247. package/src/shade/renderer/rasterize/forward/chunk_material_side_should_draw.js +0 -26
  248. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts +0 -3
  249. package/src/shade/renderer/shader/chunk/jobs/chunk_job_system.d.ts.map +0 -1
  250. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevel.js → level/VGeoLevel.js} +0 -0
  251. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelOptions.js → level/VGeoLevelOptions.js} +0 -0
  252. /package/src/shade/renderer/geometry/virtual/build/{VGeoLevelSummary.js → level/VGeoLevelSummary.js} +0 -0
  253. /package/src/shade/renderer/geometry/virtual/build/{vgeo_graph_components.js → partition/vgeo_graph_components.js} +0 -0
  254. /package/src/shade/renderer/geometry/virtual/build/{VGeoGatheredFaces.js → submesh/VGeoGatheredFaces.js} +0 -0
  255. /package/src/shade/renderer/geometry/virtual/build/{VGeoSubmesh.js → submesh/VGeoSubmesh.js} +0 -0
@@ -1,460 +0,0 @@
1
- import { assert } from "../../../core/assert.js";
2
- import { UINT16_MAX } from "../../../core/binary/UINT16_MAX.js";
3
- import { hsv_to_rgb } from "../../../core/color/hsv/hsv_to_rgb.js";
4
- import {
5
- decode_octahedron_to_unit
6
- } from "../../../core/geom/3d/normal/octahedron/decode_octahedron_to_unit.js";
7
- import { Attribute } from "../../renderer/geometry/Attribute.js";
8
- import { Geometry } from "../../renderer/geometry/Geometry.js";
9
- import { StandardAttributes } from "../../renderer/geometry/StandardAttributes.js";
10
- import {
11
- VGEO_ATTRIBUTE
12
- } from "../../renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTE.js";
13
- import {
14
- VGEO_ATTRIBUTES
15
- } from "../../renderer/geometry/virtual/format/attribute/VGEO_ATTRIBUTES.js";
16
- import {
17
- vgeo_payload_attribute_offset
18
- } from "../../renderer/geometry/virtual/format/payload/vgeo_payload_attribute_offset.js";
19
-
20
- /**
21
- * Turning a cut into something drawable.
22
- *
23
- * Payloads are `SHADE_MESHLET_V1`'s (`VGEO_FORMAT.md` §8): the index section first, three 8-bit
24
- * local indices per triangle, then the attribute sections. Position is always read — it is raw
25
- * float32, never constant-compressed — and the stored normal section only when a normal display asks
26
- * for it, because the direct geometry path carries position and colour per vertex and nowhere to put
27
- * the rest.
28
- *
29
- * @author Alex Goldring
30
- * @copyright Company Named Limited (c) 2026
31
- */
32
-
33
- /**
34
- * Everything in the container is little-endian (§2).
35
- * @type {boolean}
36
- */
37
- const LE = true;
38
-
39
- /**
40
- * The `encoding_flags` bit that says a cluster's normal section holds one constant-compressed word
41
- * for the whole cluster instead of one per vertex.
42
- * @type {number}
43
- */
44
- const NORMAL_COMPRESSION_FLAG = VGEO_ATTRIBUTES[VGEO_ATTRIBUTE.NORMAL].compression_flag;
45
-
46
- /**
47
- * What a cluster's colour is keyed on.
48
- *
49
- * The two normal modes are not keyed on the cluster at all: they paint every vertex with its own
50
- * direction, and the cluster boundaries go with it. `stored normal` is the container's own
51
- * {@link VGEO_ATTRIBUTE.NORMAL}, decoded out of the payload — the only mode that shows an attribute
52
- * the file carries rather than something derived from it. `geometric normal` is the area-weighted
53
- * normal of the decoded triangles, which is what every other mode shades with. The pair is the
54
- * point: they agree where the builder's normals still describe the geometry it shipped, and a source
55
- * with no normals at all makes the first one flat.
56
- *
57
- * `clamp` is the streaming one: it paints the clusters a coarser page is standing in for, so the
58
- * regions still waiting on bytes are visible as regions rather than as a number in a panel.
59
- *
60
- * @enum {string}
61
- */
62
- export const VGEO_COLOR_MODE = {
63
- Cluster: 'cluster',
64
- Group: 'group',
65
- Page: 'page',
66
- Level: 'level',
67
- Error: 'error',
68
- Clamp: 'clamp',
69
- StoredNormal: 'stored normal',
70
- GeometricNormal: 'geometric normal',
71
- };
72
-
73
- /**
74
- * Key colours are spread by the golden ratio so that adjacent ids never land on adjacent hues —
75
- * neighbouring clusters are exactly what has to be told apart.
76
- * @type {number}
77
- */
78
- const HUE_STEP = 0.6180339887498949;
79
-
80
- /**
81
- * Key lights, baked into vertex colour.
82
- *
83
- * The direct path carries position and colour per vertex and nothing else — no normal reaches the
84
- * shader — so shading happens here, once per cut, against normals derived from the decoded
85
- * triangles. Two opposed lights and a generous ambient, so that no part of the surface is black and
86
- * every cluster's colour stays readable wherever it faces.
87
- *
88
- * @type {number[]}
89
- */
90
- const KEY_LIGHT = [0.35, 0.78, 0.52];
91
-
92
- /**
93
- * @type {number[]}
94
- */
95
- const FILL_LIGHT = [-0.55, -0.25, -0.79];
96
-
97
- /**
98
- * Ceiling on a baked colour's brightest channel.
99
- *
100
- * The pass draws at `AfterTransparency`, so everything it writes still goes through the tonemapper,
101
- * and the tonemapper desaturates as it approaches white. Pushed to 1.0 the clusters come out pastel
102
- * and stop being tellable apart, which defeats the only thing the colour is for — so the shading
103
- * range is deliberately kept below it.
104
- *
105
- * @type {number}
106
- */
107
- const COLOR_CEILING = 0.9;
108
-
109
- /**
110
- * One cluster's worth of decoded stored normals, reused across clusters.
111
- *
112
- * Sized for the largest cluster a `u8` `vertex_count` can *state* rather than the largest the format
113
- * permits, which is 128. The two differ only on a file that has broken §11 — and with validation off
114
- * by default, nothing upstream has looked. A scratch that is twice as large as it needs to be costs
115
- * three kilobytes; a short one would come back as a handful of quietly wrong colours.
116
- *
117
- * @type {Float32Array}
118
- */
119
- const stored_normals = new Float32Array(256 * 3);
120
-
121
- /**
122
- * One decoded direction, on its way from the octahedral codec into a caller's array.
123
- * @type {Float32Array}
124
- */
125
- const scratch_direction = new Float32Array(3);
126
-
127
- /**
128
- * Decode one cluster's stored normal section into unit vectors.
129
- *
130
- * The section is one octahedral `u32` per vertex, or a single word for the whole cluster when the
131
- * encoder found every vertex agreeing — which is also what a source lacking normals encodes to, so
132
- * the constant case is the ordinary one and not an exception. A stride of zero is what reads it:
133
- * every vertex fetches the same word, and the loop does not have to know which case it is in.
134
- *
135
- * @param {VGeoPage} page
136
- * @param {number} cluster index within the page
137
- * @param {Float32Array} out at least `3 · vertex_count` long
138
- */
139
- function read_cluster_normals(page, cluster, out) {
140
- const vertex_count = page.vertex_count[cluster];
141
-
142
- assert.greaterThanOrEqual(
143
- out.length, vertex_count * 3, 'out must hold three components per cluster vertex'
144
- );
145
-
146
- const encoding_flags = page.encoding_flags[cluster];
147
-
148
- const at = page.payload_at(cluster)
149
- + vgeo_payload_attribute_offset(
150
- VGEO_ATTRIBUTE.NORMAL, vertex_count, page.triangle_count[cluster], encoding_flags
151
- );
152
-
153
- const stride = (encoding_flags & NORMAL_COMPRESSION_FLAG) === 0 ? 4 : 0;
154
-
155
- for (let i = 0; i < vertex_count; i++) {
156
- const word = page.data.getUint32(at + i * stride, LE);
157
-
158
- const u = ((word & 0xFFFF) / UINT16_MAX) * 2 - 1;
159
- const v = (((word >>> 16) & 0xFFFF) / UINT16_MAX) * 2 - 1;
160
-
161
- decode_octahedron_to_unit(scratch_direction, 0, u, v);
162
-
163
- /*
164
- The encoder hands the octahedral codec `(nx, nz, ny)` — Shade's own convention, matched so
165
- that a `.vgeo` payload is byte for byte a `MeshletBatch` one — so the decode comes back in
166
- that order and has to be put back.
167
- */
168
- out[i * 3] = scratch_direction[0];
169
- out[i * 3 + 1] = scratch_direction[2];
170
- out[i * 3 + 2] = scratch_direction[1];
171
- }
172
- }
173
-
174
- /**
175
- * Paint a run of vertices with their own directions and no shading: `rgb = n · 0.5 + 0.5`, scaled by
176
- * {@link COLOR_CEILING} for the same reason every other mode is.
177
- *
178
- * Unlit on purpose. A direction multiplied by how much light it happens to catch is unreadable
179
- * exactly where reading it matters — a normal facing away from both lights would come out black, and
180
- * black is not a direction.
181
- *
182
- * @param {Float32Array} colors four per vertex
183
- * @param {number} first index of the run's first vertex
184
- * @param {number} count vertices in the run
185
- * @param {Float32Array} directions unit vectors, three components apiece
186
- * @param {number} directions_offset index of the run's first component within `directions`
187
- */
188
- function paint_directions(colors, first, count, directions, directions_offset) {
189
- for (let i = 0; i < count; i++) {
190
- const d = directions_offset + i * 3;
191
- const o = (first + i) * 4;
192
-
193
- colors[o] = COLOR_CEILING * (directions[d] * 0.5 + 0.5);
194
- colors[o + 1] = COLOR_CEILING * (directions[d + 1] * 0.5 + 0.5);
195
- colors[o + 2] = COLOR_CEILING * (directions[d + 2] * 0.5 + 0.5);
196
- colors[o + 3] = 1;
197
- }
198
- }
199
-
200
- /**
201
- * A cut, decoded into one geometry.
202
- *
203
- * Nothing about it depends on where the camera is: the mesh is drawn solid and the depth buffer
204
- * orders it, so the triangle list is uploaded once when the cut is taken and never touched again.
205
- */
206
- export class VGeoCutGeometry {
207
- /**
208
- * Position and colour, indexed by {@link triangles}.
209
- * @type {Geometry}
210
- */
211
- geometry = new Geometry();
212
-
213
- /**
214
- * `3 · triangle_count` — the full triangle list, in cluster order, and the geometry's index.
215
- * @type {Uint32Array}
216
- */
217
- triangles = new Uint32Array(0);
218
-
219
- /**
220
- * @type {number}
221
- */
222
- triangle_count = 0;
223
-
224
- /**
225
- * @type {number}
226
- */
227
- vertex_count = 0;
228
- }
229
-
230
- /**
231
- * Decode the selected clusters into one geometry.
232
- *
233
- * @param {VGeoCut} cut
234
- * @param {VGEO_COLOR_MODE} color_mode
235
- * @returns {VGeoCutGeometry}
236
- */
237
- export function vgeo_build_cut_geometry(cut, color_mode) {
238
- const vertex_count = cut.vertex_count;
239
- const triangle_count = cut.triangle_count;
240
-
241
- const positions = new Float32Array(vertex_count * 3);
242
- const colors = new Float32Array(vertex_count * 4);
243
- const normals = new Float32Array(vertex_count * 3);
244
-
245
- const result = new VGeoCutGeometry();
246
-
247
- result.triangles = new Uint32Array(triangle_count * 3);
248
- result.triangle_count = triangle_count;
249
- result.vertex_count = vertex_count;
250
-
251
- const triangles = result.triangles;
252
-
253
- const count = cut.clusters.length;
254
-
255
- /*
256
- The error ramp spans the *cut's* own errors, not the file's. Normalizing against the coarsest
257
- error in the container would be defensible and useless: a fine cut's clusters all sit orders of
258
- magnitude below it and the whole model comes out one flat colour. What the question actually is
259
- — which parts of this cut settled for more error than the rest — is a question about this cut.
260
- */
261
- let error_low = Number.POSITIVE_INFINITY;
262
- let error_high = 0;
263
-
264
- for (let c = 0; c < count; c++) {
265
- const error = cut.pages[c].self_error[cut.clusters[c]];
266
-
267
- error_low = Math.min(error_low, error);
268
- error_high = Math.max(error_high, error);
269
- }
270
-
271
- const error_span = error_high - error_low;
272
-
273
- /**
274
- * First vertex of each selected cluster, so colour can be applied per cluster after the normals
275
- * are known.
276
- * @type {Uint32Array}
277
- */
278
- const cluster_vertex_first = new Uint32Array(count);
279
-
280
- let vertex_cursor = 0;
281
- let triangle_cursor = 0;
282
-
283
- for (let c = 0; c < count; c++) {
284
- const page = cut.pages[c];
285
- const id = cut.clusters[c];
286
-
287
- const cluster_vertices = page.vertex_count[id];
288
- const cluster_triangles = page.triangle_count[id];
289
-
290
- const payload = page.payload_at(id);
291
-
292
- cluster_vertex_first[c] = vertex_cursor;
293
-
294
- const position_at = payload + vgeo_payload_attribute_offset(
295
- VGEO_ATTRIBUTE.POSITION, cluster_vertices, cluster_triangles, page.encoding_flags[id]
296
- );
297
-
298
- /*
299
- Read a word at a time rather than viewed in place: a Float32Array view demands 4-byte
300
- alignment against the *page's* buffer, which is a property of where the decode happened to
301
- land it and not something the format promises.
302
- */
303
- for (let i = 0; i < cluster_vertices * 3; i++) {
304
- positions[vertex_cursor * 3 + i] = page.data.getFloat32(position_at + i * 4, LE);
305
- }
306
-
307
- for (let i = 0; i < cluster_triangles * 3; i++) {
308
- triangles[triangle_cursor * 3 + i] = vertex_cursor + page.bytes[payload + i];
309
- }
310
-
311
- vertex_cursor += cluster_vertices;
312
- triangle_cursor += cluster_triangles;
313
- }
314
-
315
- assert.equal(vertex_cursor, vertex_count, 'decoded vertices must match the cut');
316
- assert.equal(triangle_cursor, triangle_count, 'decoded triangles must match the cut');
317
-
318
- // Area-weighted vertex normals, which is all shading reads. Clusters share no vertices, so
319
- // accumulating over the whole list still gives each cluster its own smoothing — the crease that
320
- // leaves at a cluster seam is a feature here, not an artefact.
321
- for (let t = 0; t < triangle_count; t++) {
322
- const a = triangles[t * 3] * 3;
323
- const b = triangles[t * 3 + 1] * 3;
324
- const c = triangles[t * 3 + 2] * 3;
325
-
326
- const abx = positions[b] - positions[a];
327
- const aby = positions[b + 1] - positions[a + 1];
328
- const abz = positions[b + 2] - positions[a + 2];
329
-
330
- const acx = positions[c] - positions[a];
331
- const acy = positions[c + 1] - positions[a + 1];
332
- const acz = positions[c + 2] - positions[a + 2];
333
-
334
- const nx = aby * acz - abz * acy;
335
- const ny = abz * acx - abx * acz;
336
- const nz = abx * acy - aby * acx;
337
-
338
- normals[a] += nx; normals[a + 1] += ny; normals[a + 2] += nz;
339
- normals[b] += nx; normals[b + 1] += ny; normals[b + 2] += nz;
340
- normals[c] += nx; normals[c + 1] += ny; normals[c + 2] += nz;
341
- }
342
-
343
- // Normalized here rather than where they are read, because two things read them now — the
344
- // shading, and `geometric normal` — and a direction is the same direction for both.
345
- for (let v = 0; v < vertex_count; v++) {
346
- const n = v * 3;
347
-
348
- const length = Math.hypot(normals[n], normals[n + 1], normals[n + 2]);
349
-
350
- // A vertex left with no area around it has no direction to give. Zero shades as ambient and
351
- // displays as mid grey, and both say "nothing here" rather than inventing an answer.
352
- const scale = length > 0 ? 1 / length : 0;
353
-
354
- normals[n] *= scale;
355
- normals[n + 1] *= scale;
356
- normals[n + 2] *= scale;
357
- }
358
-
359
- const tint = new Float32Array(3);
360
-
361
- for (let c = 0; c < count; c++) {
362
- const page = cut.pages[c];
363
- const id = cut.clusters[c];
364
-
365
- const first = cluster_vertex_first[c];
366
- const vertices = page.vertex_count[id];
367
-
368
- if (color_mode === VGEO_COLOR_MODE.StoredNormal) {
369
- read_cluster_normals(page, id, stored_normals);
370
-
371
- paint_directions(colors, first, vertices, stored_normals, 0);
372
-
373
- continue;
374
- }
375
-
376
- if (color_mode === VGEO_COLOR_MODE.GeometricNormal) {
377
- paint_directions(colors, first, vertices, normals, first * 3);
378
-
379
- continue;
380
- }
381
-
382
- if (color_mode === VGEO_COLOR_MODE.Error) {
383
- // cool where the cut is refined, hot where it settled for the most error
384
- const t = error_span > 0 ? (page.self_error[id] - error_low) / error_span : 0;
385
-
386
- hsv_to_rgb(tint, 0, 0.68 * (1 - t), 0.9, 1);
387
- } else if (color_mode === VGEO_COLOR_MODE.Clamp) {
388
- /*
389
- Two colours and nothing in between. Amber is a cluster standing in for a page that has
390
- not arrived; slate is the cut the container's metric actually selects. The question this
391
- mode answers is where, not how much, so a ramp would only make it harder to read.
392
- */
393
- const waiting = cut.clamped_keys.has(page.index * 65536 + id);
394
-
395
- tint[0] = waiting ? 1 : 0.42;
396
- tint[1] = waiting ? 0.66 : 0.52;
397
- tint[2] = waiting ? 0.16 : 0.62;
398
- } else {
399
- hsv_to_rgb(tint, 0, (color_key(page, id, color_mode) * HUE_STEP) % 1, 0.85, 1);
400
- }
401
-
402
- const end = first + vertices;
403
-
404
- for (let v = first; v < end; v++) {
405
- const n = v * 3;
406
-
407
- const nx = normals[n];
408
- const ny = normals[n + 1];
409
- const nz = normals[n + 2];
410
-
411
- const key_term = Math.max(
412
- 0, nx * KEY_LIGHT[0] + ny * KEY_LIGHT[1] + nz * KEY_LIGHT[2]
413
- );
414
-
415
- const fill_term = Math.max(
416
- 0, nx * FILL_LIGHT[0] + ny * FILL_LIGHT[1] + nz * FILL_LIGHT[2]
417
- );
418
-
419
- const shade = COLOR_CEILING * (0.22 + 0.60 * key_term + 0.18 * fill_term);
420
-
421
- colors[v * 4] = tint[0] * shade;
422
- colors[v * 4 + 1] = tint[1] * shade;
423
- colors[v * 4 + 2] = tint[2] * shade;
424
- colors[v * 4 + 3] = 1;
425
- }
426
- }
427
-
428
- result.geometry.addAttribute(Attribute.from(positions, 3, StandardAttributes.Position));
429
- result.geometry.addAttribute(Attribute.from(colors, 4, StandardAttributes.Color));
430
- result.geometry.index = Attribute.from(result.triangles, 1, StandardAttributes.Index);
431
-
432
- return result;
433
- }
434
-
435
- /**
436
- * What a hue is spread from, for the modes that key on an identity rather than on a value.
437
- *
438
- * Page index enters the cluster and group keys because clusters are numbered per page now, exactly
439
- * as the format numbers them — without it, cluster 0 of every page would come out the same colour.
440
- *
441
- * @param {VGeoPage} page
442
- * @param {number} cluster
443
- * @param {VGEO_COLOR_MODE} color_mode
444
- * @returns {number}
445
- */
446
- function color_key(page, cluster, color_mode) {
447
- switch (color_mode) {
448
- case VGEO_COLOR_MODE.Group:
449
- return page.index * 65536 + page.group_of_cluster[cluster];
450
- case VGEO_COLOR_MODE.Page:
451
- return page.index;
452
- case VGEO_COLOR_MODE.Level:
453
- // A non-root page spans one contiguous band, so its min is the level of everything in
454
- // it; the root page is the one that can span several and there is nothing per cluster to
455
- // read it from.
456
- return page.min_level;
457
- default:
458
- return page.index * 65536 + cluster;
459
- }
460
- }
@@ -1,77 +0,0 @@
1
- <!doctype html>
2
- <html lang="en">
3
- <head>
4
- <meta charset="utf-8">
5
- <title>meep — .vgeo viewer</title>
6
-
7
- <!-- an empty icon rather than none: the browser asks for /favicon.ico otherwise, and a 404 in
8
- the console of a debugging tool is noise where noise is the signal -->
9
- <link rel="icon" href="data:,">
10
-
11
- <style>
12
- :root { color-scheme: dark; }
13
-
14
- html, body { height: 100%; margin: 0; overflow: hidden; background: #070b10; }
15
-
16
- /* the canvas is appended to the body at start-up, so it comes after both of these in DOM
17
- order and would paint over them without a stacking order of their own */
18
- #vgeo-panel {
19
- position: absolute; top: 0; right: 0; width: 340px; max-height: 100vh; overflow-y: auto;
20
- z-index: 10; padding: 12px 14px; box-sizing: border-box;
21
- font: 12px/1.45 ui-monospace, "Cascadia Mono", Consolas, monospace;
22
- color: #dfe6ee; background: rgba(12, 16, 22, 0.88);
23
- border-left: 1px solid #2b3947;
24
- }
25
-
26
- #vgeo-panel h1 { margin: 0 0 8px; font-size: 13px; letter-spacing: 0.06em; color: #7fd2ff; }
27
-
28
- #vgeo-panel h2 {
29
- margin: 14px 0 6px; font-size: 11px; letter-spacing: 0.12em; text-transform: uppercase;
30
- color: #6b7c8d; border-bottom: 1px solid #24313d; padding-bottom: 3px;
31
- }
32
-
33
- #vgeo-panel .row { display: flex; justify-content: space-between; gap: 8px; }
34
- #vgeo-panel .row span:last-child { color: #f2f6fa; text-align: right; }
35
- #vgeo-panel .count { font-size: 30px; line-height: 1.1; color: #8fe388; }
36
- #vgeo-panel .muted { color: #6b7c8d; }
37
- #vgeo-panel .bad { color: #ff8a7a; }
38
- #vgeo-panel .warn { color: #ffbe55; }
39
- #vgeo-panel .good { color: #8fe388; }
40
-
41
- #vgeo-panel button {
42
- width: 100%; margin: 8px 0 2px; padding: 7px; cursor: pointer;
43
- font: inherit; color: #061018; background: #7fd2ff; border: 0; border-radius: 3px;
44
- }
45
-
46
- #vgeo-panel button:hover { background: #a5e0ff; }
47
- #vgeo-panel button:disabled { opacity: 0.4; cursor: default; }
48
- #vgeo-panel label { display: flex; align-items: center; gap: 6px; margin: 3px 0; cursor: pointer; }
49
- #vgeo-panel input[type=range] { width: 100%; }
50
-
51
- #vgeo-panel select {
52
- width: 100%; font: inherit; background: #16202b; color: #dfe6ee;
53
- border: 1px solid #2b3947; padding: 3px;
54
- }
55
-
56
- #vgeo-panel ol { margin: 4px 0; padding-left: 18px; }
57
-
58
- #vgeo-drop {
59
- position: absolute; inset: 0; z-index: 20;
60
- display: none; align-items: center; justify-content: center;
61
- font: 20px ui-monospace, monospace; color: #7fd2ff;
62
- background: rgba(6, 12, 20, 0.82); border: 3px dashed #7fd2ff; box-sizing: border-box;
63
- }
64
-
65
- #vgeo-drop.active { display: flex; }
66
- </style>
67
- </head>
68
- <body>
69
-
70
- <div id="vgeo-drop">drop a .vgeo file</div>
71
-
72
- <div id="vgeo-panel"><h1>.vgeo viewer</h1></div>
73
-
74
- <script type="module" src="./main.js"></script>
75
-
76
- </body>
77
- </html>