@woosh/meep-engine 3.60.4 → 3.60.6
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.
- package/CHANGELOG.md +2621 -0
- package/CONTRIBUTING.md +7 -0
- package/MIGRATION_2_TO_3.md +136 -0
- package/SECURITY.md +4 -0
- package/editor/EditorCameraNavigation.d.ts +2 -1
- package/editor/EditorCameraNavigation.d.ts.map +1 -1
- package/editor/EditorCameraNavigation.js +51 -57
- package/package.json +6 -2
- package/src/engine/EngineHarness.d.ts +3 -9
- package/src/engine/EngineHarness.d.ts.map +1 -1
- package/src/engine/EngineHarness.js +6 -8
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts +9 -6
- package/src/engine/graphics/camera/makeOrbitalCameraController.d.ts.map +1 -1
- package/src/engine/graphics/camera/makeOrbitalCameraController.js +44 -71
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts +64 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/MomentumAxis.js +187 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts +86 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.d.ts.map +1 -0
- package/src/engine/graphics/camera/orbital/OrbitalCameraRig.js +319 -0
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts +34 -10
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraController.js +116 -30
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts +1 -7
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.d.ts.map +1 -1
- package/src/engine/graphics/ecs/camera/topdown/TopDownCameraControllerSystem.js +1 -37
- package/src/engine/graphics/ecs/water/Water.d.ts +8 -0
- package/src/engine/graphics/ecs/water/Water.d.ts.map +1 -1
- package/src/engine/graphics/ecs/water/Water.js +8 -0
- package/src/engine/graphics3/WaterSystem.d.ts.map +1 -1
- package/src/engine/graphics3/WaterSystem.js +731 -734
- package/src/engine/graphics3/decal/DecalTileShader.d.ts +61 -0
- package/src/engine/graphics3/decal/DecalTileShader.d.ts.map +1 -0
- package/src/engine/graphics3/decal/DecalTileShader.js +138 -0
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts +10 -4
- package/src/engine/graphics3/decal/GPUDecalRenderer.d.ts.map +1 -1
- package/src/engine/graphics3/decal/GPUDecalRenderer.js +149 -44
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts +25 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.d.ts.map +1 -0
- package/src/engine/graphics3/decal/chunk_decal_tile_vertex.js +55 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts +22 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/graph_gather_decal_tiles.js +70 -0
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts +7 -5
- package/src/engine/graphics3/decal/shader_decal_composite.d.ts.map +1 -1
- package/src/engine/graphics3/decal/shader_decal_composite.js +48 -44
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts +12 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_decal_tile_copy.js +78 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts +11 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.d.ts.map +1 -0
- package/src/engine/graphics3/decal/shader_gather_decal_tiles.js +80 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts +13 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.d.ts.map +1 -0
- package/src/engine/input/devices/mouse/MouseEventButtons.js +23 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts +4 -0
- package/src/engine/input/ecs/controllers/KeyboardCameraController.d.ts.map +1 -1
- package/src/engine/input/ecs/controllers/KeyboardCameraController.js +9 -45
- package/src/engine/physics/fluid/ecs/FluidObstacleSystem.d.ts +4 -4
- package/src/shade/playground/water_refraction/README.md +5 -6
- package/src/shade/playground/water_refraction/index.html +1 -1
- package/src/shade/renderer/Renderer.d.ts +11 -0
- package/src/shade/renderer/Renderer.d.ts.map +1 -1
- package/src/shade/renderer/Renderer.js +50 -6
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts +40 -80
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.d.ts.map +1 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraController.js +197 -147
- package/src/shade/renderer/fluid/GPUFluidCascade.d.ts +3 -3
- package/src/shade/renderer/fluid/GPUFluidCascadeStack.d.ts +1 -1
- package/src/shade/renderer/fluid/forcing/GPUFluidForcing.d.ts +6 -6
- package/src/shade/renderer/fluid/pressure/GPUFluidPressureSolve.d.ts +1 -1
- package/src/shade/renderer/fluid/query/GPUFluidQueries.d.ts +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts +28 -45
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/GPUGeometrySDFManager.js +111 -119
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts +22 -3
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.d.ts.map +1 -1
- package/src/shade/renderer/geometry/sdf/cards/GPUMeshCardSets.js +84 -3
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts +19 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_proxy_triangle_limit.js +25 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts +31 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/proxy/vgeo_to_proxy_mesh.js +343 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts +15 -0
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/VirtualGeometry.js +38 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts +17 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.d.ts.map +1 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_meshlet_metadata_write.js +29 -0
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/runtime/vgeo_runtime_meshlet_batch.js +7 -13
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts +28 -59
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.d.ts.map +1 -1
- package/src/shade/renderer/geometry/virtual/sdf/VGeoSDFProxies.js +84 -789
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/GPUProbeClipmapGI.js +1 -8
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts +7 -6
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/ProbeClipmapSceneHolds.js +12 -11
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.d.ts +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/brick/mesh/chunk_mesh_brick_instance.js +2 -2
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts +1 -4
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/GPUProbeClipmap.js +1 -10
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts +5 -15
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/chunk_probe_clipmap_hit_surface.js +6 -34
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.d.ts.map +1 -1
- package/src/shade/renderer/global_illumination/probe_clipmap/probe/shader_probe_clipmap_shade.js +1 -7
- package/src/shade/renderer/hiz/HZBFootprint.d.ts +14 -0
- package/src/shade/renderer/hiz/HZBFootprint.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZBFootprint.js +16 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_X.js +11 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts +10 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/HZB_FOOTPRINT_Y.js +11 -0
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts +0 -7
- package/src/shade/renderer/hiz/HierarchicalZBuffer.d.ts.map +1 -1
- package/src/shade/renderer/hiz/HierarchicalZBuffer.js +405 -350
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_x.js +27 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts +12 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.d.ts.map +1 -0
- package/src/shade/renderer/hiz/chunk_hzb_footprint_y.js +27 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts +14 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.d.ts.map +1 -0
- package/src/shade/renderer/hiz/hzb_footprint_texels.js +34 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts +0 -5
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.d.ts.map +1 -1
- package/src/shade/renderer/hiz/shader_hzb_reduce_any.js +37 -57
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts +11 -0
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0.d.ts.map +1 -0
- package/src/shade/renderer/hiz/{shader_hzb_reduce_mip0_clip.js → shader_hzb_reduce_mip0.js} +120 -111
- package/src/shade/renderer/loader/gltf/tiny-gltf.d.ts +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts +11 -1
- package/src/shade/renderer/material/GPUMaterialManager.d.ts.map +1 -1
- package/src/shade/renderer/material/GPUMaterialManager.js +16 -8
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts +12 -12
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.d.ts.map +1 -1
- package/src/shade/renderer/material/resident/GPUResidentMaterialContext.js +17 -118
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts +7 -3
- package/src/shade/renderer/postprocess/gtao/GTAO.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/GTAO.js +26 -13
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts +14 -0
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/ao_reproject_shader.js +196 -68
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao.js +42 -28
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.d.ts.map +1 -1
- package/src/shade/renderer/postprocess/gtao/fragment_shader_gtao_with_irradiance.js +429 -414
- package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts +16 -0
- package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.d.ts.map +1 -0
- package/src/shade/renderer/postprocess/gtao/shader_gtao_spatial_denoise.js +156 -0
- package/src/shade/renderer/scene/GPUSceneContext.d.ts +2 -2
- package/src/shade/renderer/scene/GPUSceneContext.js +5 -5
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.d.ts.map +1 -1
- package/src/shade/renderer/shadow/map/GPUSceneShadowmapContext.js +7 -2
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts +0 -6
- package/src/shade/renderer/water/GPUWaterRenderer.d.ts.map +1 -1
- package/src/shade/renderer/water/GPUWaterRenderer.js +12 -17
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts +35 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.d.ts.map +1 -0
- package/src/shade/renderer/water/medium/graph_water_meshlets.js +89 -0
- package/src/shade/renderer/water/query/GPUWaterQueries.d.ts +1 -1
- package/src/shade/renderer/water/shader_water.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water.js +22 -13
- package/src/shade/renderer/water/shader_water_avboit.d.ts.map +1 -1
- package/src/shade/renderer/water/shader_water_avboit.js +7 -7
- package/src/shade/renderer/water/surface/graph_water_tessellation.d.ts +1 -1
- package/src/shade/renderer/water/surface/graph_water_tessellation.js +1 -1
- package/src/shade/wgsl/emulator/WGSLJavaScriptCompiler.js +9 -1
- package/editor/REWORK_PLAN_2026_08.md +0 -692
- package/src/CODEC_LAYOUT_VERIFICATION.md +0 -419
- package/src/CORRECTNESS_HUNT_2026_07_24.md +0 -142
- package/src/DUPLICATION_AUDIT_2026_08_07/00_core_reuse_surface.md +0 -738
- package/src/DUPLICATION_AUDIT_2026_08_07/A_core_math_geom.md +0 -79
- package/src/DUPLICATION_AUDIT_2026_08_07/B_core_data.md +0 -93
- package/src/DUPLICATION_AUDIT_2026_08_07/C_gfx_render.md +0 -80
- package/src/DUPLICATION_AUDIT_2026_08_07/D_gfx_features.md +0 -164
- package/src/DUPLICATION_AUDIT_2026_08_07/E_physics.md +0 -69
- package/src/DUPLICATION_AUDIT_2026_08_07/F_sound.md +0 -110
- package/src/DUPLICATION_AUDIT_2026_08_07/G_net_save.md +0 -129
- package/src/DUPLICATION_AUDIT_2026_08_07/H_engine_misc.md +0 -72
- package/src/DUPLICATION_AUDIT_2026_08_07/I_generation_view.md +0 -74
- package/src/DUPLICATION_AUDIT_2026_08_07/K_crosscutting.md +0 -169
- package/src/DUPLICATION_AUDIT_2026_08_07.md +0 -254
- package/src/DUPLICATION_AUDIT_REMEDIATION.md +0 -250
- package/src/DUPLICATION_REVIEW_2026_10_24.md +0 -1072
- package/src/REVIEW_2026_08_06/adv-core.md +0 -511
- package/src/REVIEW_2026_08_06/adv-gfx.md +0 -480
- package/src/REVIEW_2026_08_06/adv-view.md +0 -446
- package/src/REVIEW_2026_08_06/api-core.md +0 -296
- package/src/REVIEW_2026_08_06/api-engine.md +0 -195
- package/src/REVIEW_2026_08_06/bvh-phys-sound-net.md +0 -507
- package/src/REVIEW_2026_08_06/core-binary.md +0 -348
- package/src/REVIEW_2026_08_06/core-collection.md +0 -376
- package/src/REVIEW_2026_08_06/core-math.md +0 -221
- package/src/REVIEW_2026_08_06/core-process.md +0 -266
- package/src/REVIEW_2026_08_06/core-science.md +0 -223
- package/src/REVIEW_2026_08_06/engine-ai-nav.md +0 -279
- package/src/REVIEW_2026_08_06/engine-animation.md +0 -167
- package/src/REVIEW_2026_08_06/engine-asset.md +0 -166
- package/src/REVIEW_2026_08_06/engine-ecs.md +0 -920
- package/src/REVIEW_2026_08_06/engine-input.md +0 -197
- package/src/REVIEW_2026_08_06/engine-misc.md +0 -248
- package/src/REVIEW_2026_08_06/engine-terrain.md +0 -52
- package/src/REVIEW_2026_08_06/generation.md +0 -176
- package/src/REVIEW_2026_08_06/geom-2d.md +0 -434
- package/src/REVIEW_2026_08_06/geom-3d.md +0 -117
- package/src/REVIEW_2026_08_06/gfx-gi.md +0 -143
- package/src/REVIEW_2026_08_06/gfx-render.md +0 -740
- package/src/REVIEW_2026_08_06/gfx-texture.md +0 -690
- package/src/REVIEW_2026_08_06/prior-criticals.md +0 -49
- package/src/REVIEW_2026_08_06/prior-highs.md +0 -138
- package/src/REVIEW_2026_08_06/test-gaps.md +0 -364
- package/src/REVIEW_2026_08_06/view.md +0 -667
- package/src/REVIEW_2026_08_06.md +0 -610
- package/src/core/binary/lz4/LZ4_HIGH_COMPRESSION_PLAN_2026_09_14.md +0 -542
- package/src/core/bvh2/bvh3/NOTES.md +0 -2
- package/src/core/bvh8/NOTES.md +0 -63
- package/src/core/cache/wtinylfu/benchmark/CacheWTinylfu.bench.md +0 -243
- package/src/core/color/COLOR_FIX_PLAN_2026_08_28.md +0 -417
- package/src/core/color/COLOR_REVIEW_2026_08_28.md +0 -779
- package/src/core/geom/2d/polygon/TRIANGULATION_DESIGN.md +0 -433
- package/src/core/geom/3d/atlas/ATLAS_PORT_PLAN.md +0 -486
- package/src/core/geom/3d/atlas/BFF_PLAN.md +0 -174
- package/src/core/geom/3d/atlas/REVIEW_02.md +0 -392
- package/src/core/geom/3d/gjk/GJK_REVIEW_NOTES.md +0 -146
- package/src/core/geom/3d/gjk/NOTES.md +0 -8
- package/src/core/geom/3d/topology/TOPO_MESH_RETIREMENT_PLAN.md +0 -135
- package/src/core/geom/GEOMETRY_REVIEW_002_API_ISSUES.md +0 -381
- package/src/core/geom/GEOMETRY_REVIEW_002_NAMING.md +0 -684
- package/src/core/geom/MANIFOLD_COMPARISON_2026_08_01.md +0 -554
- package/src/core/model/reactive/evaluation/PREDICATE_APPLICABILITY_PROPOSAL.md +0 -446
- package/src/engine/REVIEW_2026_07_03.md +0 -211
- package/src/engine/asset/loaders/image/IMAGE_CODEC_REVIEW_2026_08_28.md +0 -815
- package/src/engine/control/first-person/DESIGN.md +0 -658
- package/src/engine/control/first-person/DESIGN_COLLISION.md +0 -382
- package/src/engine/control/first-person/DESIGN_EXTENSIONS.md +0 -563
- package/src/engine/control/first-person/TODO.md +0 -160
- package/src/engine/ecs/ASYNC_SYSTEMS_PROPOSAL.md +0 -531
- package/src/engine/ecs/HIERARCHY_REVIEW.md +0 -717
- package/src/engine/ecs/async/WORKER_SYSTEM_PLAN.md +0 -262
- package/src/engine/ecs/ik/PLAN.md +0 -179
- package/src/engine/ecs/storage/binary/SERIALIZATION_COVERAGE.md +0 -272
- package/src/engine/ecs/storage/binary/object-v2/DESIGN.md +0 -199
- package/src/engine/ecs/transform/TRANSFORM64_MIGRATION_PLAN_2026_09_04.md +0 -521
- package/src/engine/graphics/CONTEXT_LOSS_RECOVERY_PLAN.md +0 -463
- package/src/engine/graphics/ecs/camera/pp/NOTES.md +0 -48
- package/src/engine/graphics/render/frame_graph/CORRECTNESS_FIXES_2026_09_04.md +0 -659
- package/src/engine/graphics/render/frame_graph/FRAME_GRAPH_RECOMMENDATIONS.md +0 -235
- package/src/engine/graphics/sh3/path_tracer/REVIEW_001_ACTION_PLAN.md +0 -490
- package/src/engine/graphics/texture/sampler/compare/FLIP_IMPLEMENTATION_PLAN.md +0 -466
- package/src/engine/input/GAMEPAD_API_PROPOSAL.md +0 -717
- package/src/engine/input/ecs/ism/ISM_DESIGN.md +0 -1523
- package/src/engine/input/ecs/ism/ISM_IMPLEMENTATION_PLAN.md +0 -627
- package/src/engine/navigation/mesh/OVERLAPPING_SURFACES_2026_08_25.md +0 -661
- package/src/engine/navigation/mesh/PATHFINDING_PLAN.md +0 -229
- package/src/engine/network/CONGESTION_CONTROL.md +0 -87
- package/src/engine/network/MESSAGE_TRANSPORT.md +0 -364
- package/src/engine/network/SMOOTHNESS_DESIGN.md +0 -400
- package/src/engine/physics/cloth/MEASUREMENTS.md +0 -5304
- package/src/engine/physics/cloth/PLAN.md +0 -3056
- package/src/engine/physics/fluid/GPU_FLUID_CASCADES_PROPOSAL_2026_10_16.md +0 -1382
- package/src/engine/physics/fluid/REVIEW_02_PLAN.md +0 -243
- package/src/engine/physics/fluid/solver/NOTES.md +0 -46
- package/src/engine/sound/SOUND_EMITTER_RETIREMENT_PLAN.md +0 -536
- package/src/engine/sound/simulation/IMPLEMENTATION_PLAN.md +0 -432
- package/src/engine/sound/simulation/PROBE_PLACEMENT.md +0 -250
- package/src/engine/sound/simulation/PROBE_TRANSFER_RESEARCH.md +0 -322
- package/src/engine/sound/simulation/REFLECTION_IR_PLAN.md +0 -261
- package/src/engine/sound/simulation/VISIBILITY_GRAPH_PLAN.md +0 -121
- package/src/engine/sound/sopra/IMPLEMENTATION_PLAN.md +0 -999
- package/src/format/image/avif/DECISIONS.md +0 -545
- package/src/format/image/jpeg/NOTES.md +0 -3
- package/src/format/scene/gltf/MESHOPT_COMPRESSION_PLAN.md +0 -814
- package/src/generation/COORDINATES.md +0 -54
- package/src/generation/REVIEW_01_ACTION_PLAN.md +0 -628
- package/src/generation/foliage/ANNUAL_SHOOTS_BRIEF_2026_10_25.md +0 -220
- package/src/generation/foliage/CROWN_FILLING_BRIEF_2026_10_26.md +0 -172
- package/src/generation/foliage/CROWN_FULLNESS_BRIEF_2026_10_26.md +0 -86
- package/src/generation/foliage/FOLIAGE_DESIGN.md +0 -547
- package/src/generation/foliage/FOLIAGE_PLAN.md +0 -198
- package/src/generation/foliage/LEAF_ARCHITECTURE_BRIEF_2026_10_26.md +0 -158
- package/src/generation/foliage/LOD_REWORK_BRIEF_2026_10_27.md +0 -521
- package/src/generation/foliage/REAL_TIME_TREES_BRIEF_2026_10_27.md +0 -86
- package/src/generation/foliage/SELF_ORGANIZING_FRAMEWORK_BRIEF_2026_10_26.md +0 -347
- package/src/generation/foliage/SHOOT_SYSTEMS_ALL_SPECIES_BRIEF_2026_10_26.md +0 -248
- package/src/generation/foliage/SPEEDTREE_COMPARISON_2026_10_24.md +0 -694
- package/src/generation/foliage/TWO_FRONT_ENDS_BRIEF_2026_10_28.md +0 -552
- package/src/shade/RENDERER_CONTRACT.md +0 -697
- package/src/shade/SHADER_F16_PROPOSAL_2026_10_24.md +0 -263
- package/src/shade/device/IMMEDIATE_DATA_PLAN_2026_08_28.md +0 -569
- package/src/shade/device/PASS_ENCODER_PROPOSAL_2026_08_31.md +0 -755
- package/src/shade/device/mock/EXTENSION_PROPOSAL_2026_08_22.md +0 -458
- package/src/shade/device/mock/IMPLEMENTATION_PLAN.md +0 -255
- package/src/shade/device/mock/REVIEW_2026_08_22.md +0 -527
- package/src/shade/device/timing/GPU_PROFILER_PROPOSAL_2026_08_28.md +0 -894
- package/src/shade/device/timing/profile/SGPT_FORMAT.md +0 -345
- package/src/shade/renderer/NOTES.md +0 -78
- package/src/shade/renderer/PLAN.md +0 -8
- package/src/shade/renderer/animation/ADDITIVE_BLENDING_PLAN.md +0 -145
- package/src/shade/renderer/animation/SKINNING_FRAME_PLAN.md +0 -357
- package/src/shade/renderer/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts +0 -76
- package/src/shade/renderer/camera/orbital/MomentumAxis.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/MomentumAxis.js +0 -164
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts +0 -45
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraConfig.js +0 -66
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts +0 -98
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraInput.js +0 -184
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts +0 -175
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/OrbitalCameraRig.js +0 -411
- package/src/shade/renderer/camera/orbital/README.md +0 -81
- package/src/shade/renderer/camera/orbital/index.d.ts +0 -6
- package/src/shade/renderer/camera/orbital/index.d.ts.map +0 -1
- package/src/shade/renderer/camera/orbital/index.js +0 -9
- package/src/shade/renderer/extension/RENDER_EXTENSION_DESIGN.md +0 -964
- package/src/shade/renderer/fluid/GPU_FLUID_OCCUPANCY_AND_SOTA_REVIEW_2026_10_26.md +0 -361
- package/src/shade/renderer/geometry/bvh/BLAS_REFIT_BATCH_PLAN.md +0 -619
- package/src/shade/renderer/geometry/meshlet/COMPACTION_PLAN_2026_09_16.md +0 -674
- package/src/shade/renderer/geometry/sdf/NOTES.md +0 -6
- package/src/shade/renderer/geometry/virtual/ATTRIBUTE_PLAN_2026_09_18.md +0 -540
- package/src/shade/renderer/geometry/virtual/MICRON_COMPARISON_2026_08_20.md +0 -305
- package/src/shade/renderer/geometry/virtual/VGEO_FORMAT.md +0 -913
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_DESIGN.md +0 -787
- package/src/shade/renderer/geometry/virtual/VIRTUAL_GEOMETRY_PLAN.md +0 -481
- package/src/shade/renderer/geometry/virtual/VK_LOD_CLUSTERS_COMPARISON_2026_08_20.md +0 -301
- package/src/shade/renderer/geometry/virtual/WEDGE_PLAN_2026_09_18.md +0 -448
- package/src/shade/renderer/geometry/virtual/runtime/CULL_PLAN_2026_09_16.md +0 -385
- package/src/shade/renderer/geometry/virtual/runtime/CUT_PLAN_2026_09_14.md +0 -656
- package/src/shade/renderer/geometry/virtual/runtime/REVIEW_LEDGER.md +0 -308
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN.md +0 -657
- package/src/shade/renderer/geometry/virtual/runtime/RUNTIME_PLAN_2026_09_14.md +0 -551
- package/src/shade/renderer/geometry/virtual/runtime/SHADOW_PLAN_2026_09_28.md +0 -529
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts +0 -47
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/sdf/VGEO_SDF.js +0 -80
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts +0 -16
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_collect.js +0 -67
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts +0 -17
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_decode.js +0 -145
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts +0 -12
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.d.ts.map +0 -1
- package/src/shade/renderer/geometry/virtual/sdf/shader_vgeo_sdf_traverse.js +0 -105
- package/src/shade/renderer/global_illumination/lpv/NOTES.md +0 -3
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_CLIPMAP_PROPOSAL_2026_10_27.md +0 -4306
- package/src/shade/renderer/global_illumination/probe_clipmap/PROBE_RAYS_VARIABLE_AND_SORTED_SCOPE_2026_10_30.md +0 -410
- package/src/shade/renderer/global_illumination/sharc/NOTES.md +0 -8
- package/src/shade/renderer/gpu_primitive/bvh/GPU_BVH_BUILD_PLAN.md +0 -1369
- package/src/shade/renderer/gpu_primitive/bvh/PHASE1_HANDOVER.md +0 -202
- package/src/shade/renderer/gpu_primitive/indirect/NOTES.md +0 -94
- package/src/shade/renderer/hiz/NOTES.md +0 -3
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts +0 -8
- package/src/shade/renderer/hiz/shader_hzb_reduce_mip0_clip.d.ts.map +0 -1
- package/src/shade/renderer/light/cluster/NOTES.md +0 -11
- package/src/shade/renderer/light/cluster/PROPOSAL_ALGORITHM_2026_10_16.md +0 -524
- package/src/shade/renderer/light/cluster/PROPOSAL_HIERARCHICAL_2026_10_16.md +0 -1101
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts +0 -24
- package/src/shade/renderer/material/resident/shader_resident_texture_means.d.ts.map +0 -1
- package/src/shade/renderer/material/resident/shader_resident_texture_means.js +0 -120
- package/src/shade/renderer/particles/DESIGN.md +0 -1011
- package/src/shade/renderer/particles/EMITTER_GLOBAL_STATE_PLAN_2026_10_29.md +0 -280
- package/src/shade/renderer/particles/ORIENTATION_PLAN_2026_10_15.md +0 -453
- package/src/shade/renderer/path_tracer/PATH_TRACED_MEDIA_PLAN_2026_10_02.md +0 -520
- package/src/shade/renderer/postprocess/bloom/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/fsr/NOTES.md +0 -4
- package/src/shade/renderer/postprocess/gtao/NOTES.md +0 -6
- package/src/shade/renderer/postprocess/nss/NOTES.md +0 -332
- package/src/shade/renderer/postprocess/perspective/NOTES.md +0 -3
- package/src/shade/renderer/postprocess/sscs/NOTES.md +0 -5
- package/src/shade/renderer/postprocess/ssr/NOTES.md +0 -14
- package/src/shade/renderer/postprocess/ssr/REPROJECTION_PROPOSAL.md +0 -286
- package/src/shade/renderer/postprocess/ssr/prefilter/NOTES.md +0 -39
- package/src/shade/renderer/postprocess/taa/NOTES.md +0 -11
- package/src/shade/renderer/postprocess/upscale-dither/NOTES.md +0 -78
- package/src/shade/renderer/postprocess/vrs/NOTES.md +0 -4
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_LEDGER.md +0 -1218
- package/src/shade/renderer/rasterize/native/avboit/AVBOIT_PLAN_2026_09_03.md +0 -600
- package/src/shade/renderer/restir/reservoir/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/atmosphere/NOTES.md +0 -6
- package/src/shade/renderer/shader/chunk/brdf/FRESNEL_BRIEF_2026_10_16.md +0 -391
- package/src/shade/renderer/shader/chunk/color/tonemap/ACES_TONE_MAPPING_BRIEF_2026_10_17.md +0 -153
- package/src/shade/renderer/shader/chunk/color/tonemap/HDR_TONE_MAPPING_FORMS_BRIEF_2026_10_16.md +0 -322
- package/src/shade/renderer/shader/chunk/color/tonemap/SDR_TONE_MAPPING_BRIEF_2026_10_16.md +0 -247
- package/src/shade/renderer/shader/chunk/fsr/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/fsr/spd/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/geometry/ray/NOTES.md +0 -4
- package/src/shade/renderer/shader/chunk/material/MULTISCATTER.md +0 -159
- package/src/shade/renderer/shader/chunk/mboit/NOTES.md +0 -38
- package/src/shade/renderer/shader/chunk/spherical_harmonics/l1i/NOTES.md +0 -3
- package/src/shade/renderer/shader/chunk/spherical_harmonics/sampling/NOTES.md +0 -8
- package/src/shade/renderer/shader/compiler/SHADER_SWITCH_PROPOSAL_2026_10_16.md +0 -927
- package/src/shade/renderer/shadow/contact/FINDINGS.md +0 -413
- package/src/shade/renderer/shadow/map/csm/NOTES.md +0 -5
- package/src/shade/renderer/shadow/ray/NOTES.md +0 -31
- package/src/shade/renderer/shadow/sdf/NOTES.md +0 -9
- package/src/shade/renderer/shadow/sdf/brixelizer/NOTES.md +0 -5
- package/src/shade/renderer/shadow/sdf/cascade/NOTES.md +0 -9
- package/src/shade/renderer/shadow/vsm/NOTES.md +0 -12
- package/src/shade/renderer/shadow/vsm/PLAN.md +0 -442
- package/src/shade/renderer/shadow/vsm/REVIEW_LEDGER.md +0 -43
- package/src/shade/renderer/texture/COMPRESSED_TEXTURE_PLAN_2026_09_01.md +0 -2444
- package/src/shade/renderer/texture/mipmaps/NOTES.md +0 -3
- package/src/shade/renderer/volumetrics/NOTES.md +0 -1329
- package/src/shade/renderer/volumetrics/VOLUMETRIC_NOISE_PLAN_2026_10_15.md +0 -336
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts +0 -23
- package/src/shade/renderer/water/medium/GPUWaterBodies.d.ts.map +0 -1
- package/src/shade/renderer/water/medium/GPUWaterBodies.js +0 -75
- package/src/shade/wgsl/NOTES.md +0 -4
|
@@ -1,198 +0,0 @@
|
|
|
1
|
-
# Meep Procedural Foliage & Tree Generation System — Implementation Plan
|
|
2
|
-
|
|
3
|
-
This implementation plan translates `FOLIAGE_DESIGN.md` (including all §9 adversarial review resolutions) into concrete, verifiable phases with exact file paths, function signatures, invariants, and co-located Vitest unit test suites.
|
|
4
|
-
|
|
5
|
-
---
|
|
6
|
-
|
|
7
|
-
## Phase 1: Core Engine Primitives Leveraged (`Graph`, `Transform64`, `Attribute`)
|
|
8
|
-
|
|
9
|
-
The foliage system directly composes Meep's existing primitives without modifying `BinaryTopology`:
|
|
10
|
-
1. **`Graph` & `Edge` (`src/core/graph/v2/Graph.js`, `src/core/graph/Edge.js`)**: Directed skeletal graph (`EdgeDirectionType.Forward`).
|
|
11
|
-
2. **`Transform64` & `t64_look_rotation` (`src/engine/ecs/transform/Transform64.js`, `t64_look_rotation.js`)**: Per-node and per-attachment 3D position, RMF quaternion orientation (`[R, S, T]`), and radius scale.
|
|
12
|
-
3. **`Attribute` (`src/shade/renderer/geometry/Attribute.js`)**: Typed-array per-node, per-segment, and per-attachment data channels.
|
|
13
|
-
|
|
14
|
-
---
|
|
15
|
-
|
|
16
|
-
## Phase 2: Species Configuration, Enums, Curves, & Botanical Presets
|
|
17
|
-
Location: `packages/meep-engine/src/generation/foliage/config/` & `presets/`
|
|
18
|
-
|
|
19
|
-
### Files & Signatures
|
|
20
|
-
1. **`config/CrownEnvelopeType.js`**
|
|
21
|
-
- Enum: `Conical = 0`, `Spherical = 1`, `Hemispherical = 2`, `Cylindrical = 3`, `TaperedCylindrical = 4`, `Flame = 5`, `InverseConical = 6`, `TendFlame = 7`, `Weeping = 8`.
|
|
22
|
-
2. **`config/PhyllotaxisMode.js`**
|
|
23
|
-
- Enum: `SpiralGolden = 0`, `AlternateDistichous = 1`, `Tristichous = 2`, `Opposite = 3`, `OppositeDecussate = 4`, `Whorled = 5`.
|
|
24
|
-
3. **`config/FoliageCardType.js`**
|
|
25
|
-
- Enum: `FoldedVCard = 0`, `CrossCard = 1`, `TriStarCluster = 2`, `RibbedFrond = 3`, `OctagonalCutoutHull = 4`.
|
|
26
|
-
4. **`config/TreePreset.js`**
|
|
27
|
-
- Enum: `Oak = "oak"`, `Pine = "pine"`, `Birch = "birch"`, `Willow = "willow"`, `Maple = "maple"`, `Spruce = "spruce"`, `Palm = "palm"`, `Shrub = "shrub"`, `Fern = "fern"`.
|
|
28
|
-
5. **`config/BranchLevelConfig.js`**
|
|
29
|
-
- Fields:
|
|
30
|
-
- `level = 0`
|
|
31
|
-
- `segments = 8` (Hermite segments along branch spine)
|
|
32
|
-
- `radial_segments_max = 12` ($\ge 3$), `radial_segments_min = 4` ($\ge 3$)
|
|
33
|
-
- `length = 8.0`, `length_variance = 0.1`
|
|
34
|
-
- `length_profile: AnimationCurve` (scales child length along parent $t \in [0, 1]$)
|
|
35
|
-
- `radius_ratio = 0.06` (base radius relative to length, or pipe-model tip floor)
|
|
36
|
-
- `taper = 0.85`, `radius_profile: AnimationCurve`
|
|
37
|
-
- `bare_length_ratio = 0.25` (bare zone at base of this branch before children spawn)
|
|
38
|
-
- `child_count = 12` (number of lateral child nodes spawned along this branch)
|
|
39
|
-
- `phyllotaxis_mode = PhyllotaxisMode.SpiralGolden`, `whorl_count = 3`, `azimuth_jitter = 0.15`
|
|
40
|
-
- `insertion_angle = 0.75` (radians from parent tangent), `insertion_angle_variation = 0.2`, `insertion_angle_profile: AnimationCurve`
|
|
41
|
-
- `curvature = 0.15` (total pitch bend in radians), `curve_back = 0.0`, `spiral_twist = 0.0`
|
|
42
|
-
- `gravitropism = 0.1` (positive bends toward $-Y$, negative bends toward $+Y$), `phototropism = 0.15`
|
|
43
|
-
- `gnarl_strength = 0.1`, `gnarl_frequency = 0.35`
|
|
44
|
-
- `split_probability = 0.0`, `split_count = 2`, `split_angle = 0.4`
|
|
45
|
-
- `flare_amplitude = 0.0`, `flare_height_ratio = 0.18`, `flare_lobes = 5`, `flare_sharpness = 4.0`
|
|
46
|
-
- `flute_amplitude = 0.0`, `flute_frequency = 6`
|
|
47
|
-
- `collar_weld_rings = 2`, `collar_length_ratio = 0.08`, `collar_spread_upper = 0.25`, `collar_spread_lower = 0.45`, `collar_normal_blend = 0.85`
|
|
48
|
-
- Methods: `static from(options)`, `copy(other)`, `clone()`, `equals(other)`, `hash()`.
|
|
49
|
-
6. **`config/CrownConfig.js`**
|
|
50
|
-
- Fields: `envelope_type = CrownEnvelopeType.Spherical`, `height = 10.0`, `radius = 4.5`, `base_height = 2.0`, `prune_ratio = 0.35`, `space_colonization_weight = 0.25`, `attraction_point_count = 160`, `attraction_radius = 2.5`, `kill_radius = 0.6`, `pipe_model_exponent = 2.3`, `pipe_model_weight = 0.65`, `sky_phototropism_mix = 0.6`.
|
|
51
|
-
- Methods: `static from(options)`, `copy(other)`, `clone()`, `equals(other)`, `hash()`.
|
|
52
|
-
7. **`config/FoliageConfig.js`**
|
|
53
|
-
- Fields: `enabled = true`, `card_type = FoliageCardType.FoldedVCard`, `attach_min_level = 2`, `cards_per_branch = 10`, `terminal_rosette_count = 3`, `bare_ratio = 0.2`, `phyllotaxis_mode = PhyllotaxisMode.SpiralGolden`, `whorl_count = 2`, `insertion_angle = 0.85`, `card_width = 0.85`, `card_length = 0.95`, `size_variance = 0.2`, `fold_angle = 0.28`, `arch_height = 0.08`, `camber_droop = 0.1`, `frond_segments = 5`, `phototropism = 0.6`, `gravitropism = 0.25`, `angular_jitter = 0.25`, `normal_puffiness = 0.35`, `ao_core_darkening = 0.35`, `color_variation = 0.08`.
|
|
54
|
-
- Methods: `static from(options)`, `copy(other)`, `clone()`, `equals(other)`, `hash()`.
|
|
55
|
-
8. **`config/BarkMaterialConfig.js` & `config/FoliageMaterialConfig.js`**
|
|
56
|
-
- `BarkMaterialConfig`: `resolution = 128`, `primary_color: Color`, `secondary_color: Color`, `moss_color: Color`, `moss_amount = 0.1`, `fissure_frequency = 8`, `fissure_depth = 0.65`, `lenticel_amount = 0.0` (birch horizontal marks), `roughness = 0.85`, `texel_density = 1.5`, `twist_uv = 0.0`.
|
|
57
|
-
- `FoliageMaterialConfig`: `resolution = 128`, `primary_color: Color`, `secondary_color: Color`, `autumn_tint = 0.0`, `leaf_shape = "lobed"` (`"ovate" | "lobed" | "serrated" | "palmate" | "needle" | "frond"`), `leaflets_per_cluster = 5`, `roughness = 0.58`, `vein_strength = 0.5`.
|
|
58
|
-
9. **`config/TreeWindConfig.js` & `config/TreeLODConfig.js`**
|
|
59
|
-
- `TreeWindConfig`: `enabled = true`, `max_joints = 32`, `trunk_compliance = 0.012`, `branch_compliance = 0.045`, `natural_frequency = 2.8`, `damping_ratio = 0.32`, `turbulence = 0.28`, `max_bend_angle = 0.65`.
|
|
60
|
-
- `TreeLODConfig`: `level = 0`, `radial_scale = 1.0`, `longitudinal_scale = 1.0`, `max_branch_level = 3`, `min_branch_radius = 0.0`, `foliage_keep_ratio = 1.0`, `foliage_area_compensation_exponent = 0.42`, `simplify_cards = false`.
|
|
61
|
-
10. **`config/TreeSpeciesConfig.js` + `config/TreeSpeciesConfig.spec.js`**
|
|
62
|
-
- Combines `name`, `preset`, `seed`, `crown: CrownConfig`, `levels: BranchLevelConfig[]`, `foliage: FoliageConfig`, `bark_material: BarkMaterialConfig`, `foliage_material: FoliageMaterialConfig`, `wind: TreeWindConfig`, `lods: TreeLODConfig[]`.
|
|
63
|
-
- Methods: `static from(options)`, `applyOverrides(overrides)`, `copy(other)`, `clone()`, `equals(other)`, `hash()`.
|
|
64
|
-
11. **`presets/make_tree_species_preset.js` + `presets/make_tree_species_preset.spec.js`**
|
|
65
|
-
- `export function make_tree_species_preset(preset = TreePreset.Oak, overrides = {}): TreeSpeciesConfig`
|
|
66
|
-
- Botanically tuned configurations for `Oak`, `Pine`, `Birch`, `Willow`, `Maple`, `Spruce`, `Palm`, `Shrub`, `Fern`.
|
|
67
|
-
|
|
68
|
-
---
|
|
69
|
-
|
|
70
|
-
## Phase 3: Skeleton Topology, Rotation-Minimizing Frames, & Hybrid Growth
|
|
71
|
-
Location: `packages/meep-engine/src/generation/foliage/skeleton/`
|
|
72
|
-
|
|
73
|
-
### Files & Signatures
|
|
74
|
-
1. **`skeleton/TreeSkeleton.js` + `skeleton/TreeSkeleton.spec.js`**
|
|
75
|
-
- Wraps `graph = new Graph()`, `node_transforms: Transform64[]`, 3 per-node `Attribute`s (`attr_node_branch_info`, `attr_node_spine_param`, `attr_node_joint`), and 4 per-segment `Attribute`s (`attr_segment_endpoints`, `attr_segment_hermite_m0`, `attr_segment_hermite_m1`, `attr_segment_metrics`).
|
|
76
|
-
- Also holds flat branch metadata table (`branch_count`, `branch_root_vertex: Int32Array`, `branch_tip_vertex: Int32Array`, `branch_level: Uint8Array`, `branch_parent: Int32Array`, `branch_parent_edge: Int32Array`, `branch_length: Float32Array`, `branch_base_radius: Float32Array`, `crown_center: Float32Array(3)`, `crown_radii: Float32Array(3)`).
|
|
77
|
-
- `add_node(px, py, pz, tx, ty, tz, rx, ry, rz, radius, branch_id, level, parent_branch_id, t_norm, arc_s, phase_hash): number`
|
|
78
|
-
- Adds node `v` to `this.graph`, populates `this.node_transforms[v]` (`Transform64` with `setTranslation`, `t64_look_rotation`, `setScaleScalar(radius)`, `updateMatrix()`), and writes per-node `Attribute`s.
|
|
79
|
-
- `add_segment(v0, v1, m0x, m0y, m0z, m1x, m1y, m1z, length, parent_attach_t): number`
|
|
80
|
-
- Creates a directed `EdgeDirectionType.Forward` edge `v0 -> v1` in `this.graph` and writes per-segment `Attribute`s.
|
|
81
|
-
- `evaluate_segment_position(out, out_offset, edge_id, u)` & `evaluate_segment_tangent(out, out_offset, edge_id, u)`:
|
|
82
|
-
- Evaluates 3D cubic Hermite position/derivative via `spline3_hermite` / `spline3_hermite_derivative`.
|
|
83
|
-
- `copy(other)` & `clone()`:
|
|
84
|
-
- Deep-copies `this.graph`, `this.node_transforms`, and all `Attribute` buffers.
|
|
85
|
-
2. **`skeleton/crown_envelope_evaluate.js` + `skeleton/crown_envelope_evaluate.spec.js`**
|
|
86
|
-
- `export function crown_envelope_evaluate(envelope_type, h_norm, prune_width_peak = 0.6, power_low = 1.5, power_high = 1.5): number`
|
|
87
|
-
- Evaluates the normalized radial envelope $S_{\text{env}}(h_{\text{norm}}) \in [0.05, 1.0]$ for all 9 `CrownEnvelopeType` modes.
|
|
88
|
-
- `export function crown_envelope_sdf(px, py, pz, crown_config): number` — signed distance to the 3D crown envelope around `+Y` trunk axis.
|
|
89
|
-
3. **`skeleton/spine_frame_double_reflection.js` + `skeleton/spine_frame_double_reflection.spec.js`**
|
|
90
|
-
- `export function spine_frame_double_reflection(out, out_offset, x0, y0, z0, tx0, ty0, tz0, rx0, ry0, rz0, x1, y1, z1, tx1, ty1, tz1): void`
|
|
91
|
-
- Computes Wang et al. (2008) fourth-order Rotation-Minimizing Frame `[Rx1, Ry1, Rz1, Sx1, Sy1, Sz1]` at `(x1, y1, z1)` with full guards for $c_1 \le 10^{-12}$ (`tube_frame_transport` fallback), $c_2 \le 10^{-12}$ (identity second reflection), and Gram-Schmidt re-orthonormalization.
|
|
92
|
-
4. **`skeleton/tree_skeleton_grow.js` + `skeleton/tree_skeleton_grow.spec.js`**
|
|
93
|
-
- `export function tree_skeleton_grow(config, out = new TreeSkeleton()): TreeSkeleton`
|
|
94
|
-
- Seeds `seededRandom(config.seed)` and computes a seed-derived 3D noise offset $\mathbf{o}_{\text{seed}}$.
|
|
95
|
-
- Populates space colonization attraction points in the crown envelope and builds `PointHashGrid3` once with `cell_size = config.crown.attraction_radius` and an external `Uint8Array` `alive` mask.
|
|
96
|
-
- Generates trunk ($l=0$) and recursive branch levels ($l=1 \dots L_{\max}$), handling phyllotaxis, `AnimationCurve` profiles, gravitropism (along $-Y$), phototropism (toward $+Y$ and radial crown exterior), `curl_noise_3d` gnarl, dichotomous/sympodial splitting, RMF transport, and Hermite tangent fitting.
|
|
97
|
-
5. **`skeleton/tree_skeleton_compute_pipe_radii.js` + `skeleton/tree_skeleton_compute_pipe_radii.spec.js`**
|
|
98
|
-
- `export function tree_skeleton_compute_pipe_radii(skeleton, config): void`
|
|
99
|
-
- Post-order bottom-up pass over `skeleton.topology` vertices, accumulating $R_{\text{pipe}}(v) = (R_{\text{tip}}^\alpha + \sum_{e=(v\to u)} R_{\text{pipe}}(u)^\alpha)^{1/\alpha}$ and blending with parametric taper `radius_profile.evaluate(t)` via `config.crown.pipe_model_weight`.
|
|
100
|
-
6. **`skeleton/tree_skeleton_assign_skin_joints.js` + `skeleton/tree_skeleton_assign_skin_joints.spec.js`**
|
|
101
|
-
- `export function tree_skeleton_assign_skin_joints(skeleton, max_joints = 32): { joint_count: number, joint_vertex_ids: Int32Array, joint_parents: Int32Array, joint_positions: Float32Array, joint_levels: Uint8Array, joint_phases: Float32Array }`
|
|
102
|
-
- Selects up to `max_joints` structural skeleton nodes in topological pre-order (`joint_parents[j] < j`) and assigns every skeleton vertex its `[primary_joint, parent_joint]` indices in `layer_node_joint`.
|
|
103
|
-
|
|
104
|
-
---
|
|
105
|
-
|
|
106
|
-
## Phase 4: Bark & Foliage Mesh Synthesis, Collar Welding, & Canopy AO
|
|
107
|
-
Location: `packages/meep-engine/src/generation/foliage/mesh/`
|
|
108
|
-
|
|
109
|
-
### Files & Signatures
|
|
110
|
-
1. **`mesh/branch_collar_project.js` + `mesh/branch_collar_project.spec.js`**
|
|
111
|
-
- `export function branch_collar_project(out_pos, out_pos_offset, out_norm, out_norm_offset, ring_x, ring_y, ring_z, tube_nx, tube_ny, tube_nz, child_tx, child_ty, child_tz, parent_px, parent_py, parent_pz, parent_tx, parent_ty, parent_tz, parent_radius, weld_factor, normal_blend): void`
|
|
112
|
-
- Projects lateral branch collar vertices onto the parent branch cylinder surface with bounded axial pullback ($|\tau| \le 1.25 R_p$) and interpolates vertex normals from the parent cylinder normal $\mathbf{n}_{\text{parent}}$ to $\mathbf{n}_{\text{child}}$.
|
|
113
|
-
2. **`mesh/branch_ring_triangulate.js` + `mesh/branch_ring_triangulate.spec.js`**
|
|
114
|
-
- `export function branch_ring_triangulate(indices, index_cursor, ring0_start, m0, ring1_start, m1): number`
|
|
115
|
-
- `export function branch_apex_triangulate(indices, index_cursor, ring_start, m, apex_start): number`
|
|
116
|
-
- Enforces $m_0 \ge 3, m_1 \ge 3$, zippers unequal rings using exact integer cross-multiplication `(j0 + 1) * m1 <= (j1 + 1) * m0` with outward CCW winding, and guarantees **zero repeated vertex indices** (`i0 !== i1 && i1 !== i2 && i2 !== i0`).
|
|
117
|
-
3. **`mesh/tree_mesh_build_bark.js` + `mesh/tree_mesh_build_bark.spec.js`**
|
|
118
|
-
- `export function tree_mesh_build_bark(skeleton, config, lod_config, skin_info = null, out = new Geometry()): Geometry`
|
|
119
|
-
- Sweeps all retained branches ($l \le \text{lod\_config.max\_branch\_level}$ and $R_0 \ge \text{lod\_config.min\_branch\_radius}$) using `spline3_hermite`, `spine_frame_double_reflection`, root buttress lobes, bark flutes, lateral collar welding (for `parent_attach_t < 0.95`), terminal fork blending (for `parent_attach_t >= 0.95`), quantized seamless bark UVs (`uv0`), wind weights (`uv1`), canopy/collar AO (`color`), and 4-joint skinning attributes (`joints`, `weights`).
|
|
120
|
-
- Calls `out.ensureBounds()` and `out.ensureTangents()`.
|
|
121
|
-
4. **`mesh/foliage_collect_attachments.js` + `mesh/foliage_collect_attachments.spec.js`**
|
|
122
|
-
- `export function foliage_collect_attachments(skeleton, config): FoliageAttachmentSet`
|
|
123
|
-
- Generates phyllotactic attachment points, heliotropic/gravitropic orthonormal bases $(\mathbf{F}, \mathbf{U}, \mathbf{W})$ with outward hemisphere alignment ($\mathbf{U} \cdot \mathbf{n}_{\text{canopy}} \ge 0$), golden-ratio decimation rank $h_i = (i \cdot \varphi^{-1}) \bmod 1$, and inherited skin joint indices/weights.
|
|
124
|
-
5. **`mesh/tree_mesh_build_foliage.js` + `mesh/tree_mesh_build_foliage.spec.js`**
|
|
125
|
-
- `export function tree_mesh_build_foliage(skeleton, attachments, config, lod_config, out = new Geometry()): Geometry`
|
|
126
|
-
- Filters attachments by $h_i < k_{\text{keep}}$, applies area compensation scaling $s_{\text{comp}} = k_{\text{keep}}^{-\eta}$, and emits the selected `FoliageCardType` (`FoldedVCard`, `CrossCard`, `TriStarCluster`, `RibbedFrond`, `OctagonalCutoutHull`) with `position`, `normal`, `uv0`, `uv1` (wind weights), `color` (AO + color jitter), and `joints`/`weights`.
|
|
127
|
-
6. **`mesh/tree_mesh_apply_canopy_ao.js` + `mesh/tree_mesh_apply_canopy_ao.spec.js`**
|
|
128
|
-
- `export function tree_mesh_apply_canopy_ao(geometry, crown_center, crown_radii, options): void`
|
|
129
|
-
- Computes analytic crown ellipsoid + sky-exposure AO into `StandardAttributes.Color` and applies hemisphere-safe normal puffing ($\mathbf{n}_{\text{vertex}} \cdot \mathbf{n}_{\text{face}} \ge 0.55$) before `geometry.ensureTangents()`.
|
|
130
|
-
|
|
131
|
-
---
|
|
132
|
-
|
|
133
|
-
## Phase 5: Procedural PBR Materials, Wind Clips, & Turn-Key Asset Pipeline
|
|
134
|
-
Location: `packages/meep-engine/src/generation/foliage/material/`, `animation/`, `asset/`
|
|
135
|
-
|
|
136
|
-
### Files & Signatures
|
|
137
|
-
1. **`material/make_bark_material.js` + `material/make_bark_material.spec.js`**
|
|
138
|
-
- `export function make_bark_material(config = new BarkMaterialConfig(), seed = 1): StandardShadeMaterial`
|
|
139
|
-
- Synthesizes tileable `Sampler2D` $\to$ `ShadeImage` $\to$ `ShadeTexture` for bark Albedo (`ColorSpace.SRGB`), 2-channel Normal (`ColorSpace.None` / `LinearSRGB`, `TextureFilterType.LinearNormal`), and ORM (`ColorSpace.None` / `LinearSRGB`), sets `material.ambient_factors.set(1, 0)`, `TransparencyMode.Opaque`, `ShadeDrawSide.Front`.
|
|
140
|
-
2. **`material/make_foliage_material.js` + `material/make_foliage_material.spec.js`**
|
|
141
|
-
- `export function make_foliage_material(config = new FoliageMaterialConfig(), seed = 1): StandardShadeMaterial`
|
|
142
|
-
- Synthesizes botanical leaf/needle cluster Albedo + Alpha mask (dilated straight RGB into $A=0$ texels with `AlphaMode.Straight` so GPU upload premultiplies cleanly once), Normal map (vein relief), and ORM map, sets `material.ambient_factors.set(1, 0)`, `TransparencyMode.AlphaTested`, `ShadeDrawSide.Double`, `transmission_factor = 0`.
|
|
143
|
-
3. **`animation/build_tree_wind_rig.js` + `animation/build_tree_wind_rig.spec.js`**
|
|
144
|
-
- `export function build_tree_wind_rig(skin_info, wind_config = new TreeWindConfig()): FoliageWindRig|null`
|
|
145
|
-
- Generates a GPU fluid-driven `FoliageWindRig` (`name: "foliage_wind"`) whose joints (`2..J`, with joint `0` / `SceneNode` `1` anchored at the trunk base) carry physical Euler-Bernoulli cantilever `compliance`, `natural_frequency`, `damping_ratio`, `max_angle`, `turbulence`, `branch_axis`, and `flutter_phase`. At runtime, `GPUAnimationManager` dispatches `shader_foliage_wind_apply` to sample `GPUSceneWind` (`chunk_wind_field_sample`) at each bone's world position and step a 2nd-order damped oscillator into `pose_accumulator`.
|
|
146
|
-
4. **`asset/TreeLODAsset.js` & `asset/TreeAsset.js`**
|
|
147
|
-
- `TreeLODAsset`: holds `level`, `bark_geometry: Geometry`, `foliage_geometry: Geometry|null`, `bark_material: StandardShadeMaterial`, `foliage_material: StandardShadeMaterial`, `wind_rig: FoliageWindRig|null`, and **lazy memoized getters** `.bark_meshlet_geometry`, `.foliage_meshlet_geometry`, `.scene_bundle`, `.prefab`.
|
|
148
|
-
- `TreeAsset`: holds `config: TreeSpeciesConfig`, `skeleton: TreeSkeleton`, `attachments: FoliageAttachmentSet`, `skin_info`, `wind_rig: FoliageWindRig|null`, `bark_material: StandardShadeMaterial`, `foliage_material: StandardShadeMaterial`, `lods: TreeLODAsset[]`, plus convenience getters `.bark_geometry`, `.foliage_geometry`, `.bark_meshlet_geometry`, `.foliage_meshlet_geometry`, `.scene_bundle`, `.prefab` aliasing `lods[0]`.
|
|
149
|
-
5. **`asset/generate_tree.js` + `asset/generate_tree.spec.js`**
|
|
150
|
-
- `export function generate_tree(options = {}): TreeAsset`
|
|
151
|
-
- Turn-key entry point accepting zero arguments (`generate_tree()`), a `TreeSpeciesConfig`, or `{ preset, seed, crown, levels, foliage, bark_material, foliage_material, wind, lod_count, eager_meshlets }`.
|
|
152
|
-
6. **`asset/place_tree.js` + `asset/place_tree.spec.js`**
|
|
153
|
-
- `export function place_tree(scene_context, dataset, options = {}): PlacedTree`
|
|
154
|
-
- `export function unplace_tree(scene_context, dataset, placed): void`
|
|
155
|
-
- Accepts either an existing `tree` (`TreeAsset`) / `prefab` (`Prefab`) or generation options, constructs `Transform64` from `placement` or `{ position, rotation, rotation_y, scale }`, calls `prefab_place`, registers `FoliageWindRig`s on `scene_context.animation_manager` with position-derived phase offsets, and provides `unplace_tree` for complete cleanup.
|
|
156
|
-
|
|
157
|
-
---
|
|
158
|
-
|
|
159
|
-
## Adversarial Review of the Implementation Plan
|
|
160
|
-
|
|
161
|
-
Before beginning implementation, each phase of this plan was audited against the exact runtime contracts in `packages/meep-engine/src`:
|
|
162
|
-
|
|
163
|
-
1. **`StandardAttributes.SkinningJoints` TypedArray Contract**:
|
|
164
|
-
- `geometry_obtain_attribute` always allocates a `Float32Array`, whereas `meshlet_encode_attribute` expects `StandardAttributes.SkinningJoints` (`'joints'`) to be backed by a `Uint16Array(vertex_count * 4)`.
|
|
165
|
-
- *Plan Adjustment*: `tree_mesh_build_bark` and `tree_mesh_build_foliage` will obtain `'joints'` via a dedicated `Uint16Array` attribute helper (`Attribute.from(new Uint16Array(vertex_count * 4), 4, StandardAttributes.SkinningJoints)`) and `'weights'` via `geometry_obtain_attribute(geometry, StandardAttributes.SkinningWeights, 4, vertex_count)`.
|
|
166
|
-
2. **`Sampler2D.uint8(itemSize, width, height)` Parameter Order & Direct Buffer Writes**:
|
|
167
|
-
- `Sampler2D.uint8` takes `(itemSize, width, height)` with `itemSize` first.
|
|
168
|
-
- *Plan Adjustment*: `make_bark_material` and `make_foliage_material` will construct `Sampler2D.uint8(channels, resolution, resolution)` and write directly into `sampler.data` (`Uint8Array`) for fast zero-overhead texture synthesis.
|
|
169
|
-
3. **`GPUAnimationManager` Clip Registration & Unregistration Order in `place_tree` / `unplace_tree`**:
|
|
170
|
-
- `GPUAnimationManager` methods are `register_clip(clip)`, `set_flags(clip_id, AnimationClipFlags.Playing | AnimationClipFlags.Loop)`, `set_time(clip_id, time)`, `set_playback_rate(clip_id, rate)`, `set_playback_weight(clip_id, weight)`, and `unregister_clip(clip_id)`.
|
|
171
|
-
- `register_clip` grants `GPUStateAuthorityFlags.TransformAttachment | GPUStateAuthorityFlags.Transform64` on target entities and registers an entity event listener on `dataset`.
|
|
172
|
-
- *Plan Adjustment*: In `unplace_tree(scene_context, dataset, placed)`, `animation_manager.unregister_clip(clip_id)` **must** be called **before** `prefab_unplace(scene_context, dataset, placed)` so target entities and their `GPUStateAuthority` components still exist in `dataset` when `unregister_clip` revokes GPU authority and removes the event listener.
|
|
173
|
-
4. **Root Joint Binding for Unassigned / Root Vertices**:
|
|
174
|
-
- In `tree_skeleton_assign_skin_joints`, joint `0` (`SceneNode` index `1`) is placed at the trunk base `(0, 0, 0)`. Any vertex at the very base of the trunk (`t = 0`) binds with weight `1.0` to joint `0` (`joints = [0, 0, 0, 0]`, `weights = [1, 0, 0, 0]`), and `build_tree_wind_clip` keeps joint `0` stationary (or applies only micro-base flex) so the base of the trunk stays anchored to the ground during wind sway.
|
|
175
|
-
|
|
176
|
-
---
|
|
177
|
-
|
|
178
|
-
## Step 7: Adversarial Review of the Implementation & Resolutions
|
|
179
|
-
|
|
180
|
-
Following completion of Phases 1–5, a comprehensive adversarial review of the implementation was conducted across `src/core/geom/3d/topology/struct/binary/query/` and `src/generation/foliage/`. Every identified edge case and mathematical hazard was resolved and covered with regression unit tests:
|
|
181
|
-
|
|
182
|
-
1. **Adaxial Crotch Root Selection in `branch_collar_project.js`**:
|
|
183
|
-
- *Finding*: For the upper (adaxial/crotch) half of a tilted lateral branch ($\alpha \in (0, \pi/2)$) originating on the parent spine axis, the ring offset $\mathbf{q}$ has a negative projection onto the emerging direction $\mathbf{u}$ ($b_{\text{half}} = \mathbf{q} \cdot \mathbf{u} < 0$). Selecting `Math.abs(t_plus) < Math.abs(t_minus)` caused $b_{\text{half}} < 0$ vertices to select $t_{\text{minus}} = \frac{-b_{\text{half}} - \sqrt{\Delta}}{\|\mathbf{u}\|^2}$, which satisfies $(\mathbf{q} + t_{\text{minus}}\mathbf{u})\cdot\mathbf{u} = -\sqrt{\Delta} < 0$ (the opposite back wall of the parent trunk!).
|
|
184
|
-
- *Resolution*: Always select the emerging ($+\mathbf{u}$) cylinder root $\tau = t_{\text{plus}} = \frac{-b_{\text{half}} + \sqrt{\Delta}}{\|\mathbf{u}\|^2}$, which algebraically guarantees $(\mathbf{q} + t_{\text{plus}}\mathbf{u})\cdot\mathbf{u} = +\sqrt{\Delta} \ge 0$ for all collar vertices regardless of the sign of $b_{\text{half}}$, and bias steep-angle radial projection into the $+\mathbf{u}$ hemisphere.
|
|
185
|
-
2. **Parent RMF Transport & Singularity-Free Child RMF Initialization in `tree_skeleton_grow.js` and `foliage_collect_attachments.js`**:
|
|
186
|
-
- *Finding*: When interpolating the parent branch's Rotation-Minimizing Frame at `local_u` along `parent_e`, `spine_frame_double_reflection` was called with `SCRATCH_POS` for both start and end points (`c1 === 0`), skipping the spatial chord reflection from `p_v0` to `SCRATCH_POS`. Additionally, initializing the child branch RMF radial vector from `D_rad` when $\alpha \approx \pi/2$ caused near-collinearity with `T_c`.
|
|
187
|
-
- *Resolution*: Pass `p_v0`'s actual position and tangent as `(x0, y0, z0, tx0, ty0, tz0)` into `spine_frame_double_reflection`, and initialize the child branch's radial vector using the exact orthonormal vector in the $(\mathbf{T}_p, \mathbf{D}_{\text{rad}})$ plane: $\mathbf{R}_c = \cos(\alpha)\mathbf{D}_{\text{rad}} - \sin(\alpha)\mathbf{T}_p$, which has unit length and zero singularity across all $\alpha \in [0, \pi]$.
|
|
188
|
-
3. **Dichotomous Split Frame Preservation & Interior Hermite Tangent Smoothing in `tree_skeleton_grow.js`**:
|
|
189
|
-
- *Finding*: During a dichotomous split, rotating `next_t` for fork 0 without rotating `next_r` broke frame orthogonality, and re-writing `m0` from `vertex_read_normal(branch_vertices[0])` overwrote continuation fork `f`'s departure tangent with fork 0's tangent at the shared split vertex.
|
|
190
|
-
- *Resolution*: Preserve the pre-split orthonormal triad `(pre_t, pre_r, pre_s)`, rotate both `T` and `R` around each fork's bend axis so every fork maintains an exact right-handed orthonormal triad, and smooth only interior vertices (`1 <= k < branch_edges.length`) so continuation forks retain their exact departure Hermite tangent `m0`.
|
|
191
|
-
4. **Longitudinal Hermite Spline Resampling (`longitudinal_scale`), Watertight Apex Cones (`branch_apex_triangulate`), Collar Tip Guard, & Empty Skeleton Fallback in `tree_mesh_build_bark.js`**:
|
|
192
|
-
- *Finding*: `tree_mesh_build_bark.js` iterated over raw skeleton nodes without resampling by `lod_config.longitudinal_scale`, left branch tips uncapped, could pull short branch tips (`sample_steps <= collar_weld_rings`) back onto the parent trunk, and left the 4-vertex empty-skeleton fallback buffer zero-filled.
|
|
193
|
-
- *Resolution*: Resample each branch's Cubic Hermite spline chain into `sample_steps = Math.max(1, Math.round(E * long_scale))` longitudinal rings using `evaluate_segment_position`, `evaluate_segment_tangent`, and `spine_frame_double_reflection`; cap all branch tips into watertight cones via `branch_apex_triangulate`; guard collar welding with `i < sample_steps && t_norm < 0.65` using exact parent Hermite evaluation at `parent_local_u`; and populate a valid non-degenerate quad when `branch_plans.length === 0`.
|
|
194
|
-
5. **Single-Joint Wind Clips (`max_joints: 1`), Static Trees (`wind: false`), & Foliage Texture Clamping**:
|
|
195
|
-
- *Finding*: `build_tree_wind_clip` returned a 0-channel clip when `joint_count === 1`; boolean shorthand `{ wind: false }` / `{ foliage: false }` was ignored by `applyOverrides`; `generate_tree` with `wind.enabled === false` still attached a `Skin` to `TreeLODAsset`; and foliage `ShadeTexture`s defaulted to `Repeat` wrapping along $V \in [0, 1]$.
|
|
196
|
-
- *Resolution*: Animate joint `0` (`SceneNode` index `1`) when `joint_count === 1`; support boolean shorthand in `TreeWindConfig.applyOverrides` and `FoliageConfig.applyOverrides`; omit `Skin` on `TreeLODAsset` when `wind.enabled === false`; bind rest-pose skins cleanly in `place_tree` when `wind: false`; and set `TextureWrapType.ClampToEdge` on foliage textures in `make_foliage_material.js`.
|
|
197
|
-
|
|
198
|
-
|
|
@@ -1,158 +0,0 @@
|
|
|
1
|
-
# Leaf Architecture
|
|
2
|
-
|
|
3
|
-
## Problem
|
|
4
|
-
|
|
5
|
-
The oak's cards did not look like oak leaves (Alex, 2026-10-26: "What the fuck is that?"). Two causes, both hacks:
|
|
6
|
-
|
|
7
|
-
- **The leaf outline was code, not botany.** `foliage_leaf_silhouette.js` switched on a string, `"lobed"` (a ±28% sine
|
|
8
|
-
ripple, "oak-like"), `"serrated"` (a sawtooth), `"palmate"` (a cosine), each with hand-picked constants. The oak's
|
|
9
|
-
`"lobed"` blade was widest near its base, with shallow wavy edges: a Christmas tree.
|
|
10
|
-
- **A whole shoot was painted flat into one texture.** The `"rosette"` arrangement drew 11 leaves from one point,
|
|
11
|
-
fanned over ±83°, each three-quarters as wide as long. They merged into one blob with 11 tips. A `TriStarCluster`
|
|
12
|
-
stood three of those on crossing planes, which is the star in the screenshot. Meanwhile the simulation grows the
|
|
13
|
-
real shoots, so the tile duplicated the shoot geometry and contradicted it.
|
|
14
|
-
|
|
15
|
-
Fixing the oak's outline alone would have kept both hacks.
|
|
16
|
-
|
|
17
|
-
## Principle
|
|
18
|
-
|
|
19
|
-
- **A leaf is data, described as floras describe it.** Ellis et al. (2009), *Manual of Leaf Architecture*, gives the
|
|
20
|
-
vocabulary; each preset cites its flora.
|
|
21
|
-
- **A card is one leaf, on its shoot.** Each leaf is a card at its own node, leaving the shoot at the rule's insertion
|
|
22
|
-
angle and turned by its phyllotaxis.
|
|
23
|
-
- **Needles stay shoot cards.** Pine bears 1,560 needles per metre and spruce 2,450 (sourced in the presets). A card
|
|
24
|
-
per needle is out of reach, and the needle shoot is the unit those papers measure.
|
|
25
|
-
|
|
26
|
-
## Design
|
|
27
|
-
|
|
28
|
-
- **`LeafArchitecture`** (`FoliageMaterialConfig.leaf`):
|
|
29
|
-
- blade length, length/width ratio, where it is widest;
|
|
30
|
-
- apex and base angle and shape (`LeafApexShape`, `LeafBaseShape`; the angles measured as Ellis et al. define them,
|
|
31
|
-
a quarter of the blade's length from the tip or the base);
|
|
32
|
-
- lobation (`LeafLobation`), lobes, sinus depth, palmate spread and lateral lobe length;
|
|
33
|
-
- teeth per cm, tooth depth and order;
|
|
34
|
-
- secondary veins and their angle;
|
|
35
|
-
- petiole length;
|
|
36
|
-
- a compound leaf's leaflets and rachis.
|
|
37
|
-
- **`leaf_geometry`** turns that into outline contours, veins and stems in metres:
|
|
38
|
-
- **Envelope:** a monotone cubic Hermite (Fritsch-Carlson) through the base, the base angle's point, the widest point,
|
|
39
|
-
the apex angle's point and the apex. The shapes set the end slopes. A rounded end is an elliptic arc; an acuminate
|
|
40
|
-
one is shallow, so the margin is concave near the tip.
|
|
41
|
-
- **Pinnate lobes:** the blade reaches only to the sinus floor, `1 - sinus_depth` of the outline's width. Each lateral
|
|
42
|
-
lobe is a rounded blade of its own along its secondary vein (so it leans by the vein's angle), out to the outline.
|
|
43
|
-
The veins leave the midvein evenly spaced.
|
|
44
|
-
- **Palmate lobes:** a blade per primary lobe, radiating across `lobe_spread`, over a body to the sinus floors.
|
|
45
|
-
- **Base lobes:** cordate and lobate bases are a cubic Bezier from the petiole sinus round the basal lobe, solved to
|
|
46
|
-
reach exactly `base_lobe_depth` below the petiole.
|
|
47
|
-
- **Teeth:** offset along the outline's normal, spaced along the untoothed margin, with a second order a third the
|
|
48
|
-
size.
|
|
49
|
-
- **Union:** every contour winds the same way, so the union of lobes, leaflets and petiole is filled by the nonzero
|
|
50
|
-
rule (`polygon2_rasterize_coverage`, exact across each row, 4 samples down it).
|
|
51
|
-
- **`foliage_tile_layout`** (one place for every consumer):
|
|
52
|
-
- The mature leaf fills the tile within a 2% margin, attached at the bottom middle. Every tile draws at that scale,
|
|
53
|
-
so the card's size in metres is the leaf's (`card_size`).
|
|
54
|
-
- **Resolution:** the finest feature (a tooth, a sinus) is drawn 4 texels across. The narrowest stem is drawn 2
|
|
55
|
-
texels across, so wherever it falls it covers a whole texel and survives the alpha test.
|
|
56
|
-
- **Needle shoots:** a stretch of shoot as long as a needle, with the needles the shoot bears there
|
|
57
|
-
(`leaves_per_metre`), shared among the card's planes. Each plane draws the needles in its sector round the shoot,
|
|
58
|
-
foreshortened by their azimuth.
|
|
59
|
-
- **`foliage_tile_raster`:**
|
|
60
|
-
- Coverage, veins stamped near each segment, distance to the margin and to the midvein by chamfer, camber,
|
|
61
|
-
bullation, and the petiole.
|
|
62
|
-
- The pigment, senescence and normal code of `make_foliage_material` is unchanged. It now skips the texels the leaf
|
|
63
|
-
leaves empty, which keep the dilated fill.
|
|
64
|
-
- **Cards:**
|
|
65
|
-
- **Broadleaves:** a card per leaf. A short shoot's `leaves_per_short_shoot` sit at its tip. The presets draw
|
|
66
|
-
`CutoutHull` cards.
|
|
67
|
-
- **Needle cards** lie along the shoot.
|
|
68
|
-
- **Density path:** branches not grown by annual units keep it, on the layout's card size and anchor.
|
|
69
|
-
|
|
70
|
-
## Sources per species
|
|
71
|
-
|
|
72
|
-
| preset | leaf | sources | estimated, not found |
|
|
73
|
-
| :--- | :--- | :--- | :--- |
|
|
74
|
-
| oak (*Quercus robur*) | mean blade 10.6 and 12.0 cm; L/W 1.8, 1.64; width 0.81-0.85 of max at 0.5 L, 0.47-0.50 at 0.9 L; petiole 7.4-8.0% of blade | Boratyński et al. 2008, *Silva Fennica* 42: 115-124, Table 4. Fitted: widest at 0.675, apex angle 1.2, base 0.8 rad (both widths within 0.01) | auricle size, secondary angle |
|
|
75
|
-
| | obovate; apex broadly rounded; sinuses 1/3-7/8 to midrib; entire; 5-7 secondaries | FNA vol. 3 | |
|
|
76
|
-
| | 5-7 lobes a side | Flora of China | |
|
|
77
|
-
| | up to 5 pairs; auricles usually strong | BSBI Plant Crib | |
|
|
78
|
-
| birch (*Betula pendula*) | 3-7 × 2.5-5 cm, ovate-rhombic, acuminate, cuneate, doubly serrate | FNA | apex and base angles, teeth (1.3 a cm, 1.5 mm), widest point |
|
|
79
|
-
| | 6-8 lateral veins; petiole 2-3 cm | FoC | |
|
|
80
|
-
| | 2 leaves a short shoot | Maillette 1982 | |
|
|
81
|
-
| willow (*Salix babylonica*) | 90-160 × 5-20 mm, L/W 5.5-10.5, acuminate, cuneate, serrulate; petiole 7-9 mm | FNA vol. 7 | angles, teeth (5 a cm, 0.3 mm), veins |
|
|
82
|
-
| maple (*Acer rubrum*) | 6.8 cm, 39 cm² | Wilson 1966 | lobe outline, lateral lobe length 0.85, teeth (3 a cm, 1.5 mm) |
|
|
83
|
-
| | 3 lobes; lateral axes 73-86° apart; midlobe 46-56% of blade; petiole 60-114% of blade; 2 leaf pairs a short shoot | Critchfield 1971 | |
|
|
84
|
-
| | doubly serrate | Gleason & Cronquist | |
|
|
85
|
-
| | base truncate to cordate | Trees and Shrubs Online | |
|
|
86
|
-
| shrub (*Corylus avellana*) | 5-12 × 4-12 cm, abruptly acuminate, narrowly cordate, doubly serrate, ≤ 8 vein pairs | FNA | angles, base lobe depth, teeth (0.7 a cm, 2.5 mm) |
|
|
87
|
-
| | petiole 6-12 mm | Trees and Shrubs Online | |
|
|
88
|
-
| | 8 cm gives the 41 cm² of a sun leaf | Catoni et al. 2015 | |
|
|
89
|
-
| pine, spruce needles | 52 mm [Niinemets & Lukjanova 2003]; spruce's 18 mm was already chosen | | widths 1.6 and 1 mm; needle angle 0.6 rad |
|
|
90
|
-
| palm, fern | no species named: the old frond's sizes are kept | | everything |
|
|
91
|
-
|
|
92
|
-
The botanical data was gathered by a research subagent from efloras.org (FNA, FoC), BSBI, VicFlora, Go Botany, Trees
|
|
93
|
-
and Shrubs Online, SEINet and the papers above. Its quotes and URLs are in the session's scratchpad (`leaf/`).
|
|
94
|
-
floranorthamerica.org refused access, and HAL (Kremer et al. 2002) is behind a bot check.
|
|
95
|
-
|
|
96
|
-
## Measured
|
|
97
|
-
|
|
98
|
-
*Seed 1337 unless noted; the "before" figures are from 49845ff00.*
|
|
99
|
-
|
|
100
|
-
**Atlas, from the drawn tiles:**
|
|
101
|
-
|
|
102
|
-
| preset | resolution | card | coverage | one leaf |
|
|
103
|
-
| :--- | ---: | ---: | ---: | ---: |
|
|
104
|
-
| oak | 128 | 12.7 cm | 0.208 | 33 cm² |
|
|
105
|
-
| birch | 256 | 7.8 cm | 0.174 | 10.6 cm² |
|
|
106
|
-
| willow | 512 | 13.9 cm | 0.073 | 14 cm² |
|
|
107
|
-
| maple | 512 | 13.2 cm | 0.213 | 37 cm² |
|
|
108
|
-
| shrub | 128 | 9.3 cm | 0.522 | 45 cm² |
|
|
109
|
-
| pine | 256 | 9.8 cm (81 needles) | | |
|
|
110
|
-
| spruce | 256 | 3.4 cm (44 needles) | | |
|
|
111
|
-
| palm | 128 | | | |
|
|
112
|
-
| fern | 128 | | | |
|
|
113
|
-
|
|
114
|
-
Leaf areas against the sources:
|
|
115
|
-
- maple: 37 cm² against Wilson's 39;
|
|
116
|
-
- hazel: 45 cm² against Catoni's 41;
|
|
117
|
-
- birch: 10.6 cm² against about 11 from FNA's sizes.
|
|
118
|
-
|
|
119
|
-
**Cost:** cards, LOD0 triangles, and `generate_tree` time with the LOD0 meshes.
|
|
120
|
-
|
|
121
|
-
| preset | cards | foliage tris | bark tris | generate + LOD0 |
|
|
122
|
-
| :--- | ---: | ---: | ---: | ---: |
|
|
123
|
-
| oak | 25,622 | 153,732 | 81,587 | 0.77 + 0.06 s |
|
|
124
|
-
| pine | 3,554 | 21,324 | 39,817 | 0.71 + 0.03 s |
|
|
125
|
-
| birch | 63,909 | 383,454 | 454,735 | 1.73 + 0.56 s |
|
|
126
|
-
| willow | 113,001 | 678,006 | 410,091 | 1.81 + 0.46 s |
|
|
127
|
-
| maple | 13,008 | 78,048 | 37,774 | 1.16 + 0.05 s |
|
|
128
|
-
| spruce | 176,311 | 705,244 | 1,085,114 | 3.12 + 1.23 s |
|
|
129
|
-
| shrub | 16,976 | 101,856 | 62,817 | 0.52 + 0.05 s |
|
|
130
|
-
|
|
131
|
-
**Crowns,** measured with `foliage_measure_leaf_area` and `tree_crown_opacity`; "before" is 49845ff00:
|
|
132
|
-
|
|
133
|
-
| preset | leaf m² (before) | crown LAI | side density | side transparency | below density | below transparency |
|
|
134
|
-
| :--- | ---: | ---: | ---: | ---: | ---: | ---: |
|
|
135
|
-
| oak | 89.4 (90.9) | 3.11 | 0.50 | 0.42 | 0.58 | 0.27 |
|
|
136
|
-
| pine | 15.7 (35.0) | 0.74 | 0.34 | 0.64 | 0.35 | 0.62 |
|
|
137
|
-
| birch | 70.4 (64.5) | 6.77 | 0.56 | 0.33 | 0.75 | 0.12 |
|
|
138
|
-
| willow | 232.6 (136.3) | 6.43 | 0.75 | 0.18 | 0.74 | 0.19 |
|
|
139
|
-
| maple | 50.7 (36.3) | 1.97 | 0.41 | 0.42 | 0.42 | 0.32 |
|
|
140
|
-
| spruce | 78.4 (117.8) | 3.03 | 0.33 | 0.31 | 0.42 | 0.29 |
|
|
141
|
-
| shrub | 62.5 (57.8) | 4.52 | 0.63 | 0.22 | 0.64 | 0.16 |
|
|
142
|
-
|
|
143
|
-
- **Pine and spruce lost leaf area** because their old tiles overdrew. Every plane of a card drew all of its needles,
|
|
144
|
-
three times over on pine, and wider than the needles are. Now each needle is drawn once at its width.
|
|
145
|
-
- **Willow gained,** its lanceolate leaves replacing a frond drawing. Its transparency, 0.18, is near FIA's 15%.
|
|
146
|
-
|
|
147
|
-
## Open (measured, not argued)
|
|
148
|
-
|
|
149
|
-
- **Card counts rose where a card used to hold several leaves:** birch 5×, willow 9×, oak 11×. Pine and spruce rose
|
|
150
|
-
2.4×, because a needle card now covers one needle length of shoot, not 2.4. That stretch is chosen, not sourced.
|
|
151
|
-
- **Estimates:** the angles, tooth sizes and widest points the floras do not give are marked in each preset.
|
|
152
|
-
- **Palm and fern** name no species, so their leaves are not sourced.
|
|
153
|
-
- **Wind sail:**
|
|
154
|
-
- `TreeWindConfig.elastic_modulus` is fitted to the oak, whose leaf area moved by 2% (90.9 to 89.4 m²); it was not
|
|
155
|
-
refit.
|
|
156
|
-
- Pine's and spruce's sails fell with their leaf area (to 0.45 and 0.67), so they will sway less. That sway is not
|
|
157
|
-
measured.
|
|
158
|
-
- **Transparency:** every crown but willow's is still far above FIA's 15% transparency.
|