An ACIS spline-surface stored as `nurbs` (rational) carries a weight on each
control point, so the control net is a stream of x, y, z, w tuples. The
parser read plain x, y, z triples, shifting every control point by one float
and scrambling the whole net — the surface, and the solid it bounds,
rendered badly deformed. Non-rational `nubs` surfaces were unaffected, which
is why only some solids (rational lofts/sweeps with varying weights) broke.
Detect `nurbs` vs `nubs`; for rational surfaces read the fourth weight
component and build a truck `NurbsSurface` from homogeneous (xw, yw, zw, w)
control points so the weights actually shape the surface. Both the truck
B-rep path and the bespoke fallback share this parser.
Verified on VillaSavoye_MartinHedin2.dwg solid 0x24A1EE (handle 2400750): the
tessellated surface now stays within the solid's true extent instead of
flying outside it.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
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>