5e2812a6f3
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)
725 lines
24 KiB
C
725 lines
24 KiB
C
#pragma once
|
||
/**
|
||
* @file vde_capi.h
|
||
* @brief ViewDesignEngine C API — 跨语言边界接口
|
||
*
|
||
* 提供稳定的 C ABI 接口,使 Python、Rust、C# 等语言可以通过 FFI 调用
|
||
* ViewDesignEngine 的核心功能,无需依赖 C++ ABI。
|
||
*
|
||
* ## 设计原则
|
||
*
|
||
* 1. **不透明句柄**: 所有内部对象(网格、曲线、求解器等)通过 `typedef` 前向声明
|
||
* 隐藏为不透明指针类型,外部代码只能通过 API 函数操作
|
||
* 2. **C 兼容类型**: 仅使用 C 原生类型(int, double, const char*)作为参数和返回值
|
||
* 3. **输出通过指针**: 复数返回值(如顶点坐标、包围盒)通过输出参数传递,避免结构体 ABI 问题
|
||
* 4. **显式生命周期管理**: 每个 create/load 函数都有对应的 free/destroy 函数
|
||
*
|
||
* ## 句柄类型
|
||
*
|
||
* | C 类型 | 内部类型 | 创建方式 | 释放方式 |
|
||
* |------------------|--------------------|-----------------------------|-------------------|
|
||
* | VdeHandle | VdeContext | vde_create() | vde_destroy() |
|
||
* | VdeMeshHandle | HalfedgeMesh | vde_load_mesh(), 工厂函数 | vde_mesh_free() |
|
||
* | VdeCurveHandle | NurbsCurve | vde_curve_create_bezier() | vde_curve_free() |
|
||
* | VdeSolverHandle | ConstraintSolver | vde_solver_create() | vde_solver_free() |
|
||
* | VdeBodyHandle | BrepModel | vde_body_create_*() | vde_body_free() |
|
||
*
|
||
* ## 布尔操作编码
|
||
*
|
||
* | 操作 | 整数值 |
|
||
* |------|--------|
|
||
* | 并集 | 0 |
|
||
* | 交集 | 1 |
|
||
* | 差集 | 2 |
|
||
*
|
||
* ## 线程安全性
|
||
*
|
||
* - 每个 VdeHandle 是独立的上下文,不同句柄之间线程安全
|
||
* - 同一句柄上的操作不是线程安全的(调用方负责同步)
|
||
*
|
||
* @ingroup capi
|
||
* @see vde.h C++ 等价接口
|
||
*/
|
||
|
||
#include <stddef.h>
|
||
#include <stdint.h>
|
||
|
||
#ifdef __cplusplus
|
||
extern "C" {
|
||
#endif
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 不透明句柄类型(在 vde.h 中已有前向声明)
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/** @brief 引擎上下文句柄 — 管理错误状态和内部资源 */
|
||
#ifndef VDE_HANDLE_DEFINED
|
||
typedef struct VdeContext* VdeHandle;
|
||
#endif
|
||
|
||
/** @brief 三角网格句柄 — 顶点+面集合 */
|
||
#ifndef VDE_MESH_HANDLE_DEFINED
|
||
typedef struct VdeMesh* VdeMeshHandle;
|
||
#endif
|
||
|
||
/** @brief 参数曲线句柄 — NURBS 曲线 */
|
||
#ifndef VDE_CURVE_HANDLE_DEFINED
|
||
typedef struct VdeCurve* VdeCurveHandle;
|
||
#endif
|
||
|
||
/** @brief 约束求解器句柄 — 二维草图约束 */
|
||
#ifndef VDE_SOLVER_HANDLE_DEFINED
|
||
typedef struct VdeSolver* VdeSolverHandle;
|
||
#endif
|
||
|
||
/** @brief B-Rep 实体句柄 — 边界表示模型 */
|
||
#ifndef VDE_BODY_HANDLE_DEFINED
|
||
typedef struct VdeBody* VdeBodyHandle;
|
||
#endif
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 引擎生命周期
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 创建 ViewDesignEngine 上下文
|
||
*
|
||
* 初始化一个独立的引擎实例。几乎所有后续操作都需要传入此句柄。
|
||
*
|
||
* @return 新的引擎句柄,不需要时通过 vde_destroy() 释放
|
||
*
|
||
* @code{.py}
|
||
* // Python ctypes 示例
|
||
* ctx = lib.vde_create()
|
||
* @endcode
|
||
*
|
||
* @see vde_destroy 释放上下文
|
||
*/
|
||
VdeHandle vde_create(void);
|
||
|
||
/**
|
||
* @brief 销毁引擎上下文
|
||
*
|
||
* 释放上下文及其内部资源。销毁后不能再使用该句柄。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
*
|
||
* @see vde_create
|
||
*/
|
||
void vde_destroy(VdeHandle ctx);
|
||
|
||
/**
|
||
* @brief 获取引擎版本字符串
|
||
*
|
||
* @return 语义版本号字符串(如 "0.5.0"),静态生命周期,无需释放
|
||
*
|
||
* @code{.c}
|
||
* printf("VDE version: %s\n", vde_version());
|
||
* @endcode
|
||
*/
|
||
const char* vde_version(void);
|
||
|
||
/**
|
||
* @brief 获取最后一次操作的错误描述
|
||
*
|
||
* 当某操作失败(如加载不存在的文件)时,可通过此函数获取详情。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @return 错误描述字符串(上下文的内部缓冲区,静态生命周期)
|
||
*
|
||
* @note 每次新的失败操作会覆盖此描述。成功操作不会清除它。
|
||
*/
|
||
const char* vde_last_error(VdeHandle ctx);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 网格 I/O
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 从文件加载三角网格
|
||
*
|
||
* 支持 OBJ (.obj), STL (.stl), PLY (.ply) 三种格式。
|
||
* 格式通过文件扩展名自动检测。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param path 文件路径(UTF-8 编码)
|
||
* @return 网格句柄,失败时返回 NULL(通过 vde_last_error() 获取原因)
|
||
*
|
||
* @code{.c}
|
||
* VdeMeshHandle mesh = vde_load_mesh(ctx, "model.obj");
|
||
* if (!mesh) {
|
||
* fprintf(stderr, "Load failed: %s\n", vde_last_error(ctx));
|
||
* return;
|
||
* }
|
||
* @endcode
|
||
*
|
||
* @see vde_mesh_free 释放网格
|
||
* @see vde_save_mesh 保存网格
|
||
*/
|
||
VdeMeshHandle vde_load_mesh(VdeHandle ctx, const char* path);
|
||
|
||
/**
|
||
* @brief 将三角网格保存为文件
|
||
*
|
||
* 当前支持 OBJ 格式输出。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param mesh 网格句柄
|
||
* @param path 输出文件路径
|
||
* @param format 输出格式(当前仅 "obj" 有效)
|
||
* @return 成功返回 1,失败返回 0
|
||
*
|
||
* @see vde_load_mesh 加载网格
|
||
*/
|
||
int vde_save_mesh(VdeHandle ctx, VdeMeshHandle mesh, const char* path, const char* format);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 网格查询
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 获取网格的顶点数量
|
||
*
|
||
* @param mesh 网格句柄(必须有效且非 NULL)
|
||
* @return 顶点数
|
||
*
|
||
* @see vde_mesh_num_faces 面数
|
||
*/
|
||
size_t vde_mesh_num_vertices(VdeMeshHandle mesh);
|
||
|
||
/**
|
||
* @brief 获取网格的三角面数量
|
||
*
|
||
* @param mesh 网格句柄
|
||
* @return 面数
|
||
*
|
||
* @see vde_mesh_num_vertices 顶点数
|
||
*/
|
||
size_t vde_mesh_num_faces(VdeMeshHandle mesh);
|
||
|
||
/**
|
||
* @brief 获取指定索引的顶点坐标
|
||
*
|
||
* 顶点索引从 0 开始,到 num_vertices - 1。
|
||
*
|
||
* @param mesh 网格句柄
|
||
* @param idx 顶点索引 [0, num_vertices)
|
||
* @param out_x [out] 顶点 X 坐标
|
||
* @param out_y [out] 顶点 Y 坐标
|
||
* @param out_z [out] 顶点 Z 坐标
|
||
*
|
||
* @pre idx < vde_mesh_num_vertices(mesh)
|
||
*/
|
||
void vde_mesh_get_vertex(VdeMeshHandle mesh, size_t idx,
|
||
double* out_x, double* out_y, double* out_z);
|
||
|
||
/**
|
||
* @brief 获取网格的轴对齐包围盒
|
||
*
|
||
* @param mesh 网格句柄
|
||
* @param out_min_x [out] 最小 X 坐标
|
||
* @param out_min_y [out] 最小 Y 坐标
|
||
* @param out_min_z [out] 最小 Z 坐标
|
||
* @param out_max_x [out] 最大 X 坐标
|
||
* @param out_max_y [out] 最大 Y 坐标
|
||
* @param out_max_z [out] 最大 Z 坐标
|
||
*/
|
||
void vde_mesh_get_bounds(VdeMeshHandle mesh,
|
||
double* out_min_x, double* out_min_y, double* out_min_z,
|
||
double* out_max_x, double* out_max_y, double* out_max_z);
|
||
|
||
/**
|
||
* @brief 释放网格句柄及其资源
|
||
*
|
||
* 释放后将不能再使用该句柄。
|
||
*
|
||
* @param mesh 网格句柄
|
||
*/
|
||
void vde_mesh_free(VdeMeshHandle mesh);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 网格处理
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 网格简化
|
||
*
|
||
* 通过 edge-collapse 或类似算法减少三角形数量,
|
||
* 同时尽可能保留几何特征。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param mesh 输入网格句柄(不修改输入)
|
||
* @param target_ratio 目标简化比率 [0, 1](0 = 不变,1 = 最大简化)
|
||
* @return 简化后的新网格句柄
|
||
*
|
||
* @code{.c}
|
||
* VdeMeshHandle simple = vde_mesh_simplify(ctx, mesh, 0.5); // 减少 50%
|
||
* @endcode
|
||
*
|
||
* @see vde_mesh_smooth 网格平滑
|
||
*/
|
||
VdeMeshHandle vde_mesh_simplify(VdeHandle ctx, VdeMeshHandle mesh, double target_ratio);
|
||
|
||
/**
|
||
* @brief 网格平滑(Laplacian 或 Taubin 平滑)
|
||
*
|
||
* 通过迭代平滑顶点位置改善网格质量,减少噪声。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param mesh 输入网格句柄
|
||
* @param iterations 平滑迭代次数
|
||
* @return 平滑后的新网格句柄
|
||
*
|
||
* @see vde_mesh_simplify 网格简化
|
||
*/
|
||
VdeMeshHandle vde_mesh_smooth(VdeHandle ctx, VdeMeshHandle mesh, int iterations);
|
||
|
||
/**
|
||
* @brief 网格布尔运算
|
||
*
|
||
* 对两个三角网格执行布尔操作。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param a 网格 A
|
||
* @param b 网格 B
|
||
* @param operation 布尔操作类型: 0 = 并集, 1 = 交集, 2 = 差集 (A \ B)
|
||
* @return 布尔结果的新网格句柄
|
||
*
|
||
* @warning 两个输入网格必须是水密的(closed manifold),否则结果不可预测。
|
||
*
|
||
* @code{.c}
|
||
* VdeMeshHandle result = vde_mesh_boolean(ctx, box, sphere, 0); // 并集
|
||
* @endcode
|
||
*/
|
||
VdeMeshHandle vde_mesh_boolean(VdeHandle ctx, VdeMeshHandle a, VdeMeshHandle b, int operation);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 曲线
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 创建 Bézier 曲线
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param control_points 控制点数组,每 3 个 double 表示一个三维点 (x,y,z)
|
||
* @param num_points 控制点数量(次数 = num_points - 1)
|
||
* @param dim 维度(固定为 3)
|
||
* @return 曲线句柄
|
||
*
|
||
* @code{.c}
|
||
* double cp[] = {0,0,0, 1,2,0, 3,0,0}; // 3 控制点,2 次 Bézier
|
||
* VdeCurveHandle curve = vde_curve_create_bezier(ctx, cp, 3, 3);
|
||
* @endcode
|
||
*
|
||
* @see vde_curve_evaluate 求值
|
||
* @see vde_curve_free 释放
|
||
*/
|
||
VdeCurveHandle vde_curve_create_bezier(VdeHandle ctx, const double* control_points,
|
||
int num_points, int dim);
|
||
|
||
/**
|
||
* @brief 在参数 t 处求值曲线
|
||
*
|
||
* @param curve 曲线句柄
|
||
* @param t 参数值 [0, 1]
|
||
* @param out_x [out] 曲线上点的 X 坐标
|
||
* @param out_y [out] 曲线上点的 Y 坐标
|
||
* @param out_z [out] 曲线上点的 Z 坐标
|
||
*
|
||
* @pre 0 ≤ t ≤ 1
|
||
*/
|
||
void vde_curve_evaluate(VdeCurveHandle curve, double t,
|
||
double* out_x, double* out_y, double* out_z);
|
||
|
||
/**
|
||
* @brief 获取曲线的次数
|
||
*
|
||
* 对于 Bézier 曲线,次数 = 控制点数 - 1。
|
||
*
|
||
* @param curve 曲线句柄
|
||
* @return 曲线次数
|
||
*/
|
||
int vde_curve_degree(VdeCurveHandle curve);
|
||
|
||
/**
|
||
* @brief 释放曲线句柄
|
||
*
|
||
* @param curve 曲线句柄
|
||
*/
|
||
void vde_curve_free(VdeCurveHandle curve);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 碰撞检测
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 两球体碰撞检测(GJK 算法)
|
||
*
|
||
* 用于验证和测试 GJK 碰撞检测算法的轻量级接口。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param cx1, cy1, cz1 第一个球体的球心坐标
|
||
* @param r1 第一个球体的半径
|
||
* @param cx2, cy2, cz2 第二个球体的球心坐标
|
||
* @param r2 第二个球体的半径
|
||
* @return 碰撞返回 1,不碰撞返回 0
|
||
*
|
||
* @code{.c}
|
||
* int hit = vde_collision_gjk_spheres(ctx, 0,0,0, 1.0, 1.5,0,0, 0.5);
|
||
* @endcode
|
||
*
|
||
* @see vde_collision_ray_mesh 射线-网格相交
|
||
*/
|
||
int vde_collision_gjk_spheres(VdeHandle ctx,
|
||
double cx1, double cy1, double cz1, double r1,
|
||
double cx2, double cy2, double cz2, double r2);
|
||
|
||
/**
|
||
* @brief 射线与网格的最近交点查询
|
||
*
|
||
* 使用 BVH 加速结构加速查询。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param mesh 目标网格句柄
|
||
* @param ox, oy, oz 射线起点
|
||
* @param dx, dy, dz 射线方向(无需归一化)
|
||
* @param out_t [out] 交点参数 t(沿射线的距离)
|
||
* @param out_x, out_y, out_z [out] 交点坐标
|
||
* @return 命中返回 1,未命中返回 0
|
||
*
|
||
* @code{.c}
|
||
* double t, hx, hy, hz;
|
||
* int hit = vde_collision_ray_mesh(ctx, mesh,
|
||
* 0,0,-10, // 射线起点
|
||
* 0,0,1, // 射线方向 (沿 Z 轴正方向)
|
||
* &t, &hx, &hy, &hz);
|
||
* if (hit) printf("Hit at (%f,%f,%f), t=%f\n", hx, hy, hz, t);
|
||
* @endcode
|
||
*
|
||
* @see vde_collision_gjk_spheres GJK 球体碰撞
|
||
*/
|
||
int vde_collision_ray_mesh(VdeHandle ctx, VdeMeshHandle mesh,
|
||
double ox, double oy, double oz,
|
||
double dx, double dy, double dz,
|
||
double* out_t, double* out_x, double* out_y, double* out_z);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 约束求解器(二维草图)
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 创建二维约束求解器
|
||
*
|
||
* 用于求解草图几何约束(距离、水平、垂直等)。
|
||
*
|
||
* @return 求解器句柄
|
||
*
|
||
* @see vde_solver_free 释放
|
||
*/
|
||
VdeSolverHandle vde_solver_create(void);
|
||
|
||
/**
|
||
* @brief 向求解器添加点
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param x 初始 X 坐标
|
||
* @param y 初始 Y 坐标
|
||
* @param fixed 固定点标记(1 = 固定不移动)
|
||
* @return 点的 ID(用于后续约束引用)
|
||
*
|
||
* @see vde_solver_add_line 添加线段
|
||
*/
|
||
int vde_solver_add_point(VdeSolverHandle solver, double x, double y, int fixed);
|
||
|
||
/**
|
||
* @brief 向求解器添加线段(由两个点定义)
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param p0 起点 ID
|
||
* @param p1 终点 ID
|
||
* @return 线段的 ID
|
||
*
|
||
* @see vde_solver_add_point 添加点
|
||
* @see vde_solver_add_horizontal 添加水平约束
|
||
* @see vde_solver_add_vertical 添加垂直约束
|
||
*/
|
||
int vde_solver_add_line(VdeSolverHandle solver, int p0, int p1);
|
||
|
||
/**
|
||
* @brief 添加距离约束(两点之间)
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param p0 第一个点的 ID
|
||
* @param p1 第二个点的 ID
|
||
* @param d 目标距离(必须 > 0)
|
||
*
|
||
* @see vde_solver_add_horizontal 水平约束
|
||
*/
|
||
void vde_solver_add_distance_constraint(VdeSolverHandle solver, int p0, int p1, double d);
|
||
|
||
/**
|
||
* @brief 添加水平约束(线段水平)
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param line_id 线段 ID
|
||
*
|
||
* @see vde_solver_add_vertical 垂直约束
|
||
* @see vde_solver_add_line 添加线段
|
||
*/
|
||
void vde_solver_add_horizontal(VdeSolverHandle solver, int line_id);
|
||
|
||
/**
|
||
* @brief 添加垂直约束(线段垂直)
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param line_id 线段 ID
|
||
*
|
||
* @see vde_solver_add_horizontal 水平约束
|
||
*/
|
||
void vde_solver_add_vertical(VdeSolverHandle solver, int line_id);
|
||
|
||
/**
|
||
* @brief 求解约束系统
|
||
*
|
||
* 通过迭代优化使所有点的位置满足所有约束。
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param max_iter 最大迭代次数
|
||
* @param tol 收敛容差
|
||
* @return 收敛返回 1,未收敛返回 0
|
||
*
|
||
* @code{.c}
|
||
* int converged = vde_solver_solve(solver, 100, 1e-6);
|
||
* @endcode
|
||
*
|
||
* @see vde_solver_get_point 获取求解后的点坐标
|
||
*/
|
||
int vde_solver_solve(VdeSolverHandle solver, int max_iter, double tol);
|
||
|
||
/**
|
||
* @brief 获取求解后的点坐标
|
||
*
|
||
* @param solver 求解器句柄
|
||
* @param idx 点 ID
|
||
* @param out_x [out] 求解后 X 坐标
|
||
* @param out_y [out] 求解后 Y 坐标
|
||
*
|
||
* @pre 必须先调用 vde_solver_solve()
|
||
*/
|
||
void vde_solver_get_point(VdeSolverHandle solver, int idx, double* out_x, double* out_y);
|
||
|
||
/**
|
||
* @brief 释放求解器句柄
|
||
*
|
||
* @param solver 求解器句柄
|
||
*/
|
||
void vde_solver_free(VdeSolverHandle solver);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// B-Rep 建模
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 创建实心立方体 B-Rep
|
||
*
|
||
* 以原点为中心的轴对齐立方体。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param w 宽度(X 方向),> 0
|
||
* @param h 高度(Y 方向),> 0
|
||
* @param d 深度(Z 方向),> 0
|
||
* @return B-Rep 实体句柄
|
||
*
|
||
* @see vde_body_create_cylinder 圆柱体
|
||
* @see vde_body_create_sphere 球体
|
||
*/
|
||
VdeBodyHandle vde_body_create_box(VdeHandle ctx, double w, double h, double d);
|
||
|
||
/**
|
||
* @brief 创建实心圆柱体 B-Rep
|
||
*
|
||
* 沿 Y 轴、以原点为中心的圆柱体。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param r 截面半径,> 0
|
||
* @param h 总高度(从 -h/2 到 +h/2)
|
||
* @param segs 截面分段数(边数)
|
||
* @return B-Rep 实体句柄
|
||
*
|
||
* @see vde_body_create_box 立方体
|
||
*/
|
||
VdeBodyHandle vde_body_create_cylinder(VdeHandle ctx, double r, double h, int segs);
|
||
|
||
/**
|
||
* @brief 创建球体 B-Rep
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param r 球半径,> 0
|
||
* @param su 经度方向分段数
|
||
* @param sv 纬度方向分段数
|
||
* @return B-Rep 实体句柄
|
||
*/
|
||
VdeBodyHandle vde_body_create_sphere(VdeHandle ctx, double r, int su, int sv);
|
||
|
||
/**
|
||
* @brief 将 B-Rep 实体转换为三角网格
|
||
*
|
||
* 以指定的弦高误差对曲面进行 tessellation。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param body B-Rep 实体句柄
|
||
* @param deflection 弦高误差(越小 = 越精细,推荐 0.01)
|
||
* @return 三角网格句柄
|
||
*
|
||
* @code{.c}
|
||
* VdeBodyHandle body = vde_body_create_box(ctx, 10, 5, 3);
|
||
* VdeMeshHandle mesh = vde_body_to_mesh(ctx, body, 0.01);
|
||
* vde_save_mesh(ctx, mesh, "box.obj", "obj");
|
||
* @endcode
|
||
*
|
||
* @see vde_body_free 释放 B-Rep 实体
|
||
*/
|
||
VdeMeshHandle vde_body_to_mesh(VdeHandle ctx, VdeBodyHandle body, double deflection);
|
||
|
||
/**
|
||
* @brief 释放 B-Rep 实体句柄
|
||
*
|
||
* @param body B-Rep 实体句柄
|
||
*/
|
||
void vde_body_free(VdeBodyHandle body);
|
||
|
||
/** @brief 深拷贝 B-Rep 实体 */
|
||
VdeBodyHandle vde_body_clone(VdeHandle ctx, VdeBodyHandle body);
|
||
|
||
// ── B-Rep STEP/IGES I/O ──
|
||
|
||
/** @brief 从 STEP 文件导入 B-Rep 实体列表。返回数量,每个 body 写入 out_bodies */
|
||
int vde_body_load_step(VdeHandle ctx, const char* path, VdeBodyHandle** out_bodies);
|
||
|
||
/** @brief 从 IGES 文件导入 B-Rep 实体列表 */
|
||
int vde_body_load_iges(VdeHandle ctx, const char* path, VdeBodyHandle** out_bodies);
|
||
|
||
/** @brief 将 B-Rep 实体列表导出为 STEP 文件。成功返回 1 */
|
||
int vde_body_save_step(VdeHandle ctx, VdeBodyHandle* bodies, int count, const char* path);
|
||
|
||
/** @brief 将 B-Rep 实体列表导出为 IGES 文件 */
|
||
int vde_body_save_iges(VdeHandle ctx, VdeBodyHandle* bodies, int count, const char* path);
|
||
|
||
// ── B-Rep Boolean ──
|
||
|
||
/** @brief B-Rep 布尔运算。op: 0=Union, 1=Intersection, 2=Difference (A\B) */
|
||
VdeBodyHandle vde_body_boolean(VdeHandle ctx, VdeBodyHandle a, VdeBodyHandle b, int op);
|
||
|
||
// ── Mesh face data access ──
|
||
|
||
/** @brief 获取网格面的顶点索引。返回顶点数,out_indices 需调用 vde_free_buffer 释放 */
|
||
int vde_mesh_get_face(VdeMeshHandle mesh, size_t face_idx, int** out_indices);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// SDF 建模
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/** @brief SDF 节点句柄(不透明) */
|
||
#ifndef VDE_SDF_HANDLE_DEFINED
|
||
typedef struct VdeSdfNode* VdeSdfHandle;
|
||
#endif
|
||
|
||
/** @brief 创建 SDF 球体节点 */
|
||
VdeSdfHandle vde_sdf_sphere(VdeHandle ctx, double radius);
|
||
|
||
/** @brief 创建 SDF 盒子节点 */
|
||
VdeSdfHandle vde_sdf_box(VdeHandle ctx, double hx, double hy, double hz);
|
||
|
||
/** @brief 创建 SDF 圆柱节点 */
|
||
VdeSdfHandle vde_sdf_cylinder(VdeHandle ctx, double radius, double height);
|
||
|
||
/** @brief SDF 布尔并集 */
|
||
VdeSdfHandle vde_sdf_union(VdeHandle ctx, VdeSdfHandle a, VdeSdfHandle b);
|
||
|
||
/** @brief SDF 布尔交集 */
|
||
VdeSdfHandle vde_sdf_intersection(VdeHandle ctx, VdeSdfHandle a, VdeSdfHandle b);
|
||
|
||
/** @brief SDF 布尔差集 */
|
||
VdeSdfHandle vde_sdf_difference(VdeHandle ctx, VdeSdfHandle a, VdeSdfHandle b);
|
||
|
||
/** @brief SDF 转网格 */
|
||
VdeMeshHandle vde_sdf_to_mesh(VdeHandle ctx, VdeSdfHandle sdf, int resolution);
|
||
|
||
/** @brief 释放 SDF 节点 */
|
||
void vde_sdf_free(VdeSdfHandle sdf);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 装配体
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/** @brief 装配体句柄 */
|
||
#ifndef VDE_ASSEMBLY_HANDLE_DEFINED
|
||
typedef struct VdeAssembly* VdeAssemblyHandle;
|
||
#endif
|
||
|
||
/** @brief 创建装配体 */
|
||
VdeAssemblyHandle vde_assembly_create(VdeHandle ctx, const char* name);
|
||
|
||
/** @brief 向装配体根节点添加零件 */
|
||
int vde_assembly_add_part(VdeAssemblyHandle assembly, const char* name, VdeBodyHandle body);
|
||
|
||
/** @brief 获取装配体零件数量 */
|
||
int vde_assembly_part_count(VdeAssemblyHandle assembly);
|
||
|
||
/** @brief 释放装配体(不释放其中的 body,调用方自行管理) */
|
||
void vde_assembly_free(VdeAssemblyHandle assembly);
|
||
|
||
/** @brief 释放 body 句柄数组(由 load_step/load_iges 返回) */
|
||
void vde_body_free_array(VdeBodyHandle* bodies, int count);
|
||
|
||
// ═══════════════════════════════════════════════════════════
|
||
// 序列化
|
||
// ═══════════════════════════════════════════════════════════
|
||
|
||
/**
|
||
* @brief 将网格序列化为二进制字节流
|
||
*
|
||
* 返回的缓冲区需要在消费后通过 vde_free_buffer() 释放。
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param mesh 网格句柄
|
||
* @param out_data [out] 指向序列化字节数组的指针
|
||
* @return 字节数
|
||
*
|
||
* @note 输出的缓冲区由库管理,调用方不得直接 free/delete。
|
||
*
|
||
* @code{.c}
|
||
* uint8_t* data = NULL;
|
||
* size_t len = vde_serialize_mesh(ctx, mesh, &data);
|
||
* // ... 使用/存储 data ...
|
||
* vde_free_buffer(data);
|
||
* @endcode
|
||
*
|
||
* @see vde_deserialize_mesh 反序列化
|
||
* @see vde_free_buffer 释放序列化缓冲区
|
||
*/
|
||
size_t vde_serialize_mesh(VdeHandle ctx, VdeMeshHandle mesh, uint8_t** out_data);
|
||
|
||
/**
|
||
* @brief 从二进制字节流反序列化为网格
|
||
*
|
||
* @param ctx 引擎上下文句柄
|
||
* @param data 序列化数据缓冲区
|
||
* @param len 数据长度(字节数)
|
||
* @return 反序列化后的网格句柄
|
||
*
|
||
* @see vde_serialize_mesh 序列化
|
||
*/
|
||
VdeMeshHandle vde_deserialize_mesh(VdeHandle ctx, const uint8_t* data, size_t len);
|
||
|
||
/**
|
||
* @brief 释放由 vde_serialize_mesh 分配的缓冲区
|
||
*
|
||
* @param ptr 由 vde_serialize_mesh 返回的缓冲区指针
|
||
*/
|
||
void vde_free_buffer(uint8_t* ptr);
|
||
|
||
#ifdef __cplusplus
|
||
}
|
||
#endif
|