feat(v6.2): Blender addon + .NET/C# bindings + developer docs + plugin system
v6.2.1 — Blender Integration Addon: - 5 files, 1,732 lines: __init__, operators (9 ops), panels (4 panels) - preferences, vde_bridge (subprocess CLI bridge) - Import/Export STEP, primitives, boolean, SDF→Mesh v6.2.2 — .NET/C# Bindings (VdeSharp): - 8 files: NativeMethods (50+ P/Invoke), BrepModel, MeshData, SdfEngine, Assembly - C API extended with 20 new functions (STEP I/O, Boolean, SDF, Assembly) - vde_capi rebuilt as SHARED library - Example: import STEP → boolean → export v6.2.3 — Developer Docs + Plugin System: - 7 docs: architecture, contributing, API overview, building, testing, plugin-system - plugin_system.h/.cpp: PluginInterface, PluginManager, dlopen/LoadLibrary - README.md updated with v6 features - Syntax-check passed (GCC 10.2.1, -Wall -Wextra -Wpedantic)
This commit is contained in:
@@ -0,0 +1,106 @@
|
||||
# ViewDesignEngine 开发者指南
|
||||
|
||||
欢迎来到 ViewDesignEngine (VDE) 开发者文档。本指南面向希望理解 VDE 内部架构、贡献代码或基于 VDE 构建应用的开发者。
|
||||
|
||||
## 文档导航
|
||||
|
||||
| 文档 | 说明 |
|
||||
|------|------|
|
||||
| [架构概览](architecture.md) | 模块依赖关系图、数据流、分层架构设计 |
|
||||
| [API 总览](api-overview.md) | 公开 API 接口一览、命名空间规范、核心类型 |
|
||||
| [构建指南](building.md) | 从源码构建、Docker 环境、CMake 选项、依赖管理 |
|
||||
| [测试指南](testing.md) | 测试框架、编写测试、运行测试、覆盖率 |
|
||||
| [贡献指南](contributing.md) | 代码规范、提交流程、Code Review、分支策略 |
|
||||
| [插件系统设计](plugin-system.md) | 插件架构、生命周期、动态加载、清单文件 |
|
||||
|
||||
## 快速开始
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone ssh://git@localhost:22/hm/ViewDesignEngine.git
|
||||
cd ViewDesignEngine
|
||||
|
||||
# Docker 构建(推荐)
|
||||
docker run --rm -v $PWD:/ws vde-builder:latest bash -c \
|
||||
"cd /ws && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j\$(nproc)"
|
||||
|
||||
# 本地构建
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j$(nproc)
|
||||
|
||||
# 运行测试
|
||||
cd build && ctest --output-on-failure
|
||||
```
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
ViewDesignEngine/
|
||||
├── CMakeLists.txt # 顶层 CMake
|
||||
├── cmake/ # CMake 模块 (CompilerSettings 等)
|
||||
├── include/vde/ # 公开头文件
|
||||
│ ├── foundation/ # 基础数学、I/O、公差
|
||||
│ ├── core/ # 几何核心、CAM
|
||||
│ ├── curves/ # 曲线曲面
|
||||
│ ├── mesh/ # 网格处理
|
||||
│ ├── spatial/ # 空间索引
|
||||
│ ├── boolean/ # 布尔运算
|
||||
│ ├── collision/ # 碰撞检测
|
||||
│ ├── brep/ # B-Rep 建模
|
||||
│ ├── sdf/ # SDF 隐式建模
|
||||
│ ├── sketch/ # 草图约束
|
||||
│ └── plugin/ # 插件系统 (v6.0+)
|
||||
├── src/ # 实现文件(按模块分目录)
|
||||
├── tests/ # 单元测试
|
||||
├── bench/ # 性能基准
|
||||
├── examples/ # 示例程序
|
||||
├── python/ # Python 绑定
|
||||
└── docs/ # 文档
|
||||
```
|
||||
|
||||
## 关键概念
|
||||
|
||||
### 命名空间
|
||||
|
||||
所有 VDE 代码位于 `vde::` 命名空间下,按模块分子命名空间:
|
||||
|
||||
```cpp
|
||||
namespace vde::foundation { /* 基础设施 */ }
|
||||
namespace vde::core { /* 几何核心 */ }
|
||||
namespace vde::curves { /* 曲线曲面 */ }
|
||||
namespace vde::mesh { /* 网格处理 */ }
|
||||
namespace vde::spatial { /* 空间索引 */ }
|
||||
namespace vde::boolean { /* 布尔运算 */ }
|
||||
namespace vde::collision { /* 碰撞检测 */ }
|
||||
namespace vde::brep { /* B-Rep 建模 */ }
|
||||
namespace vde::sdf { /* SDF 隐式建模 */ }
|
||||
namespace vde::sketch { /* 草图约束 */ }
|
||||
namespace vde::plugin { /* 插件系统 */ }
|
||||
```
|
||||
|
||||
### 依赖关系
|
||||
|
||||
- **L0 foundation**: 零上游依赖(仅 Eigen)
|
||||
- **L1 core**: 依赖 foundation
|
||||
- **L2 curves**: 依赖 core
|
||||
- **L3 mesh**: 依赖 core + brep
|
||||
- **L4 spatial**: 依赖 core
|
||||
- **L5 boolean/collision**: 依赖 L1-L4
|
||||
- **brep**: 依赖 curves + mesh + collision
|
||||
- **sdf**: 依赖 core + mesh
|
||||
- **plugin**: 依赖 foundation(独立于其他模块)
|
||||
|
||||
### 设计原则
|
||||
|
||||
1. **零开销抽象** — 模板与编译期多态,避免不必要的虚函数
|
||||
2. **数据驱动** — SoA 布局优化缓存命中率
|
||||
3. **不可变优先** — 几何实体默认不可变,变换返回新实体
|
||||
4. **RAII 资源管理** — 智能指针管理所有资源
|
||||
5. **单一依赖** — 仅依赖 Eigen,不引入 Boost
|
||||
|
||||
## 相关文档
|
||||
|
||||
- [项目开发计划](../00-开发计划.md)
|
||||
- [系统架构设计](../02-概要设计/01-系统架构设计.md)
|
||||
- [CHANGELOG](../../CHANGELOG.md)
|
||||
- [API 参考手册](../API-REFERENCE.md)
|
||||
@@ -0,0 +1,222 @@
|
||||
# API 总览
|
||||
|
||||
ViewDesignEngine 提供 C++17 头文件 API,所有公开接口位于 `include/vde/` 目录下。
|
||||
|
||||
## 模块 API 概览
|
||||
|
||||
### foundation — 基础设施 (`vde::foundation`)
|
||||
|
||||
```cpp
|
||||
// 数学类型
|
||||
#include <vde/foundation/point.h> // Point2D, Point3D, Vector2D, Vector3D
|
||||
#include <vde/foundation/matrix.h> // Matrix3x3, Matrix4x4, Transform3D
|
||||
#include <vde/foundation/aabb.h> // AABB2D, AABB3D
|
||||
|
||||
// 公差与精确谓词
|
||||
#include <vde/foundation/tolerance.h> // Tolerance, is_zero(), is_equal()
|
||||
#include <vde/foundation/exact_predicates.h> // orient2d, orient3d, incircle
|
||||
|
||||
// 格式 I/O
|
||||
#include <vde/foundation/io_obj.h> // load_obj(), export_obj()
|
||||
#include <vde/foundation/io_stl.h> // load_stl(), export_stl()
|
||||
#include <vde/foundation/io_ply.h> // load_ply(), export_ply()
|
||||
#include <vde/foundation/io_gltf.h> // export_gltf(), export_glb()
|
||||
#include <vde/foundation/io_3mf.h> // load_3mf(), export_3mf()
|
||||
#include <vde/foundation/industrial_formats.h> // STEP/IGES 导入导出
|
||||
```
|
||||
|
||||
### core — 几何核心 (`vde::core`)
|
||||
|
||||
```cpp
|
||||
#include <vde/core/polygon.h> // Polygon2D, triangulate(), simplify()
|
||||
#include <vde/core/voronoi.h> // VoronoiDiagram2D
|
||||
#include <vde/core/convex_hull.h> // convex_hull_2d(), convex_hull_3d()
|
||||
#include <vde/core/distance.h> // point_to_line(), point_to_triangle()
|
||||
#include <vde/core/icp.h> // icp_align()
|
||||
#include <vde/core/cam_toolpath.h> // ToolPath, GCode, CLData
|
||||
#include <vde/core/cam_strategies.h> // contour_toolpath, pocket_toolpath
|
||||
#include <vde/core/cam_5axis.h> // 5轴联动: swarf, multi_axis_roughing
|
||||
#include <vde/core/object_pool.h> // ObjectPool<T> 内存池
|
||||
```
|
||||
|
||||
### curves — 曲线曲面 (`vde::curves`)
|
||||
|
||||
```cpp
|
||||
#include <vde/curves/bezier_curve.h> // BezierCurve
|
||||
#include <vde/curves/bspline_curve.h> // BSplineCurve
|
||||
#include <vde/curves/nurbs_curve.h> // NurbsCurve
|
||||
#include <vde/curves/bezier_surface.h> // BezierSurface
|
||||
#include <vde/curves/bspline_surface.h> // BSplineSurface
|
||||
#include <vde/curves/nurbs_surface.h> // NurbsSurface
|
||||
#include <vde/curves/nurbs_operations.h> // offset, trim, blend, ruled, coons, extrude
|
||||
#include <vde/curves/tessellation.h> // adaptive_tessellate()
|
||||
#include <vde/curves/surface_intersection.h> // surface_intersect()
|
||||
#include <vde/curves/surface_analysis.h> // curvature_analysis()
|
||||
#include <vde/curves/surface_continuity.h>// G0/G1/G2 continuity check
|
||||
#include <vde/curves/surface_fairing.h> // surface_fairing()
|
||||
#include <vde/curves/exact_offset.h> // exact_offset_curve()
|
||||
#include <vde/curves/surface_extension.h> // extend_surface()
|
||||
#include <vde/curves/parallel_intersection.h> // parallel_intersect()
|
||||
```
|
||||
|
||||
### mesh — 网格处理 (`vde::mesh`)
|
||||
|
||||
```cpp
|
||||
#include <vde/mesh/halfedge_mesh.h> // HalfedgeMesh
|
||||
#include <vde/mesh/delaunay_2d.h> // delaunay_2d(), cdt_2d()
|
||||
#include <vde/mesh/delaunay_3d.h> // delaunay_3d()
|
||||
#include <vde/mesh/mesh_simplify.h> // qem_simplify()
|
||||
#include <vde/mesh/mesh_smooth.h> // laplacian_smooth(), hc_smooth(), bilateral_smooth()
|
||||
#include <vde/mesh/mesh_boolean.h> // mesh_union(), mesh_intersection(), mesh_difference()
|
||||
#include <vde/mesh/mesh_quality.h> // mesh_quality_report()
|
||||
#include <vde/mesh/mesh_repair.h> // repair_non_manifold()
|
||||
#include <vde/mesh/alpha_shapes.h> // alpha_shape()
|
||||
#include <vde/mesh/mesh_parameterize.h> // parameterize()
|
||||
#include <vde/mesh/geodesic.h> // geodesic_distance()
|
||||
#include <vde/mesh/mesh_curvature.h> // curvature()
|
||||
#include <vde/mesh/marching_cubes.h> // marching_cubes()
|
||||
#include <vde/mesh/parallel_mc.h> // parallel_marching_cubes()
|
||||
#include <vde/mesh/mesh_lod.h> // generate_lod()
|
||||
#include <vde/mesh/reverse_engineering.h> // reverse_engineering pipeline
|
||||
#include <vde/mesh/point_cloud.h> // PointCloud processing
|
||||
#include <vde/mesh/fea_mesh.h> // FEA mesh generation
|
||||
```
|
||||
|
||||
### spatial — 空间索引 (`vde::spatial`)
|
||||
|
||||
```cpp
|
||||
#include <vde/spatial/bvh.h> // BVH<Triangle>
|
||||
#include <vde/spatial/octree.h> // Octree<Point3D>
|
||||
#include <vde/spatial/kd_tree.h> // KDTree<Point3D>
|
||||
#include <vde/spatial/r_tree.h> // RTree<AABB3D>
|
||||
#include <vde/spatial/incremental_bvh.h> // IncrementalBVH
|
||||
```
|
||||
|
||||
### boolean — 布尔运算 (`vde::boolean`)
|
||||
|
||||
```cpp
|
||||
#include <vde/boolean/boolean_2d.h> // clip_polygon(), boolean_2d()
|
||||
#include <vde/boolean/boolean_mesh.h> // mesh_union(), mesh_difference(), mesh_intersection()
|
||||
#include <vde/boolean/polygon_offset.h> // offset_polygon()
|
||||
```
|
||||
|
||||
### collision — 碰撞检测 (`vde::collision`)
|
||||
|
||||
```cpp
|
||||
#include <vde/collision/gjk.h> // gjk_distance(), gjk_intersect()
|
||||
#include <vde/collision/sat.h> // sat_intersect()
|
||||
#include <vde/collision/ray_intersect.h> // ray_triangle(), ray_aabb(), ray_mesh()
|
||||
#include <vde/collision/tri_intersect.h> // tri_tri_intersection()
|
||||
```
|
||||
|
||||
### brep — B-Rep 建模 (`vde::brep`)
|
||||
|
||||
```cpp
|
||||
#include <vde/brep/brep.h> // BrepModel, TopoVertex, TopoEdge, TopoFace
|
||||
#include <vde/brep/modeling.h> // make_box, make_sphere, fillet, chamfer, shell
|
||||
#include <vde/brep/brep_boolean.h> // brep_union, brep_intersection, brep_difference
|
||||
#include <vde/brep/brep_validate.h> // validate()
|
||||
#include <vde/brep/brep_heal.h> // heal()
|
||||
#include <vde/brep/tolerance.h> // Tolerance settings
|
||||
#include <vde/brep/trimmed_surface.h> // TrimmedSurface
|
||||
#include <vde/brep/ssi_boolean.h> // Surface-surface intersection boolean
|
||||
#include <vde/brep/format_io.h> // STEP/IGES import/export
|
||||
#include <vde/brep/measure.h> // distance, surface_area, volume, centroid
|
||||
#include <vde/brep/brep_drawing.h> // Drawing generation
|
||||
#include <vde/brep/auto_dimensioning.h> // Automatic dimensioning
|
||||
#include <vde/brep/pmi_mbd.h> // PMI/MBD annotations
|
||||
#include <vde/brep/gdt.h> // GD&T annotations
|
||||
#include <vde/brep/euler_op.h> // Euler operators
|
||||
#include <vde/brep/draft_analysis.h> // Draft angle analysis
|
||||
#include <vde/brep/feature_recognition.h> // Feature recognition
|
||||
#include <vde/brep/defeature.h> // Defeaturing
|
||||
#include <vde/brep/advanced_blend.h> // Advanced blending
|
||||
#include <vde/brep/ffd_deformation.h> // Free-form deformation
|
||||
#include <vde/brep/constraint_solver.h> // Assembly constraint solving
|
||||
#include <vde/brep/direct_modeling.h> // Direct modeling
|
||||
#include <vde/brep/kinematic_chain.h> // Kinematic chains
|
||||
#include <vde/brep/motion_simulation.h> // Motion simulation
|
||||
#include <vde/brep/assembly_lod.h> // Assembly LOD
|
||||
#include <vde/brep/fastener_library.h> // Fastener library
|
||||
```
|
||||
|
||||
### sdf — 隐式建模 (`vde::sdf`)
|
||||
|
||||
```cpp
|
||||
#include <vde/sdf/sdf_primitives.h> // sphere, box, cylinder, torus, cone, etc.
|
||||
#include <vde/sdf/sdf_operations.h> // union, intersection, difference, smooth_union
|
||||
#include <vde/sdf/sdf_tree.h> // SdfNode, evaluate()
|
||||
#include <vde/sdf/sdf_to_mesh.h> // sdf_to_mesh()
|
||||
#include <vde/sdf/sdf_gradient.h> // gradient()
|
||||
#include <vde/sdf/sdf_optimize.h> // fit_to_point_cloud(), optimize()
|
||||
```
|
||||
|
||||
### sketch — 草图约束 (`vde::sketch`)
|
||||
|
||||
```cpp
|
||||
#include <vde/sketch/constraint_solver.h> // ConstraintSolver
|
||||
```
|
||||
|
||||
### plugin — 插件系统 (`vde::plugin`, v6.0+)
|
||||
|
||||
```cpp
|
||||
#include <vde/plugin/plugin_system.h> // PluginInterface, PluginManager, PluginManifest
|
||||
```
|
||||
|
||||
详见 [插件系统设计](plugin-system.md)。
|
||||
|
||||
## 核心类型速查
|
||||
|
||||
| 类型 | 命名空间 | 说明 |
|
||||
|------|---------|------|
|
||||
| `Point2D` / `Point3D` | `vde::core` | 2D/3D 点 |
|
||||
| `Vector2D` / `Vector3D` | `vde::core` | 2D/3D 向量 |
|
||||
| `AABB2D` / `AABB3D` | `vde::core` | 轴对齐包围盒 |
|
||||
| `Matrix3x3` / `Matrix4x4` | `vde::core` | 3x3 / 4x4 变换矩阵 |
|
||||
| `Triangle` | `vde::core` | 三角形 |
|
||||
| `HalfedgeMesh` | `vde::mesh` | 半边网格数据结构 |
|
||||
| `BrepModel` | `vde::brep` | B-Rep 实体模型 |
|
||||
| `SdfNode` | `vde::sdf` | SDF 场景图节点 |
|
||||
| `BezierCurve` | `vde::curves` | Bézier 曲线 |
|
||||
| `NurbsSurface` | `vde::curves` | NURBS 曲面 |
|
||||
|
||||
## 使用约定
|
||||
|
||||
### 头文件包含
|
||||
|
||||
```cpp
|
||||
// 推荐:只包含需要的头文件
|
||||
#include <vde/mesh/halfedge_mesh.h>
|
||||
#include <vde/core/point.h>
|
||||
|
||||
// 不推荐:包含聚合头(编译慢)
|
||||
// #include <vde/vde.h> // 不存在此文件
|
||||
```
|
||||
|
||||
### 命名空间使用
|
||||
|
||||
```cpp
|
||||
// .cpp 文件中可以使用 using
|
||||
using namespace vde::core;
|
||||
using namespace vde::mesh;
|
||||
|
||||
// .h 文件中禁止 using namespace
|
||||
// 使用完整限定名或在作用域内声明
|
||||
namespace vde::my_module {
|
||||
using vde::core::Point3D;
|
||||
}
|
||||
```
|
||||
|
||||
### 错误处理
|
||||
|
||||
VDE 采用以下错误处理策略:
|
||||
- **返回值**: 大部分函数返回 `std::optional<T>` 或错误码
|
||||
- **断言**: 内部不变量使用 `assert()`
|
||||
- **异常**: 仅在构造函数/资源分配失败时使用(RAII 保证)
|
||||
- **日志**: 通过 `VDE_LOG_WARNING` / `VDE_LOG_ERROR` 宏
|
||||
|
||||
### 线程安全
|
||||
|
||||
- 所有 `const` 方法可并发调用
|
||||
- 非 `const` 方法需要外部同步
|
||||
- PluginManager 提供内部读写锁
|
||||
@@ -0,0 +1,240 @@
|
||||
# 架构概览
|
||||
|
||||
## 1. 整体架构
|
||||
|
||||
ViewDesignEngine 采用分层架构,从底层数学基础设施到高层领域建模,层层递进。v6.0 引入了插件系统,支持第三方扩展。
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 应用层 (Application) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌────────────────┐ │
|
||||
│ │ C++ API │ │ Python绑定│ │ C API │ │ 插件系统 (v6) │ │
|
||||
│ │ (头文件) │ │(pybind11) │ │ (vde_capi)│ │ PluginManager │ │
|
||||
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └───────┬────────┘ │
|
||||
│ │ │ │ │ │
|
||||
├────────┴──────────────┴─────────────┴───────────────┴────────────┤
|
||||
│ 领域建模层 (Domain) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ B-Rep │ │ SDF │ │ Sketch │ │ CAM │ │
|
||||
│ │ 实体建模 │ │ 隐式建模 │ │ 草图约束 │ │ 加工策略 │ │
|
||||
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └────────┬─────────┘ │
|
||||
│ │ │ │ │ │
|
||||
├────────┴──────────────┴─────────────┴───────────────┴────────────┤
|
||||
│ 几何处理层 (Geometry) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ Curves │ │ Mesh │ │ Boolean │ │ Collision │ │
|
||||
│ │ 曲线曲面 │ │ 网格处理 │ │ 布尔运算 │ │ 碰撞检测 │ │
|
||||
│ └─────┬─────┘ └─────┬────┘ └─────┬────┘ └────────┬─────────┘ │
|
||||
│ │ │ │ │ │
|
||||
│ └──────────────┴──────┬──────┴───────────────┘ │
|
||||
│ │ │
|
||||
├──────────────────────────────┴────────────────────────────────────┤
|
||||
│ 空间索引层 (Spatial) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ BVH │ │ Octree │ │ KD-Tree │ │ R-Tree │ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
|
||||
├───────────────────────────────────────────────────────────────────┤
|
||||
│ 基础设施层 (Foundation) │
|
||||
│ ┌──────────┐ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │
|
||||
│ │ Eigen封装│ │ 公差系统 │ │ I/O │ │ 精确谓词 │ │
|
||||
│ │ 数学库 │ │Tolerance │ │格式读写 │ │ exact_predicates│ │
|
||||
│ └──────────┘ └──────────┘ └──────────┘ └──────────────────┘ │
|
||||
└───────────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 2. 模块依赖图
|
||||
|
||||
```
|
||||
┌─────────────────────┐
|
||||
│ vde (聚合) │
|
||||
└──────────┬──────────┘
|
||||
┌───────────────────┼───────────────────┐
|
||||
│ │ │
|
||||
┌──────┴──────┐ ┌──────┴──────┐ ┌──────┴──────┐
|
||||
│ vde_capi │ │ vde_brep │ │ vde_plugin │
|
||||
│ (C 接口) │ │ (B-Rep) │ │ (插件系统) │
|
||||
└──────┬──────┘ └──────┬──────┘ └──────┬──────┘
|
||||
│ │ │
|
||||
┌──────┼──────────┬──────┼──────────┐ │
|
||||
│ │ │ │ │ │
|
||||
▼ ▼ ▼ ▼ ▼ │
|
||||
┌──────┐┌──────┐┌──────┐┌──────┐┌─────────┐ │
|
||||
│vde_ ││vde_ ││vde_ ││vde_ ││vde_ │ │
|
||||
│sdf ││sketch││mesh ││curves││collision│ │
|
||||
└──┬───┘└──┬───┘└──┬───┘└──┬───┘└────┬────┘ │
|
||||
│ │ │ │ │ │
|
||||
└───────┴───────┼───────┴─────────┘ │
|
||||
│ │
|
||||
┌────┴────┐ ┌─────┴──────┐
|
||||
│vde_core │ │vde_spatial │
|
||||
└────┬────┘ └─────┬──────┘
|
||||
│ │
|
||||
┌────┴──────────────────────────┘
|
||||
│
|
||||
┌────┴──────────┐
|
||||
│vde_foundation │
|
||||
└───────┬───────┘
|
||||
│
|
||||
┌─────┴─────┐
|
||||
│Eigen3 (外部)│
|
||||
└───────────┘
|
||||
|
||||
vde_boolean 依赖: vde_mesh + vde_spatial + vde_core
|
||||
vde_collision 依赖: vde_core + vde_spatial
|
||||
vde_gpu (可选): vde_mesh + CUDA::cudart
|
||||
vde_plugin 依赖: vde_foundation (独立于其他模块)
|
||||
```
|
||||
|
||||
## 3. 数据流
|
||||
|
||||
### 3.1 典型几何处理管线
|
||||
|
||||
```
|
||||
输入 (STEP/IGES/OBJ/STL)
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Format I/O │ foundation::import_step / import_iges / load_obj / load_stl
|
||||
│ 格式解析 │
|
||||
└──────┬───────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ 几何核心 │ core::Point3D, core::AABB3D, core::transform
|
||||
│ 类型系统 │
|
||||
└──────┬───────┘
|
||||
│
|
||||
├─────────────────────────────────────┐
|
||||
▼ ▼
|
||||
┌──────────────┐ ┌──────────────┐
|
||||
│ 曲线曲面建模 │ │ 网格处理 │
|
||||
│ curves │ │ mesh │
|
||||
│ Bezier/NURBS │ │ Delaunay/MC │
|
||||
└──────┬───────┘ └──────┬───────┘
|
||||
│ │
|
||||
├──────────────┬──────────────────────┘
|
||||
▼ ▼
|
||||
┌──────────────┐┌──────────────┐
|
||||
│ 空间索引 ││ 布尔运算 │
|
||||
│ spatial ││ boolean │
|
||||
│ BVH/Octree ││ CSG │
|
||||
└──────┬───────┘└──────┬───────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌──────────────┐┌──────────────┐
|
||||
│ 碰撞检测 ││ B-Rep 建模 │
|
||||
│ collision ││ brep │
|
||||
│ GJK/SAT ││ 抽壳/倒圆 │
|
||||
└──────┬───────┘└──────┬───────┘
|
||||
│ │
|
||||
└───────┬───────┘
|
||||
▼
|
||||
┌──────────────┐
|
||||
│ Format I/O │ foundation::export_step / export_gltf / export_stl
|
||||
│ 格式导出 │
|
||||
└──────┬───────┘
|
||||
▼
|
||||
输出 (STEP/glTF/STL/OBJ)
|
||||
```
|
||||
|
||||
### 3.2 插件系统数据流 (v6.0)
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ PluginManager │
|
||||
│ │
|
||||
│ load_plugin_dir("/usr/lib/vde/plugins") │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────┐ │
|
||||
│ │ 扫描 .so/.dylib/.dll 文件 │ │
|
||||
│ │ dlopen → dlsym(create_plugin) │ │
|
||||
│ │ → PluginInterface* │ │
|
||||
│ └──────────────┬──────────────────────┘ │
|
||||
│ │ │
|
||||
│ ▼ │
|
||||
│ ┌─────────────────────────────────────┐ │
|
||||
│ │ PluginRegistry (name → Plugin*) │ │
|
||||
│ │ io_exporters / io_importers │ │
|
||||
│ │ geometry_filters │ │
|
||||
│ │ custom_tools │ │
|
||||
│ └─────────────────────────────────────┘ │
|
||||
│ │
|
||||
│ 调用: manager.get_plugin("io.export.gltf") │
|
||||
│ → PluginInterface::execute(...) │
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 3.3 可微分几何管线 (SDF)
|
||||
|
||||
```
|
||||
参数化形状 (SdfNode)
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ SDF 求值 │ sdf::evaluate(node, point)
|
||||
│ (CSG 树遍历) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ 自动微分 │ sdf::gradient(node, point)
|
||||
│ (正向/反向模式) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ 梯度优化 │ sdf::optimize::fit_to_point_cloud
|
||||
│ (Adam/SGD) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ SDF → Mesh │ sdf::marching_cubes → HalfedgeMesh
|
||||
│ (Marching Cubes) │
|
||||
└────────┬─────────┘
|
||||
│
|
||||
▼
|
||||
┌──────────────────┐
|
||||
│ 导出 GLB │ foundation::export_gltf_binary
|
||||
└──────────────────┘
|
||||
```
|
||||
|
||||
## 4. 线程模型
|
||||
|
||||
- **单线程默认**: 所有 API 默认线程安全,内部无全局可变状态
|
||||
- **OpenMP 并行**: 在 B-Rep 布尔、网格处理等热点路径启用 (`VDE_USE_OPENMP=ON`)
|
||||
- **CUDA 加速**: 独立 GPU 库 `vde_gpu`,不阻塞 CPU 路径
|
||||
- **插件线程安全**: 插件需自行保证线程安全,PluginManager 提供读写锁
|
||||
|
||||
## 5. 内存模型
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────┐
|
||||
│ 内存分配策略 │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌─────────────────┐ │
|
||||
│ │ ObjectPool │ │ std::unique_ptr │ │
|
||||
│ │ (mesh顶点/面) │ │ (B-Rep 实体) │ │
|
||||
│ │ 连续内存块 │ │ RAII 所有权 │ │
|
||||
│ └──────────────┘ └─────────────────┘ │
|
||||
│ │
|
||||
│ ┌──────────────┐ ┌─────────────────┐ │
|
||||
│ │ SoA 布局 │ │ 小对象栈分配 │ │
|
||||
│ │ (AoS→SoA) │ │ (Point3D/AABB) │ │
|
||||
│ │ 缓存友好 │ │ 零堆开销 │ │
|
||||
│ └──────────────┘ └─────────────────┘ │
|
||||
└─────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 6. 版本演进
|
||||
|
||||
| 版本 | 关键里程碑 | 日期 |
|
||||
|------|-----------|------|
|
||||
| v0.1 - v0.9 | 核心模块建立 | 2026-07-23 |
|
||||
| v1.0 | 首个稳定版本 | 2026-07-24 |
|
||||
| v2.0 | B-Rep 完善 + STEP | 2026-07-24 |
|
||||
| v3.0 - v3.5 | SDF/IGES/装配/CAM | 2026-07-24 |
|
||||
| v4.x | 工业强化 (GDT/PMI/特征识别) | 计划中 |
|
||||
| v5.x | 性能优化 + 反向工程 | 计划中 |
|
||||
| v6.0 | 插件系统 + 开发者生态 | 计划中 |
|
||||
@@ -0,0 +1,292 @@
|
||||
# 构建指南
|
||||
|
||||
本文档说明如何从源码构建 ViewDesignEngine。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [环境要求](#1-环境要求)
|
||||
2. [快速构建](#2-快速构建)
|
||||
3. [Docker 构建](#3-docker-构建)
|
||||
4. [CMake 选项](#4-cmake-选项)
|
||||
5. [依赖管理](#5-依赖管理)
|
||||
6. [跨平台构建](#6-跨平台构建)
|
||||
7. [常见问题](#7-常见问题)
|
||||
|
||||
---
|
||||
|
||||
## 1. 环境要求
|
||||
|
||||
| 组件 | 最低版本 | 推荐版本 |
|
||||
|------|---------|---------|
|
||||
| C++ 编译器 | GCC 11 / Clang 16 | GCC 13 / Clang 18 |
|
||||
| CMake | 3.16 | 3.28+ |
|
||||
| Eigen 3 | 3.3 | 3.4.0 (自动下载) |
|
||||
| Python (可选) | 3.8 | 3.11+ |
|
||||
| pybind11 (可选) | 2.10 | 2.12+ |
|
||||
| CUDA (可选) | 10.0 | 12.0+ |
|
||||
|
||||
### 安装编译工具
|
||||
|
||||
**Ubuntu/Debian**:
|
||||
```bash
|
||||
sudo apt update
|
||||
sudo apt install build-essential cmake g++-11
|
||||
```
|
||||
|
||||
**CentOS/RHEL 8**:
|
||||
```bash
|
||||
sudo yum install gcc-toolset-11 cmake3
|
||||
scl enable gcc-toolset-11 bash
|
||||
```
|
||||
|
||||
**macOS**:
|
||||
```bash
|
||||
brew install cmake gcc@13
|
||||
```
|
||||
|
||||
**Windows (MSYS2)**:
|
||||
```bash
|
||||
pacman -S mingw-w64-x86_64-cmake mingw-w64-x86_64-gcc
|
||||
```
|
||||
|
||||
## 2. 快速构建
|
||||
|
||||
```bash
|
||||
# 克隆仓库
|
||||
git clone ssh://git@localhost:22/hm/ViewDesignEngine.git
|
||||
cd ViewDesignEngine
|
||||
|
||||
# 创建构建目录
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
|
||||
# 构建(使用所有 CPU 核心)
|
||||
cmake --build build -j$(nproc)
|
||||
|
||||
# 运行测试
|
||||
cd build && ctest --output-on-failure
|
||||
```
|
||||
|
||||
### 构建类型
|
||||
|
||||
| 类型 | 说明 |
|
||||
|------|------|
|
||||
| `Release` | 优化构建,生产环境使用 |
|
||||
| `Debug` | 调试符号,无优化 |
|
||||
| `RelWithDebInfo` | 优化 + 调试符号 |
|
||||
| `MinSizeRel` | 最小体积 |
|
||||
|
||||
```bash
|
||||
# Debug 构建(包含 Address Sanitizer)
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
## 3. Docker 构建
|
||||
|
||||
推荐使用 Docker 确保构建环境一致。
|
||||
|
||||
### 3.1 预构建镜像
|
||||
|
||||
```bash
|
||||
# 拉取或构建镜像
|
||||
docker build -t vde-builder -f docker/Dockerfile.dev .
|
||||
|
||||
# Release 构建
|
||||
docker run --rm --cpus=4 --memory=8g \
|
||||
-v $(pwd):/ws vde-builder bash -c \
|
||||
"cd /ws && cmake -B build -DCMAKE_BUILD_TYPE=Release && cmake --build build -j4"
|
||||
|
||||
# 运行测试
|
||||
docker run --rm --cpus=4 --memory=8g \
|
||||
-v $(pwd):/ws vde-builder bash -c \
|
||||
"cd /ws/build && ctest --output-on-failure"
|
||||
```
|
||||
|
||||
### 3.2 资源限制
|
||||
|
||||
```bash
|
||||
# 模拟低配环境(2 核 / 4GB)
|
||||
docker run --rm --cpus=2 --memory=4g --memory-swap=4g \
|
||||
-v $(pwd):/ws vde-builder bash -c \
|
||||
"cd /ws && cmake -B build_ci -DCMAKE_BUILD_TYPE=Release && cmake --build build_ci -j2"
|
||||
```
|
||||
|
||||
## 4. CMake 选项
|
||||
|
||||
| 选项 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| `BUILD_TESTS` | ON | 构建测试 |
|
||||
| `BUILD_BENCHMARKS` | OFF | 构建性能基准 |
|
||||
| `BUILD_EXAMPLES` | ON | 构建示例程序 |
|
||||
| `ENABLE_SANITIZERS` | OFF | 启用 Address Sanitizer |
|
||||
| `VDE_USE_GMP` | OFF | GMP 精确运算 |
|
||||
| `VDE_USE_OPENMP` | ON | OpenMP 并行 |
|
||||
| `VDE_USE_CUDA` | OFF | CUDA GPU 加速 |
|
||||
| `VDE_BUILD_PYTHON` | OFF | Python 绑定 |
|
||||
|
||||
### 常用组合
|
||||
|
||||
```bash
|
||||
# 开发调试(ASan + Debug)
|
||||
cmake -B build_asan \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_SANITIZERS=ON \
|
||||
-DVDE_USE_OPENMP=OFF
|
||||
|
||||
# 生产构建(Release + OpenMP)
|
||||
cmake -B build_release \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DVDE_USE_OPENMP=ON
|
||||
|
||||
# GPU 加速
|
||||
cmake -B build_gpu \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DVDE_USE_CUDA=ON
|
||||
|
||||
# Python 绑定
|
||||
cmake -B build_py \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DVDE_BUILD_PYTHON=ON
|
||||
|
||||
# 基准测试
|
||||
cmake -B build_bench \
|
||||
-DCMAKE_BUILD_TYPE=Release \
|
||||
-DBUILD_BENCHMARKS=ON
|
||||
```
|
||||
|
||||
## 5. 依赖管理
|
||||
|
||||
VDE 使用 CMake FetchContent 自动下载依赖,无需手动安装。
|
||||
|
||||
### 自动下载的依赖
|
||||
|
||||
| 依赖 | 版本 | 用途 |
|
||||
|------|------|------|
|
||||
| Eigen 3 | 3.4.0 | 线性代数 |
|
||||
| Google Test | 1.14.0 | 单元测试 |
|
||||
| Google Benchmark | (可选) | 性能基准 |
|
||||
| pybind11 | (可选) | Python 绑定 |
|
||||
|
||||
### 系统依赖
|
||||
|
||||
| 依赖 | 检测方式 | 回退 |
|
||||
|------|---------|------|
|
||||
| Eigen 3 | `find_package(Eigen3)` | FetchContent 自动下载 |
|
||||
| GMP | `find_package(GMP)` | `VDE_USE_GMP=OFF` 时跳过 |
|
||||
| OpenMP | `find_package(OpenMP)` | `VDE_USE_OPENMP=OFF` 时跳过 |
|
||||
| CUDA | `find_package(CUDAToolkit)` | `VDE_USE_CUDA=OFF` 时跳过 |
|
||||
|
||||
```bash
|
||||
# 使用系统 Eigen(加速首次构建)
|
||||
sudo apt install libeigen3-dev # Ubuntu
|
||||
sudo yum install eigen3-devel # CentOS
|
||||
|
||||
# 使用系统 GTest
|
||||
sudo apt install libgtest-dev # Ubuntu
|
||||
```
|
||||
|
||||
## 6. 跨平台构建
|
||||
|
||||
### Linux
|
||||
|
||||
```bash
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
### macOS
|
||||
|
||||
```bash
|
||||
# 使用 Homebrew GCC
|
||||
export CC=/usr/local/bin/gcc-13
|
||||
export CXX=/usr/local/bin/g++-13
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j$(sysctl -n hw.ncpu)
|
||||
```
|
||||
|
||||
### Windows (MSYS2 MinGW64)
|
||||
|
||||
```bash
|
||||
cmake -B build -G "MinGW Makefiles" -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
### Windows (Visual Studio)
|
||||
|
||||
```bash
|
||||
cmake -B build -G "Visual Studio 17 2022"
|
||||
cmake --build build --config Release
|
||||
```
|
||||
|
||||
## 7. 常见问题
|
||||
|
||||
### Q: CMake 找不到编译器
|
||||
|
||||
```bash
|
||||
export CC=/usr/bin/gcc-11
|
||||
export CXX=/usr/bin/g++-11
|
||||
cmake -B build ...
|
||||
```
|
||||
|
||||
### Q: FetchContent 下载失败(网络问题)
|
||||
|
||||
手动下载并放到 `build/_deps/`:
|
||||
```bash
|
||||
mkdir -p build/_deps
|
||||
# 下载 eigen-3.4.0.tar.gz 到 build/_deps/
|
||||
# 下载 googletest-1.14.0.tar.gz 到 build/_deps/
|
||||
```
|
||||
|
||||
### Q: 编译内存不足
|
||||
|
||||
```bash
|
||||
# 限制并行数
|
||||
cmake --build build -j2
|
||||
|
||||
# 或在 Docker 中限制内存
|
||||
docker run --memory=4g ...
|
||||
```
|
||||
|
||||
### Q: ASan 报告内存泄漏
|
||||
|
||||
```bash
|
||||
# Debug + ASan 构建
|
||||
cmake -B build_asan -DCMAKE_BUILD_TYPE=Debug -DENABLE_SANITIZERS=ON
|
||||
cmake --build build_asan -j$(nproc)
|
||||
|
||||
# 运行测试并检查泄漏
|
||||
cd build_asan
|
||||
ASAN_OPTIONS=detect_leaks=1 ctest --output-on-failure
|
||||
```
|
||||
|
||||
### Q: 如何加速增量构建
|
||||
|
||||
```bash
|
||||
# 安装 ccache
|
||||
sudo apt install ccache
|
||||
export CMAKE_C_COMPILER_LAUNCHER=ccache
|
||||
export CMAKE_CXX_COMPILER_LAUNCHER=ccache
|
||||
cmake -B build ...
|
||||
```
|
||||
|
||||
### Q: 构建产物位置
|
||||
|
||||
```
|
||||
build/
|
||||
├── src/ # 静态库 (.a)
|
||||
│ ├── libvde_foundation.a
|
||||
│ ├── libvde_core.a
|
||||
│ ├── libvde_curves.a
|
||||
│ ├── libvde_mesh.a
|
||||
│ ├── libvde_spatial.a
|
||||
│ ├── libvde_boolean.a
|
||||
│ ├── libvde_collision.a
|
||||
│ ├── libvde_brep.a
|
||||
│ ├── libvde_sdf.a
|
||||
│ ├── libvde_sketch.a
|
||||
│ └── libvde_capi.a
|
||||
├── tests/ # 测试可执行文件
|
||||
├── bench/ # 基准测试 (BUILD_BENCHMARKS=ON)
|
||||
├── examples/ # 示例程序
|
||||
└── python/ # Python 绑定 (VDE_BUILD_PYTHON=ON)
|
||||
```
|
||||
@@ -0,0 +1,249 @@
|
||||
# 贡献指南
|
||||
|
||||
感谢你对 ViewDesignEngine 的关注!本文档说明如何参与 VDE 开发。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [行为准则](#1-行为准则)
|
||||
2. [如何贡献](#2-如何贡献)
|
||||
3. [开发环境搭建](#3-开发环境搭建)
|
||||
4. [代码规范](#4-代码规范)
|
||||
5. [提交规范](#5-提交规范)
|
||||
6. [Code Review 流程](#6-code-review-流程)
|
||||
7. [测试要求](#7-测试要求)
|
||||
8. [文档要求](#8-文档要求)
|
||||
|
||||
---
|
||||
|
||||
## 1. 行为准则
|
||||
|
||||
- 尊重所有贡献者,建设性沟通
|
||||
- 关注代码质量而非个人
|
||||
- 接受建设性批评,乐于改进
|
||||
- 帮助新人融入项目
|
||||
|
||||
## 2. 如何贡献
|
||||
|
||||
| 贡献方式 | 说明 |
|
||||
|---------|------|
|
||||
| Bug 报告 | 通过 Issue 提交,附重现步骤 |
|
||||
| 功能请求 | 先开 Issue 讨论,获得认同后再实现 |
|
||||
| 代码贡献 | Fork → Branch → PR → Review → Merge |
|
||||
| 文档改进 | 直接提 PR 修正文档错误 |
|
||||
| 测试补充 | 新增测试用例,提高覆盖率 |
|
||||
| 插件开发 | 按 [插件系统设计](plugin-system.md) 开发第三方插件 |
|
||||
|
||||
### 贡献流程
|
||||
|
||||
```bash
|
||||
# 1. 创建分支
|
||||
git checkout -b feat/my-feature
|
||||
|
||||
# 2. 开发(遵循代码规范)
|
||||
# ... 编写代码 + 测试 ...
|
||||
|
||||
# 3. 本地验证
|
||||
cmake -B build -DBUILD_TESTS=ON
|
||||
cmake --build build -j$(nproc)
|
||||
cd build && ctest --output-on-failure
|
||||
|
||||
# 4. 提交
|
||||
git add -A
|
||||
git commit -m "feat(module): description"
|
||||
|
||||
# 5. 推送并创建 PR
|
||||
git push origin feat/my-feature
|
||||
```
|
||||
|
||||
## 3. 开发环境搭建
|
||||
|
||||
### 前提条件
|
||||
|
||||
- **编译器**: GCC 11+ / Clang 16+
|
||||
- **CMake**: ≥ 3.16
|
||||
- **Eigen 3**: 自动下载(FetchContent)
|
||||
- **Google Test**: 自动下载(FetchContent)
|
||||
|
||||
### Docker 环境(推荐)
|
||||
|
||||
```bash
|
||||
# 构建 Docker 镜像
|
||||
docker build -t vde-builder -f docker/Dockerfile.dev .
|
||||
|
||||
# 运行开发容器
|
||||
docker run -it --rm -v $PWD:/ws vde-builder bash
|
||||
cd /ws
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
### 本地环境
|
||||
|
||||
```bash
|
||||
# Ubuntu/Debian
|
||||
sudo apt install build-essential cmake g++-11
|
||||
|
||||
# CentOS/RHEL
|
||||
sudo yum install gcc-toolset-11 cmake3
|
||||
|
||||
# 构建
|
||||
cmake -B build -DCMAKE_BUILD_TYPE=Debug
|
||||
cmake --build build -j$(nproc)
|
||||
```
|
||||
|
||||
## 4. 代码规范
|
||||
|
||||
### 命名规范
|
||||
|
||||
| 元素 | 规范 | 示例 |
|
||||
|------|------|------|
|
||||
| 命名空间 | 小写,`vde::` 前缀 | `vde::brep`, `vde::mesh` |
|
||||
| 类/结构体 | PascalCase | `HalfedgeMesh`, `BrepModel` |
|
||||
| 函数/方法 | snake_case | `add_vertex()`, `to_mesh()` |
|
||||
| 成员变量 | snake_case,尾部 `_` | `vertices_`, `tolerance_` |
|
||||
| 常量 | kPascalCase 或 UPPER_SNAKE | `kDefaultTolerance`, `VDE_PI` |
|
||||
| 头文件 | snake_case.h | `halfedge_mesh.h` |
|
||||
| 源文件 | snake_case.cpp | `halfedge_mesh.cpp` |
|
||||
| 模板参数 | PascalCase | `typename T`, `typename Scalar` |
|
||||
|
||||
### 文件组织
|
||||
|
||||
```cpp
|
||||
// 头文件示例
|
||||
#pragma once
|
||||
|
||||
#include <vde/foundation/point.h> // 公开依赖
|
||||
#include <vector> // 标准库
|
||||
|
||||
namespace vde::mesh {
|
||||
|
||||
/// 简要描述
|
||||
class HalfedgeMesh {
|
||||
public:
|
||||
// 构造/析构
|
||||
HalfedgeMesh();
|
||||
~HalfedgeMesh();
|
||||
|
||||
// 禁止拷贝,允许移动
|
||||
HalfedgeMesh(const HalfedgeMesh&) = delete;
|
||||
HalfedgeMesh& operator=(const HalfedgeMesh&) = delete;
|
||||
HalfedgeMesh(HalfedgeMesh&&) noexcept = default;
|
||||
HalfedgeMesh& operator=(HalfedgeMesh&&) noexcept = default;
|
||||
|
||||
// 公开接口
|
||||
int add_vertex(const Point3D& p);
|
||||
int add_face(const std::vector<int>& vertex_ids);
|
||||
|
||||
private:
|
||||
// 成员变量
|
||||
std::vector<Point3D> vertices_;
|
||||
};
|
||||
|
||||
} // namespace vde::mesh
|
||||
```
|
||||
|
||||
### 编码风格
|
||||
|
||||
- 缩进: 4 空格,不用 Tab
|
||||
- 行宽: 100 字符
|
||||
- 大括号: K&R 风格(开括号不换行)
|
||||
- 注释: Doxygen `///` 风格
|
||||
- `#include` 顺序: 本模块头 → 项目头 → 标准库
|
||||
- 避免 `using namespace` 在头文件中
|
||||
- 优先使用 `std::unique_ptr` 而非裸指针
|
||||
|
||||
### 禁止事项
|
||||
|
||||
- ❌ 全局可变状态
|
||||
- ❌ 裸 `new`/`delete`(用智能指针)
|
||||
- ❌ C 风格类型转换(用 `static_cast` 等)
|
||||
- ❌ 可变参数 `...`
|
||||
- ❌ 异常规范声明(`throw()`)
|
||||
- ❌ 头文件 `using namespace`
|
||||
|
||||
## 5. 提交规范
|
||||
|
||||
### 提交消息格式
|
||||
|
||||
```
|
||||
<type>(<scope>): <subject>
|
||||
|
||||
<body>
|
||||
|
||||
<footer>
|
||||
```
|
||||
|
||||
| type | 说明 |
|
||||
|------|------|
|
||||
| `feat` | 新功能 |
|
||||
| `fix` | Bug 修复 |
|
||||
| `docs` | 文档变更 |
|
||||
| `style` | 格式调整(不影响逻辑) |
|
||||
| `refactor` | 重构 |
|
||||
| `test` | 测试相关 |
|
||||
| `perf` | 性能优化 |
|
||||
| `chore` | 构建/工具 |
|
||||
|
||||
示例:
|
||||
```
|
||||
feat(brep): add variable radius fillet support
|
||||
|
||||
Implement rolling-ball variable radius fillet along edges.
|
||||
Supports linear and cubic radius variation.
|
||||
|
||||
Closes #42
|
||||
```
|
||||
|
||||
### 分支策略
|
||||
|
||||
- `main` — 稳定分支,只接受 PR
|
||||
- `feat/xxx` — 功能分支
|
||||
- `fix/xxx` — 修复分支
|
||||
- `docs/xxx` — 文档分支
|
||||
- `release/vX.Y` — 发布分支
|
||||
|
||||
## 6. Code Review 流程
|
||||
|
||||
1. **提交者**: 创建 PR,填写描述,关联 Issue
|
||||
2. **CI 检查**: 自动编译 + 测试必须通过
|
||||
3. **Reviewer**: 检查代码逻辑、风格、测试覆盖
|
||||
4. **迭代**: 根据反馈修改,`git commit --amend` + force push
|
||||
5. **合并**: Reviewer 批准后 squash merge
|
||||
|
||||
### Review 检查项
|
||||
|
||||
- [ ] 代码逻辑正确,无边界 bug
|
||||
- [ ] 命名清晰,符合规范
|
||||
- [ ] 公开 API 有 Doxygen 文档
|
||||
- [ ] 有对应的单元测试
|
||||
- [ ] 无编译警告(`-Wall -Wextra`)
|
||||
- [ ] 无内存泄漏(ASan 通过)
|
||||
- [ ] 性能不退化(benchmark 对比)
|
||||
|
||||
## 7. 测试要求
|
||||
|
||||
| 要求 | 说明 |
|
||||
|------|------|
|
||||
| 新功能 | 必须包含测试 |
|
||||
| Bug 修复 | 必须包含回归测试 |
|
||||
| 测试框架 | Google Test |
|
||||
| 覆盖率目标 | ≥ 80% 行覆盖 |
|
||||
| Sanitizer | 关键路径需通过 ASan/UBSan |
|
||||
|
||||
测试文件位置: `tests/<module>/test_<feature>.cpp`
|
||||
|
||||
详见 [测试指南](testing.md)。
|
||||
|
||||
## 8. 文档要求
|
||||
|
||||
| 变更类型 | 文档要求 |
|
||||
|---------|---------|
|
||||
| 新模块 | architecture.md 更新 + API 文档 + 教程 |
|
||||
| 新公开 API | Doxygen 注释 + API-REFERENCE 更新 |
|
||||
| 行为变更 | CHANGELOG 更新 |
|
||||
| 构建变更 | building.md 更新 |
|
||||
|
||||
## 联系方式
|
||||
|
||||
- Issue Tracker: Gitea Issues
|
||||
- 代码仓库: `ssh://git@localhost:22/hm/ViewDesignEngine.git`
|
||||
@@ -0,0 +1,501 @@
|
||||
# 插件系统设计
|
||||
|
||||
v6.0 引入插件系统,允许第三方开发者扩展 ViewDesignEngine 的功能,无需修改核心代码。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [设计目标](#1-设计目标)
|
||||
2. [架构概览](#2-架构概览)
|
||||
3. [核心组件](#3-核心组件)
|
||||
4. [插件开发](#4-插件开发)
|
||||
5. [插件加载流程](#5-插件加载流程)
|
||||
6. [生命周期管理](#6-生命周期管理)
|
||||
7. [清单文件](#7-清单文件)
|
||||
8. [安全考虑](#8-安全考虑)
|
||||
9. [最佳实践](#9-最佳实践)
|
||||
|
||||
---
|
||||
|
||||
## 1. 设计目标
|
||||
|
||||
| 目标 | 说明 |
|
||||
|------|------|
|
||||
| **零侵入** | 插件不修改核心代码,独立编译 |
|
||||
| **动态加载** | 运行时 dlopen 加载,无需重新编译 VDE |
|
||||
| **版本兼容** | Manifest 声明版本约束,自动检查兼容性 |
|
||||
| **隔离性** | 插件崩溃不影响主程序 |
|
||||
| **易开发** | 继承 `PluginInterface` 即可,最少样板代码 |
|
||||
|
||||
## 2. 架构概览
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ Application │
|
||||
│ │ │
|
||||
│ PluginManager │
|
||||
│ ┌──────┴──────┐ │
|
||||
│ │ Registry │ │
|
||||
│ │ name→Plugin* │ │
|
||||
│ └──────┬──────┘ │
|
||||
│ ┌───────────────┼───────────────┐ │
|
||||
│ │ │ │ │
|
||||
│ ┌────┴────┐ ┌────┴────┐ ┌────┴────┐ │
|
||||
│ │Plugin A │ │Plugin B │ │Plugin C │ │
|
||||
│ │(.so) │ │(.so) │ │(.so) │ │
|
||||
│ │IO Format│ │Geometry │ │ Custom │ │
|
||||
│ │Exporter │ │Filter │ │ Tool │ │
|
||||
│ └─────────┘ └─────────┘ └─────────┘ │
|
||||
│ │
|
||||
│ Plugin Directory: /usr/lib/vde/plugins/ │
|
||||
│ ./vde_plugins/ │
|
||||
│ $VDE_PLUGIN_PATH │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## 3. 核心组件
|
||||
|
||||
### 3.1 PluginInterface(抽象基类)
|
||||
|
||||
所有插件必须实现的接口:
|
||||
|
||||
```cpp
|
||||
namespace vde::plugin {
|
||||
|
||||
class PluginInterface {
|
||||
public:
|
||||
virtual ~PluginInterface() = default;
|
||||
|
||||
/// 插件初始化(加载后调用一次)
|
||||
virtual bool initialize() = 0;
|
||||
|
||||
/// 插件清理(卸载前调用一次)
|
||||
virtual void shutdown() = 0;
|
||||
|
||||
/// 返回插件清单
|
||||
virtual const PluginManifest& manifest() const = 0;
|
||||
|
||||
/// 插件唯一名称(如 "io.export.usdz")
|
||||
virtual const char* name() const = 0;
|
||||
|
||||
/// 插件版本(语义化版本)
|
||||
virtual const char* version() const = 0;
|
||||
|
||||
/// 执行插件功能
|
||||
virtual bool execute(const std::string& action,
|
||||
const std::map<std::string, std::string>& params,
|
||||
void* input, void* output) = 0;
|
||||
};
|
||||
|
||||
} // namespace vde::plugin
|
||||
```
|
||||
|
||||
### 3.2 PluginManifest(插件元数据)
|
||||
|
||||
```cpp
|
||||
namespace vde::plugin {
|
||||
|
||||
struct PluginManifest {
|
||||
std::string name; ///< 唯一标识符,如 "io.export.usdz"
|
||||
std::string version; ///< 语义化版本 "1.0.0"
|
||||
std::string author; ///< 作者信息
|
||||
std::string description; ///< 功能描述
|
||||
std::string license; ///< 许可证 "MIT" / "Apache-2.0"
|
||||
std::string vde_version_min;///< 最低 VDE 版本 "6.0.0"
|
||||
std::string vde_version_max;///< 最高兼容 VDE 版本 (空=无上限)
|
||||
|
||||
/// 插件类型
|
||||
enum class Type {
|
||||
IO_IMPORT, ///< 格式导入器
|
||||
IO_EXPORT, ///< 格式导出器
|
||||
GEOMETRY_FILTER,///< 几何过滤器
|
||||
CUSTOM_TOOL, ///< 自定义工具
|
||||
OTHER
|
||||
};
|
||||
Type type = Type::OTHER;
|
||||
|
||||
/// 依赖的其他插件名称(可选)
|
||||
std::vector<std::string> dependencies;
|
||||
|
||||
/// 从 JSON 文件加载
|
||||
static std::optional<PluginManifest> from_file(const std::string& path);
|
||||
};
|
||||
|
||||
} // namespace vde::plugin
|
||||
```
|
||||
|
||||
### 3.3 PluginManager(插件管理器)
|
||||
|
||||
```cpp
|
||||
namespace vde::plugin {
|
||||
|
||||
class PluginManager {
|
||||
public:
|
||||
PluginManager();
|
||||
~PluginManager();
|
||||
|
||||
// 禁止拷贝
|
||||
PluginManager(const PluginManager&) = delete;
|
||||
PluginManager& operator=(const PluginManager&) = delete;
|
||||
|
||||
/// 从目录加载所有插件
|
||||
int load_plugin_dir(const std::string& dir_path);
|
||||
|
||||
/// 加载单个插件(路径到 .so/.dylib/.dll)
|
||||
bool load_plugin(const std::string& plugin_path);
|
||||
|
||||
/// 卸载指定插件
|
||||
bool unload_plugin(const std::string& name);
|
||||
|
||||
/// 卸载所有插件
|
||||
void unload_all();
|
||||
|
||||
/// 获取已加载的插件
|
||||
PluginInterface* get_plugin(const std::string& name);
|
||||
|
||||
/// 列出所有已加载插件
|
||||
std::vector<std::string> list_plugins() const;
|
||||
|
||||
/// 检查插件是否已加载
|
||||
bool is_loaded(const std::string& name) const;
|
||||
|
||||
/// 获取加载错误信息
|
||||
std::string last_error() const;
|
||||
|
||||
private:
|
||||
struct Impl;
|
||||
std::unique_ptr<Impl> impl_;
|
||||
};
|
||||
|
||||
} // namespace vde::plugin
|
||||
```
|
||||
|
||||
### 3.4 注册/加载函数
|
||||
|
||||
每个插件动态库必须导出以下 C 链接符号:
|
||||
|
||||
```cpp
|
||||
// 创建插件实例(必须导出)
|
||||
extern "C" VDE_PLUGIN_EXPORT vde::plugin::PluginInterface* create_plugin();
|
||||
|
||||
// 销毁插件实例(必须导出)
|
||||
extern "C" VDE_PLUGIN_EXPORT void destroy_plugin(vde::plugin::PluginInterface* plugin);
|
||||
|
||||
// 获取插件清单(可选,优化加载速度)
|
||||
extern "C" VDE_PLUGIN_EXPORT const vde::plugin::PluginManifest* get_manifest();
|
||||
```
|
||||
|
||||
## 4. 插件开发
|
||||
|
||||
### 4.1 最小插件示例
|
||||
|
||||
```cpp
|
||||
// my_exporter.cpp
|
||||
#include <vde/plugin/plugin_system.h>
|
||||
#include <iostream>
|
||||
|
||||
using namespace vde::plugin;
|
||||
|
||||
class MyExporter : public PluginInterface {
|
||||
public:
|
||||
bool initialize() override {
|
||||
manifest_.name = "io.export.myformat";
|
||||
manifest_.version = "1.0.0";
|
||||
manifest_.author = "Your Name";
|
||||
manifest_.description = "Export to MyFormat";
|
||||
manifest_.type = PluginManifest::Type::IO_EXPORT;
|
||||
manifest_.vde_version_min = "6.0.0";
|
||||
return true;
|
||||
}
|
||||
|
||||
void shutdown() override {
|
||||
// 清理资源
|
||||
}
|
||||
|
||||
const PluginManifest& manifest() const override {
|
||||
return manifest_;
|
||||
}
|
||||
|
||||
const char* name() const override {
|
||||
return manifest_.name.c_str();
|
||||
}
|
||||
|
||||
const char* version() const override {
|
||||
return manifest_.version.c_str();
|
||||
}
|
||||
|
||||
bool execute(const std::string& action,
|
||||
const std::map<std::string, std::string>& params,
|
||||
void* input, void* output) override {
|
||||
if (action == "export") {
|
||||
// 执行导出逻辑
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private:
|
||||
PluginManifest manifest_;
|
||||
};
|
||||
|
||||
// 必需的导出符号
|
||||
extern "C" VDE_PLUGIN_EXPORT PluginInterface* create_plugin() {
|
||||
return new MyExporter();
|
||||
}
|
||||
|
||||
extern "C" VDE_PLUGIN_EXPORT void destroy_plugin(PluginInterface* plugin) {
|
||||
delete plugin;
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 CMake 构建
|
||||
|
||||
```cmake
|
||||
# CMakeLists.txt for plugin
|
||||
cmake_minimum_required(VERSION 3.16)
|
||||
project(my_exporter VERSION 1.0.0)
|
||||
|
||||
find_package(ViewDesignEngine REQUIRED)
|
||||
|
||||
add_library(my_exporter SHARED my_exporter.cpp)
|
||||
target_link_libraries(my_exporter PRIVATE vde::engine)
|
||||
target_include_directories(my_exporter PRIVATE ${VDE_INCLUDE_DIRS})
|
||||
|
||||
# 设置输出到插件目录
|
||||
set_target_properties(my_exporter PROPERTIES
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/plugins"
|
||||
)
|
||||
```
|
||||
|
||||
### 4.3 插件类型
|
||||
|
||||
| 类型 | 枚举值 | 说明 | 示例 |
|
||||
|------|--------|------|------|
|
||||
| 格式导入器 | `IO_IMPORT` | 新增文件格式导入 | USDZ, 3DS, AMF |
|
||||
| 格式导出器 | `IO_EXPORT` | 新增文件格式导出 | USDZ, FBX, X3D |
|
||||
| 几何过滤器 | `GEOMETRY_FILTER` | 几何后处理 | 平滑、简化、重网格 |
|
||||
| 自定义工具 | `CUSTOM_TOOL` | 领域特定工具 | 应力分析、拓扑优化 |
|
||||
|
||||
## 5. 插件加载流程
|
||||
|
||||
```
|
||||
Application::init()
|
||||
│
|
||||
▼
|
||||
PluginManager::load_plugin_dir("/usr/lib/vde/plugins")
|
||||
│
|
||||
├── 扫描目录: for each *.so / *.dylib / *.dll
|
||||
│
|
||||
├── dlopen(plugin_path, RTLD_NOW)
|
||||
│ │
|
||||
│ ├── 成功 → 继续
|
||||
│ └── 失败 → 记录错误,跳过
|
||||
│
|
||||
├── dlsym(handle, "get_manifest")
|
||||
│ │
|
||||
│ ├── 找到 → 读取 manifest,检查版本兼容性
|
||||
│ └── 未找到 → 继续加载(稍后从 initialize 获取)
|
||||
│
|
||||
├── dlsym(handle, "create_plugin")
|
||||
│ │
|
||||
│ ├── 找到 → PluginInterface* plugin = create_plugin()
|
||||
│ └── 未找到 → dlclose,跳过
|
||||
│
|
||||
├── plugin->initialize()
|
||||
│ │
|
||||
│ ├── 返回 true → 注册到 Registry
|
||||
│ └── 返回 false → destroy_plugin + dlclose
|
||||
│
|
||||
└── 返回加载成功数量
|
||||
```
|
||||
|
||||
### 版本兼容性检查
|
||||
|
||||
```cpp
|
||||
// 伪代码
|
||||
bool is_compatible(const PluginManifest& m, const std::string& vde_version) {
|
||||
// 检查最小版本
|
||||
if (compare_versions(vde_version, m.vde_version_min) < 0)
|
||||
return false;
|
||||
|
||||
// 检查最大版本(如果指定)
|
||||
if (!m.vde_version_max.empty() &&
|
||||
compare_versions(vde_version, m.vde_version_max) > 0)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
```
|
||||
|
||||
## 6. 生命周期管理
|
||||
|
||||
```
|
||||
┌──────────────────────────────────────────────────────────────┐
|
||||
│ 插件生命周期 │
|
||||
│ │
|
||||
│ [编译] → [发现] → [加载] → [初始化] → [运行] → [卸载] │
|
||||
│ │
|
||||
│ 编译: 开发者编写代码,构建为 .so/.dylib/.dll │
|
||||
│ 发现: PluginManager 扫描插件目录 │
|
||||
│ 加载: dlopen 加载动态库 │
|
||||
│ 初始化: initialize() 注册功能 │
|
||||
│ 运行: execute() 被调用 │
|
||||
│ 卸载: shutdown() + dlclose │
|
||||
│ │
|
||||
│ 状态机: │
|
||||
│ UNLOADED → LOADING → INITIALIZED → RUNNING │
|
||||
│ ↑ ↓ ↓ │
|
||||
│ └── ERROR SHUTTING_DOWN → UNLOADED│
|
||||
└──────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 状态说明
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| `UNLOADED` | 插件未加载或已卸载 |
|
||||
| `LOADING` | dlopen 成功,正在初始化 |
|
||||
| `INITIALIZED` | initialize() 完成,等待 execute |
|
||||
| `RUNNING` | execute() 正在执行中 |
|
||||
| `SHUTTING_DOWN` | shutdown() 执行中 |
|
||||
| `ERROR` | 加载或初始化失败 |
|
||||
|
||||
## 7. 清单文件
|
||||
|
||||
插件可以在同目录放置 `plugin.json` 描述文件,加快发现速度:
|
||||
|
||||
```json
|
||||
{
|
||||
"name": "io.export.usdz",
|
||||
"version": "1.0.0",
|
||||
"author": "Your Name <email@example.com>",
|
||||
"description": "Export geometry to USDZ format for Apple AR",
|
||||
"license": "MIT",
|
||||
"type": "IO_EXPORT",
|
||||
"vde_version_min": "6.0.0",
|
||||
"vde_version_max": "",
|
||||
"dependencies": [],
|
||||
"library": "libvde_usdz_export.so",
|
||||
"entry_points": {
|
||||
"create": "create_plugin",
|
||||
"destroy": "destroy_plugin"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### PluginManager 加载优先级
|
||||
|
||||
1. 如果存在 `plugin.json` → 先读取 JSON 验证兼容性
|
||||
2. 兼容 → `dlopen` + `dlsym(create_plugin)`
|
||||
3. 不兼容 → 跳过,记录日志
|
||||
4. 无 `plugin.json` → 直接 `dlopen` + 尝试 `get_manifest` 符号
|
||||
|
||||
## 8. 安全考虑
|
||||
|
||||
### 8.1 隔离性
|
||||
|
||||
| 措施 | 说明 |
|
||||
|------|------|
|
||||
| 独立 .so | 每个插件独立动态库 |
|
||||
| 崩溃隔离 | 插件 SIGSEGV 不传播到主程序(信号处理器) |
|
||||
| 符号可见性 | 插件使用 `-fvisibility=hidden` 隐藏内部符号 |
|
||||
| 内存隔离 | 插件通过 PluginInterface 与主程序交互,不直接访问内部数据 |
|
||||
|
||||
### 8.2 信任模型
|
||||
|
||||
```
|
||||
┌───────────────────────────────────────┐
|
||||
│ 插件信任级别 │
|
||||
│ │
|
||||
│ L0 内置: VDE 官方维护,完全信任 │
|
||||
│ L1 签名: 第三方已签名,受信任 │
|
||||
│ L2 社区: 社区插件,有限沙箱 │
|
||||
│ L3 未知: 未签名/未知来源,严格沙箱 │
|
||||
│ │
|
||||
│ L3 限制: │
|
||||
│ - 不能访问文件系统(除了输出目录) │
|
||||
│ - 不能调用网络 │
|
||||
│ - 不能 fork │
|
||||
│ - CPU/内存限制 │
|
||||
└───────────────────────────────────────┘
|
||||
```
|
||||
|
||||
### 8.3 最佳安全实践
|
||||
|
||||
1. **始终验证 manifest 版本兼容性**后再 initialize
|
||||
2. **dlopen 使用 `RTLD_NOW | RTLD_LOCAL`** 而非 `RTLD_LAZY | RTLD_GLOBAL`
|
||||
3. **设置超时**:execute() 调用应有超时机制
|
||||
4. **资源限制**:通过 cgroups/Docker 限制插件资源
|
||||
5. **日志审计**:记录所有插件加载/卸载/执行事件
|
||||
|
||||
## 9. 最佳实践
|
||||
|
||||
### 9.1 插件开发建议
|
||||
|
||||
- ✅ 插件尽量无状态,每次 execute 独立
|
||||
- ✅ 用 manifest 声明清晰的功能范围
|
||||
- ✅ 支持版本协商(`vde_version_min` / `vde_version_max`)
|
||||
- ✅ 提供详细的错误信息(通过返回值 + 日志)
|
||||
- ✅ 清理所有资源在 shutdown() 中
|
||||
- ❌ 不要在 initialize() 中做耗时操作
|
||||
- ❌ 不要依赖全局可变状态
|
||||
- ❌ 不要修改 VDE 核心数据结构
|
||||
|
||||
### 9.2 插件命名规范
|
||||
|
||||
```
|
||||
格式: <category>.<subcategory>.<name>
|
||||
|
||||
示例:
|
||||
- io.import.fbx # FBX 格式导入
|
||||
- io.export.usdz # USDZ 格式导出
|
||||
- geometry.smooth.laplacian # Laplacian 平滑
|
||||
- tool.analysis.stress # 应力分析工具
|
||||
```
|
||||
|
||||
### 9.3 使用示例
|
||||
|
||||
```cpp
|
||||
#include <vde/plugin/plugin_system.h>
|
||||
|
||||
int main() {
|
||||
vde::plugin::PluginManager mgr;
|
||||
|
||||
// 加载所有插件
|
||||
int count = mgr.load_plugin_dir("/usr/lib/vde/plugins");
|
||||
std::cout << "Loaded " << count << " plugins\n";
|
||||
|
||||
// 列出已加载插件
|
||||
for (auto& name : mgr.list_plugins()) {
|
||||
std::cout << " - " << name << "\n";
|
||||
}
|
||||
|
||||
// 使用特定插件
|
||||
auto* exporter = mgr.get_plugin("io.export.gltf");
|
||||
if (exporter) {
|
||||
std::map<std::string, std::string> params;
|
||||
params["path"] = "output.glb";
|
||||
params["binary"] = "true";
|
||||
|
||||
void* mesh_data = /* ... */;
|
||||
bool ok = exporter->execute("export", params, mesh_data, nullptr);
|
||||
}
|
||||
|
||||
// 卸载
|
||||
mgr.unload_all();
|
||||
return 0;
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 附录: 平台差异
|
||||
|
||||
| 操作 | Linux | macOS | Windows |
|
||||
|------|-------|-------|---------|
|
||||
| 动态库后缀 | `.so` | `.dylib` | `.dll` |
|
||||
| 加载函数 | `dlopen` | `dlopen` | `LoadLibraryA` |
|
||||
| 符号解析 | `dlsym` | `dlsym` | `GetProcAddress` |
|
||||
| 卸载函数 | `dlclose` | `dlclose` | `FreeLibrary` |
|
||||
| 错误信息 | `dlerror()` | `dlerror()` | `GetLastError()` |
|
||||
| 链接库 | `-ldl` | (内置) | `kernel32.lib` |
|
||||
| 可见性宏 | `__attribute__((visibility("default")))` | 同 Linux | `__declspec(dllexport)` |
|
||||
@@ -0,0 +1,361 @@
|
||||
# 测试指南
|
||||
|
||||
ViewDesignEngine 使用 Google Test 框架,通过 CTest 运行测试。
|
||||
|
||||
## 目录
|
||||
|
||||
1. [测试架构](#1-测试架构)
|
||||
2. [运行测试](#2-运行测试)
|
||||
3. [编写测试](#3-编写测试)
|
||||
4. [测试规范](#4-测试规范)
|
||||
5. [Sanitizer 测试](#5-sanitizer-测试)
|
||||
6. [性能基准](#6-性能基准)
|
||||
7. [模糊测试](#7-模糊测试)
|
||||
8. [CI 集成](#8-ci-集成)
|
||||
|
||||
---
|
||||
|
||||
## 1. 测试架构
|
||||
|
||||
```
|
||||
tests/
|
||||
├── CMakeLists.txt # 顶层测试 CMake
|
||||
├── foundation/ # 基础设施测试
|
||||
│ ├── CMakeLists.txt
|
||||
│ └── test_io_obj.cpp
|
||||
├── core/ # 核心模块测试
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── test_polygon.cpp
|
||||
│ ├── test_distance.cpp
|
||||
│ └── test_cam_5axis.cpp
|
||||
├── curves/ # 曲线曲面测试
|
||||
├── mesh/ # 网格处理测试
|
||||
│ ├── CMakeLists.txt
|
||||
│ ├── test_fea_mesh.cpp
|
||||
│ ├── test_reverse_engineering.cpp
|
||||
│ └── test_xxx.cpp
|
||||
├── spatial/ # 空间索引测试
|
||||
├── boolean/ # 布尔运算测试
|
||||
├── collision/ # 碰撞检测测试
|
||||
├── brep/ # B-Rep 测试
|
||||
├── sdf/ # SDF 测试
|
||||
├── sketch/ # 草图约束测试
|
||||
├── gpu/ # GPU 测试
|
||||
└── fuzz/ # 模糊测试
|
||||
```
|
||||
|
||||
### 测试数量
|
||||
|
||||
| 模块 | 测试数 | 状态 |
|
||||
|------|--------|------|
|
||||
| foundation | ~30 | ✅ |
|
||||
| core | ~40 | ✅ |
|
||||
| curves | ~50 | ✅ |
|
||||
| mesh | ~60 | ✅ |
|
||||
| spatial | ~30 | ✅ |
|
||||
| boolean | ~40 | ✅ |
|
||||
| collision | ~30 | ✅ |
|
||||
| brep | ~70 | ✅ |
|
||||
| sdf | 189 | ✅ |
|
||||
| sketch | ~10 | ✅ |
|
||||
| gpu | ~5 | ✅ |
|
||||
| **合计** | **~500+** | ✅ |
|
||||
|
||||
## 2. 运行测试
|
||||
|
||||
### 基础命令
|
||||
|
||||
```bash
|
||||
# 构建并运行所有测试
|
||||
cmake -B build -DBUILD_TESTS=ON
|
||||
cmake --build build -j$(nproc)
|
||||
cd build && ctest --output-on-failure
|
||||
|
||||
# 并行运行
|
||||
ctest -j$(nproc) --output-on-failure
|
||||
|
||||
# 详细输出
|
||||
ctest -V
|
||||
|
||||
# 运行特定测试
|
||||
ctest -R test_brep # 名称匹配
|
||||
ctest -R "test_brep|test_sdf" # 多个模式
|
||||
|
||||
# 排除特定测试
|
||||
ctest -E test_fuzz
|
||||
```
|
||||
|
||||
### 直接运行可执行文件
|
||||
|
||||
```bash
|
||||
# 运行单个测试文件
|
||||
./build/tests/brep/test_brep
|
||||
|
||||
# 运行特定测试用例
|
||||
./build/tests/brep/test_brep --gtest_filter="*Box*"
|
||||
|
||||
# 列出所有测试用例
|
||||
./build/tests/brep/test_brep --gtest_list_tests
|
||||
|
||||
# 重复运行(检测不稳定性)
|
||||
./build/tests/mesh/test_fea_mesh --gtest_repeat=100
|
||||
```
|
||||
|
||||
### Docker 中运行
|
||||
|
||||
```bash
|
||||
docker run --rm --cpus=4 --memory=8g \
|
||||
-v $(pwd):/ws vde-builder bash -c \
|
||||
"cd /ws/build && ctest -j4 --output-on-failure"
|
||||
```
|
||||
|
||||
## 3. 编写测试
|
||||
|
||||
### 3.1 基本模板
|
||||
|
||||
```cpp
|
||||
// tests/mesh/test_my_feature.cpp
|
||||
#include <gtest/gtest.h>
|
||||
#include <vde/mesh/halfedge_mesh.h>
|
||||
#include <vde/core/point.h>
|
||||
|
||||
using namespace vde::core;
|
||||
using namespace vde::mesh;
|
||||
|
||||
// 基本断言
|
||||
TEST(MyFeatureTest, CreateEmptyMesh) {
|
||||
HalfedgeMesh mesh;
|
||||
EXPECT_EQ(mesh.vertex_count(), 0);
|
||||
EXPECT_EQ(mesh.face_count(), 0);
|
||||
}
|
||||
|
||||
// 带 fixture 的测试
|
||||
class MyFeatureFixture : public ::testing::Test {
|
||||
protected:
|
||||
void SetUp() override {
|
||||
mesh.add_vertex(Point3D(0, 0, 0));
|
||||
mesh.add_vertex(Point3D(1, 0, 0));
|
||||
mesh.add_vertex(Point3D(0, 1, 0));
|
||||
mesh.add_face({0, 1, 2});
|
||||
}
|
||||
HalfedgeMesh mesh;
|
||||
};
|
||||
|
||||
TEST_F(MyFeatureFixture, FaceCount) {
|
||||
EXPECT_EQ(mesh.face_count(), 1);
|
||||
}
|
||||
|
||||
TEST_F(MyFeatureFixture, VertexPositions) {
|
||||
EXPECT_NEAR(mesh.vertex(0).x, 0.0, 1e-6);
|
||||
EXPECT_NEAR(mesh.vertex(1).x, 1.0, 1e-6);
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 参数化测试
|
||||
|
||||
```cpp
|
||||
// 使用不同参数重复测试
|
||||
class BooleanOpTest : public ::testing::TestWithParam<
|
||||
std::tuple<std::string, int, int>> {};
|
||||
|
||||
TEST_P(BooleanOpTest, ConsistentResult) {
|
||||
auto [op_name, n1, n2] = GetParam();
|
||||
// ... test logic using parameters ...
|
||||
}
|
||||
|
||||
INSTANTIATE_TEST_SUITE_P(
|
||||
MeshBoolean,
|
||||
BooleanOpTest,
|
||||
::testing::Values(
|
||||
std::make_tuple("union", 100, 50),
|
||||
std::make_tuple("intersection", 200, 100),
|
||||
std::make_tuple("difference", 300, 150)
|
||||
));
|
||||
```
|
||||
|
||||
### 3.3 注册到 CMake
|
||||
|
||||
```cmake
|
||||
# tests/mesh/CMakeLists.txt
|
||||
add_executable(test_my_feature test_my_feature.cpp)
|
||||
target_link_libraries(test_my_feature
|
||||
PRIVATE vde_mesh vde_core
|
||||
PRIVATE GTest::gtest GTest::gtest_main
|
||||
)
|
||||
add_test(NAME test_my_feature COMMAND test_my_feature)
|
||||
```
|
||||
|
||||
## 4. 测试规范
|
||||
|
||||
### 命名规范
|
||||
|
||||
```
|
||||
测试文件名: test_<feature>.cpp
|
||||
测试套件名: <Feature>Test 或 <Module>Test
|
||||
测试用例名: <Action><Condition> 或 <MethodName><Scenario>
|
||||
|
||||
示例:
|
||||
- TEST(BrepValidateTest, ClosedShellPassesValidation)
|
||||
- TEST(MeshSimplifyTest, SimplifyingCubeReducesFaceCount)
|
||||
```
|
||||
|
||||
### 断言选择
|
||||
|
||||
| 场景 | 推荐断言 |
|
||||
|------|---------|
|
||||
| 相等比较 | `EXPECT_EQ(a, b)` |
|
||||
| 浮点比较 | `EXPECT_NEAR(a, b, tolerance)` |
|
||||
| 布尔检查 | `EXPECT_TRUE(condition)` |
|
||||
| 非致命错误 | `EXPECT_*` 继续执行 |
|
||||
| 致命错误 | `ASSERT_*` 立即终止 |
|
||||
| 异常检查 | `EXPECT_THROW(expr, exception_type)` |
|
||||
|
||||
### 测试清单
|
||||
|
||||
每个功能模块的测试应覆盖:
|
||||
|
||||
- [ ] **正常路径** (Happy Path)
|
||||
- [ ] **边界条件** (空输入、极值、零值)
|
||||
- [ ] **错误处理** (无效输入、超范围)
|
||||
- [ ] **退化情况** (共线/共面点、零面积面)
|
||||
- [ ] **数值稳定性** (接近容差的场景)
|
||||
- [ ] **性能回归** (大规模输入不超时)
|
||||
|
||||
### 反模式
|
||||
|
||||
```cpp
|
||||
// ❌ 测试依赖全局状态
|
||||
static int counter = 0;
|
||||
TEST(Foo, Bar) { EXPECT_EQ(counter++, 0); } // 不可重复
|
||||
|
||||
// ❌ 测试依赖执行顺序
|
||||
TEST(Foo, A) { /* 设置全局状态 */ }
|
||||
TEST(Foo, B) { /* 依赖 A 的状态 */ }
|
||||
|
||||
// ❌ 过于宽松的容差
|
||||
EXPECT_NEAR(result, expected, 100.0); // 容差过大
|
||||
|
||||
// ❌ 没有断言(不验证任何东西)
|
||||
TEST(Foo, Bar) {
|
||||
auto x = compute();
|
||||
// 没有 EXPECT/ASSERT
|
||||
}
|
||||
```
|
||||
|
||||
## 5. Sanitizer 测试
|
||||
|
||||
### Address Sanitizer (ASan)
|
||||
|
||||
```bash
|
||||
# 构建 ASan 版本
|
||||
cmake -B build_asan \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DENABLE_SANITIZERS=ON \
|
||||
-DVDE_USE_OPENMP=OFF
|
||||
|
||||
cmake --build build_asan -j$(nproc)
|
||||
|
||||
# 运行测试
|
||||
cd build_asan
|
||||
ASAN_OPTIONS=detect_leaks=1:abort_on_error=1 \
|
||||
ctest --output-on-failure -j4
|
||||
```
|
||||
|
||||
### Undefined Behavior Sanitizer (UBSan)
|
||||
|
||||
```bash
|
||||
# 手动添加 UBSan 标志
|
||||
cmake -B build_ubsan \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_CXX_FLAGS="-fsanitize=undefined"
|
||||
|
||||
cmake --build build_ubsan -j$(nproc)
|
||||
cd build_ubsan && ctest --output-on-failure
|
||||
```
|
||||
|
||||
### Thread Sanitizer (TSan)
|
||||
|
||||
```bash
|
||||
cmake -B build_tsan \
|
||||
-DCMAKE_BUILD_TYPE=Debug \
|
||||
-DCMAKE_CXX_FLAGS="-fsanitize=thread" \
|
||||
-DVDE_USE_OPENMP=OFF
|
||||
|
||||
cmake --build build_tsan -j$(nproc)
|
||||
cd build_tsan && ctest --output-on-failure
|
||||
```
|
||||
|
||||
## 6. 性能基准
|
||||
|
||||
### 运行基准测试
|
||||
|
||||
```bash
|
||||
# 构建基准测试
|
||||
cmake -B build_bench -DBUILD_BENCHMARKS=ON -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build_bench -j$(nproc)
|
||||
|
||||
# 运行所有基准
|
||||
cd build_bench && ctest -R bench_
|
||||
|
||||
# 直接运行并查看详细报告
|
||||
./build_bench/bench/bench_bvh --benchmark_format=json
|
||||
```
|
||||
|
||||
### 基准模块
|
||||
|
||||
| 基准 | 内容 |
|
||||
|------|------|
|
||||
| `bench_bvh` | SAH 构建 (N=1K/10K/100K) + 射线查询 |
|
||||
| `bench_delaunay` | 2D Bowyer-Watson (N=100/1K/10K) |
|
||||
| `bench_boolean` | 3D 网格布尔 (N=100/500) |
|
||||
| `bench_curves` | Bezier/BSpline evaluate 吞吐量 |
|
||||
| `bench_spatial` | R-Tree/KD-Tree 构建 + kNN |
|
||||
|
||||
## 7. 模糊测试
|
||||
|
||||
```bash
|
||||
# 构建并运行模糊测试
|
||||
cmake -B build -DBUILD_TESTS=ON
|
||||
cmake --build build -j$(nproc)
|
||||
|
||||
# 运行模糊测试
|
||||
./build/tests/fuzz/test_fuzz_sdf
|
||||
./build/tests/fuzz/test_fuzz_boolean
|
||||
./build/tests/fuzz/test_fuzz_format
|
||||
```
|
||||
|
||||
模糊测试覆盖的模块:
|
||||
- **SDF**: 随机 CSG 树组合,检测 NaN/崩溃
|
||||
- **Boolean**: 随机网格布尔运算,检测拓扑错误
|
||||
- **Format**: 随机几何 → 导出 → 导入 → 验证一致性
|
||||
|
||||
## 8. CI 集成
|
||||
|
||||
VDE 使用 Gitea CI 自动运行测试。
|
||||
|
||||
### CI 配置文件
|
||||
|
||||
`.gitea/workflows/build.yml`:
|
||||
```yaml
|
||||
name: Build & Test
|
||||
on: [push, pull_request]
|
||||
jobs:
|
||||
build-and-test:
|
||||
runs-on: ubuntu-latest
|
||||
container: vde-builder:latest
|
||||
steps:
|
||||
- name: Build
|
||||
run: |
|
||||
cmake -B build_ci -DCMAKE_BUILD_TYPE=Release
|
||||
cmake --build build_ci -j2
|
||||
- name: Test
|
||||
run: |
|
||||
cd build_ci && ctest --output-on-failure -j2
|
||||
```
|
||||
|
||||
### CI 检查项
|
||||
|
||||
- [ ] 编译通过 (零错误零警告)
|
||||
- [ ] 所有测试通过 (ctest 返回 0)
|
||||
- [ ] ASan 检查无内存错误
|
||||
- [ ] 无新增编译警告
|
||||
Reference in New Issue
Block a user