feat(model): 3D solid modelling tab — primitives + boolean ops
Rename the Home tab to "Draw" and add a Model tab beside it with two groups: - Model: BOX / CYLINDER / CONE / SPHERE / WEDGE / TORUS, placed with a footprint + height. Each is built as a real ACIS Solid3D (acadrust primitive builders) plus a truck B-rep, tessellated into the shaded mesh pipeline, with edge wires for picking + wireframe. - Design: UNION / SUBTRACT / INTERSECT via truck-shapeops. A session-only Scene.model_solids cache holds each solid's truck B-rep so the boolean tools can combine and chain them. Supersedes the old command-line BOX/SPHERE/CYLINDER (insert::solid3d_cmds keeps EXTRUDE/ REVOLVE/SWEEP/LOFT). Known limitations: booleans need solids created this session; curved ACIS primitives render in-session but not after reload (the SAT tessellator handles only planar caps); geometry assumes world_offset 0. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
4acb820e01
commit
7bf9ce31ae
17 changed files with 1095 additions and 397 deletions
|
|
@ -1190,6 +1190,22 @@ impl OpenCADStudio {
|
|||
}
|
||||
}
|
||||
|
||||
// ── Model commands (3D primitives) ─────────────────────────────
|
||||
"BOX" | "WEDGE" | "CYLINDER" | "CONE" | "SPHERE" | "TORUS" => {
|
||||
use crate::modules::model::primitive_cmd::PrimitiveCommand;
|
||||
let new_cmd = PrimitiveCommand::new(cmd);
|
||||
self.command_line.push_info(&new_cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(new_cmd));
|
||||
}
|
||||
|
||||
// ── Design commands (solid booleans) ───────────────────────────
|
||||
"UNION" | "SUBTRACT" | "INTERSECT" => {
|
||||
use crate::modules::model::boolean_cmd::BoolOp;
|
||||
if let Some(op) = BoolOp::from_id(cmd) {
|
||||
return self.solid_boolean(op);
|
||||
}
|
||||
}
|
||||
|
||||
// ── Annotate commands ──────────────────────────────────────────
|
||||
"TEXT" | "T" | "DT" => {
|
||||
use crate::modules::annotate::text::TextCommand;
|
||||
|
|
@ -5038,32 +5054,8 @@ impl OpenCADStudio {
|
|||
}
|
||||
}
|
||||
|
||||
// ── 3D Primitive — BOX ────────────────────────────────────────
|
||||
"BOX" => {
|
||||
use crate::modules::insert::solid3d_cmds::BoxCommand;
|
||||
let color = self.tabs[i].scene.layer_color(&self.tabs[i].active_layer);
|
||||
let cmd = BoxCommand::new(color);
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
}
|
||||
|
||||
// ── 3D Primitive — SPHERE ─────────────────────────────────────
|
||||
"SPHERE" => {
|
||||
use crate::modules::insert::solid3d_cmds::SphereCommand;
|
||||
let color = self.tabs[i].scene.layer_color(&self.tabs[i].active_layer);
|
||||
let cmd = SphereCommand::new(color);
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
}
|
||||
|
||||
// ── 3D Primitive — CYLINDER ───────────────────────────────────
|
||||
"CYLINDER" => {
|
||||
use crate::modules::insert::solid3d_cmds::CylinderCommand;
|
||||
let color = self.tabs[i].scene.layer_color(&self.tabs[i].active_layer);
|
||||
let cmd = CylinderCommand::new(color);
|
||||
self.command_line.push_info(&cmd.prompt());
|
||||
self.tabs[i].active_cmd = Some(Box::new(cmd));
|
||||
}
|
||||
// BOX / SPHERE / CYLINDER / CONE / WEDGE / TORUS are handled by the
|
||||
// Model-tab primitive command above (with truck boolean caching).
|
||||
|
||||
// ── EXTRUDE ────────────────────────────────────────────────────
|
||||
"EXTRUDE" | "EXT" => {
|
||||
|
|
|
|||
Loading…
Reference in a new issue