refactor(scene): group modules into role-based subfolders

Move the 30 flat modules under src/scene/ into six folders by role:
convert (entity→geometry), text (fonts/shaping), model (render models),
pick (hit-test/selection/grips/xclip), view (camera/transform/render),
cache (block + property caches). pipeline/ is unchanged.

Full path migration — all `scene::X` references become
`scene::<group>::X`, no compatibility re-exports. render.rs items that
were `pub(super)` (parent was scene) become `pub(in crate::scene)` to
keep their original scene-wide visibility.

No behavior change; build and tests are green.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan SevenandClaude Opus 4.8 committed 2026-06-16 11:33:46 +03:00
1 parent cd048165a9
commit 7fe7e0230d
160 files changed
+732 -715

No files matched your search

+69
View File
@@ -0,0 +1,69 @@
// Triangle mesh model — produced by truck Shell/Solid tessellation.
//
// Stored alongside WireModels in the scene; rendered by the mesh pipeline
// (wgpu TriangleList with depth test, flat normals).
/// A tessellated triangle mesh ready to upload to the GPU.
#[derive(Clone, Debug)]
#[allow(dead_code)]
pub struct MeshModel {
/// Unique identifier (entity handle value as decimal string).
pub name: String,
/// World-space vertex positions.
pub verts: Vec<[f32; 3]>,
/// Per-vertex normals (may be empty if not available).
pub normals: Vec<[f32; 3]>,
/// Triangle indices into `verts` (every 3 values = one triangle).
pub indices: Vec<u32>,
/// RGBA colour in [0, 1].
pub color: [f32; 4],
/// Whether this mesh is currently selected.
pub selected: bool,
}
/// Bundle of mesh tessellations at different sampling densities, picked
/// per frame by the render pipeline based on the projected pixel size of
/// `world_aabb`. Phase 3.4 LOD ladder:
///
/// | LOD | Source | Use when projected diagonal |
/// |-----|------------|------------------------------|
/// | 0 | HIGH | > 200 px |
/// | 1 | MID (½) | 50–200 px |
/// | 2 | LOW (¼) | < 50 px |
///
/// `lods` holds up to one MeshModel per LOD level (high → low). Empty
/// slots fall back to the nearest available LOD at render time.
#[derive(Clone, Debug)]
pub struct MeshLodSet {
pub lods: Vec<MeshModel>,
/// World XY AABB `[min_x, min_y, max_x, max_y]` of the mesh — used
/// by the per-frame LOD selector to compute the projected pixel
/// diagonal.
pub world_aabb: [f32; 4],
}
impl MeshLodSet {
/// Wrap a single MeshModel as a one-LOD set. Used by interactive
/// commands that only produce one tessellation (e.g. truck-based
/// BOX/CYLINDER creation). The LOD selector will pick slot 0 for
/// every zoom level.
pub fn from_single(mesh: MeshModel) -> Self {
let mut min_x = f32::INFINITY;
let mut min_y = f32::INFINITY;
let mut max_x = f32::NEG_INFINITY;
let mut max_y = f32::NEG_INFINITY;
for &[x, y, _] in &mesh.verts {
if !x.is_finite() || !y.is_finite() {
continue;
}
if x < min_x { min_x = x; }
if y < min_y { min_y = y; }
if x > max_x { max_x = x; }
if y > max_y { max_y = y; }
}
Self {
lods: vec![mesh],
world_aabb: [min_x, min_y, max_x, max_y],
}
}
}