从零构建CAD引擎:CADmium项目Rust核心开发实战指南
你是否还在为Web端CAD应用的性能瓶颈发愁?是否想了解如何用Rust构建跨平台的CAD内核?本文将带你深入CADmium项目的Rust构建系统,掌握从环境配置到高级测试的全流程开发技巧,让你在3D建模引擎开发中事半功倍。
读完本文你将获得:
- 基于Tauri+Rust的跨平台CAD开发环境搭建方案
- 几何建模核心模块的Rust实现模式
- 自动化测试与性能优化的实战技巧
- 从2D草图到3D实体的完整工作流实现
项目架构概览
CADmium采用现代化的分层架构,通过Rust实现高性能几何计算内核,配合Web前端构建跨平台CAD应用。项目使用Monorepo结构管理多语言代码,主要包含两大核心模块:
核心技术栈构成:
- 语言框架:Rust 2021 + TypeScript + Svelte
- 构建工具:Cargo + PNPM + Turbo
- 几何计算:Truck系列crate (meshalgo/modeling/shapeops)
- 跨平台:Tauri v2 + WebAssembly
- 测试工具:Cargo Test + Playwright
开发环境搭建
系统要求
| 环境 | 最低版本 | 推荐配置 |
|---|---|---|
| Rust | 1.70.0+ | 1.76.0+ |
| Node.js | 20.13.1+ | 20.15.0+ |
| PNPM | 9.1.0+ | 9.6.0+ |
| Tauri CLI | 2.0.0-beta.20 | 2.0.0-beta.20 |
完整环境配置流程
- 基础依赖安装
# 安装Rust工具链
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
rustup target add wasm32-unknown-unknown
# 安装Node.js与PNPM
curl -fsSL https://fnm.vercel.app/install | bash
fnm install 20.15.0
corepack enable pnpm
# 安装Tauri CLI
cargo install tauri-cli --version 2.0.0-beta.20
- 项目克隆与依赖安装
git clone https://gitcode.com/gh_mirrors/ca/CADmium
cd CADmium
pnpm install
- 构建验证
# 构建Rust核心模块
pnpm --filter cadmium build
# 运行Web应用
pnpm dev
Rust核心模块开发详解
项目结构与构建配置
CADmium的Rust核心位于packages/cadmium目录,采用Cargo工作区管理:
cadmium/
├── src/ # 源代码目录
│ ├── lib.rs # WASM入口
│ ├── project.rs # 项目管理
│ ├── sketch/ # 2D草图系统
│ ├── extrusion.rs # 3D挤出功能
│ └── test.rs # 单元测试
├── examples/ # 示例程序
├── Cargo.toml # 包配置
└── package.json # NPM包装配置
关键Cargo配置解析:
[package]
name = "cadmium"
version = "0.1.0"
edition = "2021"
description = "A CAD program written in Rust with a JS front end"
[lib]
crate-type = ["cdylib", "rlib"] # 同时构建WASM和常规库
[dependencies]
# 几何计算核心依赖
truck-meshalgo = { git = "https://github.com/ricosjp/truck.git", rev = "c84318b8dec" }
truck-modeling = { git = "https://github.com/ricosjp/truck.git", rev = "c84318b8dec" }
# 序列化与WASM绑定
wasm-bindgen = "0.2.87"
tsify = "0.4.5" # TypeScript类型生成
serde = "1.0.202"
serde_json = "1.0.117"
# 错误处理
anyhow = { version = "1.0.86", features = ["backtrace"] }
thiserror = "1.0.61"
核心功能实现
1. 项目管理系统
Project结构体是CADmium的核心数据容器,负责管理整个设计过程的所有元素:
// src/project.rs 核心定义
pub struct Project {
pub id: String,
pub name: String,
pub workbenches: Vec<Workbench>,
pub materials: Vec<Material>,
pub created_at: DateTime<Utc>,
pub updated_at: DateTime<Utc>,
}
impl Project {
/// 创建新项目
pub fn new(name: &str) -> Self {
let mut workbenches = Vec::new();
workbenches.push(Workbench::new("Default"));
Self {
id: Uuid::new_v4().to_string(),
name: name.to_string(),
workbenches,
materials: Vec::new(),
created_at: Utc::now(),
updated_at: Utc::now(),
}
}
/// 获取项目的JSON表示
pub fn json(&self) -> String {
serde_json::to_string_pretty(self).expect("Failed to serialize project")
}
}
2. 2D草图系统
草图系统是CAD建模的基础,负责处理2D几何元素和约束:
// src/sketch/mod.rs 核心功能
pub struct Sketch {
pub id: String,
pub name: String,
pub points: IndexMap<String, Point2D>,
pub segments: Vec<Segment>,
pub constraints: Vec<Constraint>,
pub solved: bool,
}
impl Sketch {
/// 添加点到草图
pub fn add_point(&mut self, x: f64, y: f64) -> String {
let id = format!("P-{}", self.points.len());
self.points.insert(id.clone(), Point2D::new(x, y));
id
}
/// 添加线段到草图
pub fn add_segment(&mut self, start_id: String, end_id: String) -> Result<(), SketchError> {
// 验证点存在性
if !self.points.contains_key(&start_id) || !self.points.contains_key(&end_id) {
return Err(SketchError::PointNotFound);
}
let segment = Segment::new(start_id, end_id);
self.segments.push(segment);
Ok(())
}
}
3. 3D实体建模
通过挤出(Extrusion)操作将2D草图转换为3D实体:
// src/extrusion.rs 核心实现
pub enum ExtrusionMode {
New,
Add(Vec<String>),
Subtract(Vec<String>),
Intersect(Vec<String>),
}
pub struct Extrusion {
pub sketch_id: String,
pub profiles: Vec<usize>,
pub depth: f64,
pub draft_angle: f64,
pub direction: Direction,
pub mode: ExtrusionMode,
}
impl Extrusion {
/// 创建新的挤出操作
pub fn new(
sketch_id: String,
profiles: Vec<usize>,
depth: f64,
draft_angle: f64,
direction: Direction,
mode: ExtrusionMode,
) -> Self {
Self {
sketch_id,
profiles,
depth,
draft_angle,
direction,
mode,
}
}
/// 执行挤出操作生成3D实体
pub fn execute(&self, sketch: &Sketch, workbench: &Workbench) -> Result<Solid, ExtrusionError> {
// 1. 获取草图轮廓
let profiles = self.get_profiles(sketch)?;
// 2. 应用挤出深度和拔模角度
let extrusion_vector = self.calculate_direction(workbench)?;
// 3. 使用Truck库执行几何挤出
let truck_shape = truck_modeling::extrude(
&profiles[0],
extrusion_vector,
self.draft_angle.to_radians()
);
// 4. 根据操作模式合并实体
Ok(Solid::from_truck_shape(truck_shape))
}
}
测试策略与实现
单元测试框架
CADmium采用Rust内置的cargo test框架,结合自定义测试场景验证几何算法正确性:
// src/test.rs 测试示例
#[test]
fn secondary_extrusion_simple() {
// 1. 创建基础项目和工作台
let mut p = Project::new("Test Project");
let mut wb = p.workbenches.get_mut(0).unwrap();
// 2. 创建基础草图(40x40正方形)
wb.add_sketch_to_plane("Base Sketch", "Plane-0");
let mut sketch = wb.get_sketch_mut("Base Sketch").unwrap();
let p1 = sketch.add_point(2.0, 2.0);
let p2 = sketch.add_point(42.0, 2.0);
let p3 = sketch.add_point(42.0, 42.0);
let p4 = sketch.add_point(2.0, 42.0);
sketch.add_segment(p1.clone(), p2.clone());
sketch.add_segment(p2, p3.clone());
sketch.add_segment(p3, p4.clone());
sketch.add_segment(p4, p1);
// 3. 挤出基础实体(25mm高度)
let extrusion = Extrusion::new(
"Base Sketch".to_owned(),
vec![0],
25.0,
0.0,
Direction::Normal,
ExtrusionMode::New,
);
wb.add_extrusion("Base Solid", extrusion);
// 4. 在基础实体表面创建第二个草图
let s2_id = wb.add_sketch_to_solid_face("Hole Sketch", "Base Solid:0", Vector3::new(0.0, 0.0, 1.0));
let mut s2 = wb.get_sketch_mut(&s2_id).unwrap();
// 5. 创建较小的正方形作为孔特征
let h1 = s2.add_point(12.0, 12.0);
let h2 = s2.add_point(32.0, 12.0);
let h3 = s2.add_point(32.0, 32.0);
let h4 = s2.add_point(12.0, 32.0);
s2.add_segment(h1.clone(), h2.clone());
s2.add_segment(h2, h3.clone());
s2.add_segment(h3, h4.clone());
s2.add_segment(h4, h1);
// 6. 执行添加模式挤出
let extrusion2 = Extrusion::new(
s2_id.to_owned(),
vec![0],
25.0,
0.0,
Direction::Normal,
ExtrusionMode::Add(vec!["Base Solid:0".to_string()]),
);
wb.add_extrusion("Top Feature", extrusion2);
// 7. 验证结果
let realization = p.get_realization(0, 1000);
assert_eq!(realization.solids.len(), 1, "Should have one combined solid");
// 8. 导出测试结果供可视化检查
let final_solid = &realization.solids["Base Solid:0"];
let mesh = final_solid.truck_solid.triangulation(0.02).to_polygon();
let file = std::fs::File::create("test_secondary_extrusion.obj").unwrap();
obj::write(&mesh, file).unwrap();
}
集成测试与示例程序
除单元测试外,CADmium提供完整示例程序展示核心功能:
// examples/project_simple_extrusion.rs
use cadmium::{
extrusion::{Direction, Extrusion, ExtrusionMode},
project::Project,
};
fn main() {
// 创建新项目
let mut p = Project::new("Example Project");
let wb = p.workbenches.get_mut(0).unwrap();
// 创建2D草图(40x40正方形)
wb.add_sketch_to_plane("Sketch 1", "Plane-0");
let s = wb.get_sketch_mut("Sketch 1").unwrap();
let ll = s.add_point(0.0, 0.0);
let lr = s.add_point(40.0, 0.0);
let ul = s.add_point(0.0, 40.0);
let ur = s.add_point(40.0, 40.0);
s.add_segment(ll, lr);
s.add_segment(lr, ur);
s.add_segment(ur, ul);
s.add_segment(ul, ll);
// 挤出25mm高度形成3D实体
let extrusion = Extrusion::new(
"Sketch-0".to_owned(),
vec![0],
25.0,
0.0,
Direction::Normal,
ExtrusionMode::New,
);
wb.add_extrusion("Ext1", extrusion);
// 获取实体并导出
let realization = p.get_realization(0, 1000);
let solids = realization.solids;
let solid = &solids["Ext1:0"];
// 导出为STEP和OBJ格式
solid.save_as_step("example.step");
solid.save_as_obj("example.obj", 0.001);
println!("Simple extrusion example completed successfully!");
}
构建与部署流程
开发环境构建
# 构建Rust核心模块
cd packages/cadmium
cargo build --target wasm32-unknown-unknown
# 或使用NPM脚本
pnpm --filter cadmium build:dev
生产环境构建
# 全项目构建
pnpm build
# 单独构建Tauri应用
cd applications/tauri
cargo tauri build
测试执行
# 运行Rust单元测试
cargo test --package cadmium
# 运行Web测试
pnpm test
# 运行特定测试
cargo test secondary_extrusion_simple
性能优化实践
几何计算优化
- 空间索引加速:使用
indexmap替代标准HashMap,减少内存碎片 - 延迟计算模式:草图约束求解采用按需计算策略
- 网格细分控制:通过公差参数平衡渲染质量与性能
// 优化的网格细分示例
pub fn triangulation_with_tolerance(&self, tolerance: f64) -> PolyMesh {
let mut settings = TriangulationSettings::default();
settings.max_distance = tolerance; // 控制三角化精度
settings.min_angle = 15.0; // 避免过小三角形
self.shape.triangulation(settings)
}
内存管理优化
- 对象池复用:频繁创建的几何对象使用对象池
- 引用计数:共享几何数据采用
Arc智能指针 - WASM内存限制:通过
wasm-bindgen的内存分配API控制内存使用
实战案例:从草图到3D打印
以下是一个完整的工作流示例,展示如何使用CADmium API创建模型并导出用于3D打印:
use cadmium::{
extrusion::{Direction, Extrusion, ExtrusionMode},
project::Project,
sketch::constraints::{Constraint, ConstraintType},
};
fn create_bracket() -> Project {
let mut project = Project::new("Mounting Bracket");
let wb = project.workbenches.get_mut(0).unwrap();
// 创建基础草图
wb.add_sketch_to_plane("Base", "Plane-0");
let sketch = wb.get_sketch_mut("Base").unwrap();
// 绘制主轮廓
let p1 = sketch.add_point(0.0, 0.0);
let p2 = sketch.add_point(100.0, 0.0);
let p3 = sketch.add_point(100.0, 50.0);
let p4 = sketch.add_point(0.0, 50.0);
// 添加线段
sketch.add_segment(p1.clone(), p2.clone());
sketch.add_segment(p2.clone(), p3.clone());
sketch.add_segment(p3.clone(), p4.clone());
sketch.add_segment(p4.clone(), p1.clone());
// 添加约束
sketch.add_constraint(Constraint {
id: "C1".to_string(),
type_: ConstraintType::Horizontal,
entities: vec![p1.clone(), p2.clone()],
value: None,
});
// 创建安装孔
let hole1 = sketch.add_circle(20.0, 25.0, 10.0);
let hole2 = sketch.add_circle(80.0, 25.0, 10.0);
// 挤出基础厚度
let base_extrusion = Extrusion::new(
"Base".to_string(),
vec![0], // 主轮廓
10.0, // 厚度
0.0, // 拔模角
Direction::Normal,
ExtrusionMode::New,
);
wb.add_extrusion("Base Solid", base_extrusion);
// 创建加强筋草图
let rib_sketch_id = wb.add_sketch_to_solid_face("Rib", "Base Solid:0", (0.0, 0.0, 1.0).into());
let rib_sketch = wb.get_sketch_mut(&rib_sketch_id).unwrap();
// ... 绘制加强筋轮廓 ...
// 挤出加强筋
let rib_extrusion = Extrusion::new(
rib_sketch_id,
vec![0],
5.0,
0.0,
Direction::Normal,
ExtrusionMode::Add(vec!["Base Solid:0".to_string()]),
);
wb.add_extrusion("Rib", rib_extrusion);
project
}
fn main() {
let bracket = create_bracket();
let realization = bracket.get_realization(0, 1000);
// 导出为STL格式用于3D打印
let stl_data = realization.solid_to_stl("Base Solid:0");
std::fs::write("bracket.stl", stl_data).unwrap();
println!("Bracket model created successfully!");
}
总结与未来展望
CADmium项目通过Rust的高性能与WebAssembly的跨平台能力,为浏览器环境带来了专业级CAD功能。本文详细介绍了项目的构建系统、核心模块实现和测试策略,展示了如何利用Rust生态构建复杂的几何建模系统。
未来发展方向:
- 约束求解增强:集成更强大的几何约束求解器
- 参数化设计:添加完整的参数化建模能力
- 实时协作:基于CRDT的数据同步方案
- AI辅助设计:引入机器学习辅助草图理解
通过掌握本文介绍的技术和方法,你可以构建自己的高性能CAD应用,或为CADmium项目贡献代码。项目源码可通过以下方式获取:
git clone https://gitcode.com/gh_mirrors/ca/CADmium
立即开始你的Rust CAD开发之旅吧!
附录:常用命令参考
| 命令 | 功能 |
|---|---|
cargo build | 构建Rust项目 |
cargo test | 运行Rust测试 |
pnpm dev | 启动开发服务器 |
pnpm build | 构建生产版本 |
cargo tauri dev | 运行Tauri应用 |
cargo tauri build | 构建Tauri应用安装包 |
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考



