forked from 1b-agent/opencadstudio-upstream
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:
1 parent
cd048165a9
commit
7fe7e0230d
160 files changed
+732
-715
No files matched your search
@@ -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],
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user