feat(scene): render 3D surface entities (loft/sweep/extrude/etc.)

ACAD_SURFACE entities now load and render. Their NURBS faces are
tessellated by building a truck BSplineSurface from the ACIS `spline-surface`
control net and knot vectors, then sampling its parametric grid — reusing the
same NURBS kernel the Model tab already builds on. Analytic faces
(plane/cone/sphere/torus) continue through the existing tessellator.

- New spline_tess.rs: parse the ACIS `nubs` block (degrees, knots with the
  clamped end-multiplicity fix, control grid) into a truck BSplineSurface and
  mesh it.
- tessellate_surface + Surface wired through the mesh-build, fallback-wire,
  and entity-classification paths.
- Bump acadrust to the commit that adds the Surface entity.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
Hakan Seven 2026-06-14 20:11:44 +03:00
commit 9d823363f1
9 changed files with 235 additions and 7 deletions

View file

@ -39,6 +39,7 @@ pub fn ui_name(e: &EntityType) -> &'static str {
EntityType::Solid3D(_) => "3D Solid",
EntityType::Region(_) => "Region",
EntityType::Body(_) => "Body",
EntityType::Surface(_) => "Surface",
EntityType::Mesh(_) => "Mesh",
EntityType::Ray(_) => "Ray",
EntityType::XLine(_) => "XLine",

View file

@ -282,6 +282,7 @@ pub fn fallback_wires(e: &EntityType) -> Option<&[acadrust::entities::Wire]> {
EntityType::Solid3D(s) => Some(&s.wires),
EntityType::Region(r) => Some(&r.wires),
EntityType::Body(b) => Some(&b.wires),
EntityType::Surface(s) => Some(&s.wires),
_ => None,
}
}
@ -293,6 +294,7 @@ pub fn tessellate_volume(e: &EntityType, color: [f32; 4], facet_res: f64) -> Opt
EntityType::Solid3D(s) => solid3d_tess::tessellate_solid3d(s, color, facet_res),
EntityType::Region(r) => solid3d_tess::tessellate_region(r, color, facet_res),
EntityType::Body(b) => solid3d_tess::tessellate_body(b, color, facet_res),
EntityType::Surface(s) => solid3d_tess::tessellate_surface(s, color, facet_res),
_ => None,
}
}

View file

@ -129,6 +129,7 @@ pub fn entity_type_name(et: &EntityType) -> &'static str {
EntityType::Solid3D(_) => "Solid3D",
EntityType::Region(_) => "Region",
EntityType::Body(_) => "Body",
EntityType::Surface(_) => "Surface",
EntityType::Table(_) => "Table",
EntityType::Tolerance(_) => "Tolerance",
EntityType::PolyfaceMesh(_) => "PolyfaceMesh",