/** * @file basic_usage.cpp * @brief ViewDesignEngine C API 基础使用示例 * * 演示通过纯 C 接口使用 VDE 引擎的主要功能: * - 引擎生命周期管理 * - Mesh 加载体素 → 查询 → 保存 * - 网格简化与平滑 * - 碰撞检测(GJK + 射线-网格) * - Bézier 曲线创建与求值 * - B-Rep 实体创建 → 布尔运算 → 转网格 * - SDF 隐式曲面 → 转网格 * - 序列化与反序列化 * * 编译: g++ -std=c++17 -I../include basic_usage.cpp -L../build -lvde -o basic_usage */ #include #include #include /* C API 头文件(在 C++ 中以 extern "C" 方式暴露) */ #include "vde/capi/vde_capi.h" /* ── 辅助宏 ─────────────────────────────────────────────── */ #define CHECK(cond, msg) do { \ if (!(cond)) { \ fprintf(stderr, "[FAIL] %s\n", msg); \ return 1; \ } \ } while(0) /* ── 示例 1: 引擎生命周期 ──────────────────────────────── */ static void demo01_lifecycle(void) { printf("=== 示例 1: 引擎生命周期 ===\n"); VdeHandle ctx = vde_create(); printf(" 引擎创建成功\n"); const char* ver = vde_version(); printf(" VDE 版本: %s\n", ver); vde_destroy(ctx); printf(" 引擎销毁成功\n\n"); } /* ── 示例 2: Mesh 创建/查询/保存 ───────────────────────── */ static int demo02_mesh_io(void) { printf("=== 示例 2: Mesh I/O ===\n"); VdeHandle ctx = vde_create(); /* 2.1 创建 B-Rep box → 转 mesh(模拟加载) */ VdeBodyHandle body = vde_body_create_box(ctx, 2.0, 2.0, 2.0); CHECK(body != NULL, "vde_body_create_box 失败"); VdeMeshHandle mesh = vde_body_to_mesh(ctx, body, 0.01); CHECK(mesh != NULL, "vde_body_to_mesh 失败"); /* 2.2 查询网格属性 */ size_t nv = vde_mesh_num_vertices(mesh); size_t nf = vde_mesh_num_faces(mesh); printf(" 顶点数: %zu, 三角面数: %zu\n", nv, nf); /* 2.3 获取包围盒 */ double min_x, min_y, min_z, max_x, max_y, max_z; vde_mesh_get_bounds(mesh, &min_x, &min_y, &min_z, &max_x, &max_y, &max_z); printf(" 包围盒: (%.1f, %.1f, %.1f) - (%.1f, %.1f, %.1f)\n", min_x, min_y, min_z, max_x, max_y, max_z); /* 2.4 获取第一个顶点 */ if (nv > 0) { double vx, vy, vz; vde_mesh_get_vertex(mesh, 0, &vx, &vy, &vz); printf(" 顶点 [0]: (%.3f, %.3f, %.3f)\n", vx, vy, vz); } /* 2.5 获取第一个面的索引 — 演示 vde_mesh_get_face + vde_free_buffer */ if (nf > 0) { int* indices = NULL; int n = vde_mesh_get_face(mesh, 0, &indices); if (n > 0) { printf(" 面 [0]: v%d v%d v%d\n", indices[0], indices[1], indices[2]); } vde_free_buffer((uint8_t*)indices); /* 释放库分配的索引数组 */ } /* 2.6 保存为 OBJ */ int saved = vde_save_mesh(ctx, mesh, "/tmp/vde_capi_demo_box.obj", "obj"); printf(" 保存 OBJ: %s\n", saved ? "成功" : "失败"); vde_mesh_free(mesh); vde_body_free(body); vde_destroy(ctx); printf(" Mesh I/O 演示完成\n\n"); return 0; } /* ── 示例 3: 网格简化与平滑 ────────────────────────────── */ static int demo03_mesh_process(void) { printf("=== 示例 3: 网格处理 ===\n"); VdeHandle ctx = vde_create(); /* 创建球体 → 网格(较多三角形,便于观察简化效果) */ VdeBodyHandle sphere = vde_body_create_sphere(ctx, 2.0, 32, 32); VdeMeshHandle mesh = vde_body_to_mesh(ctx, sphere, 0.01); printf(" 原始球体: %zu 顶点, %zu 面\n", vde_mesh_num_vertices(mesh), vde_mesh_num_faces(mesh)); /* 网格简化到 50% */ VdeMeshHandle simplified = vde_mesh_simplify(ctx, mesh, 0.5); if (simplified) { printf(" 简化后: %zu 顶点, %zu 面 (目标 50%%)\n", vde_mesh_num_vertices(simplified), vde_mesh_num_faces(simplified)); vde_mesh_free(simplified); } /* 网格平滑 */ VdeMeshHandle smoothed = vde_mesh_smooth(ctx, mesh, 3); if (smoothed) { printf(" 平滑后: %zu 顶点, %zu 面 (3 次迭代)\n", vde_mesh_num_vertices(smoothed), vde_mesh_num_faces(smoothed)); vde_mesh_free(smoothed); } vde_mesh_free(mesh); vde_body_free(sphere); vde_destroy(ctx); printf(" 网格处理演示完成\n\n"); return 0; } /* ── 示例 4: 碰撞检测 ──────────────────────────────────── */ static int demo04_collision(void) { printf("=== 示例 4: 碰撞检测 ===\n"); VdeHandle ctx = vde_create(); /* 4.1 GJK 球体碰撞 — 两球相交 */ int hit = vde_collision_gjk_spheres(ctx, 0.0, 0.0, 0.0, 1.0, /* 球 1: 原点, 半径 1 */ 1.5, 0.0, 0.0, 1.0); /* 球 2: (1.5,0,0), 半径 1 → 圆心距 1.5 < 1+1=2 */ printf(" GJK 两球相交: %s (期望: 1)\n", hit ? "是" : "否"); /* 相距远的球 — 不应碰撞 */ hit = vde_collision_gjk_spheres(ctx, 0.0, 0.0, 0.0, 1.0, 5.0, 0.0, 0.0, 1.0); /* 圆心距 5 > 2 */ printf(" GJK 两球分离: %s (期望: 0)\n", hit ? "是" : "否"); /* 4.2 射线-网格碰撞 — 从 Z+ 方向射向一个立方体 */ VdeBodyHandle box = vde_body_create_box(ctx, 2.0, 2.0, 2.0); VdeMeshHandle mesh = vde_body_to_mesh(ctx, box, 0.01); double t, hx, hy, hz; int ray_hit = vde_collision_ray_mesh(ctx, mesh, 0.0, 0.0, 5.0, /* 射线起点: (0,0,5) */ 0.0, 0.0, -1.0, /* 方向: 沿 Z 负方向 */ &t, &hx, &hy, &hz); if (ray_hit) { printf(" 射线命中: t=%.3f, 交点=(%.3f, %.3f, %.3f)\n", t, hx, hy, hz); } else { printf(" 射线未命中 (不应该)\n"); } vde_mesh_free(mesh); vde_body_free(box); vde_destroy(ctx); printf(" 碰撞检测演示完成\n\n"); return 0; } /* ── 示例 5: Bézier 曲线 ───────────────────────────────── */ static int demo05_curve(void) { printf("=== 示例 5: Bézier 曲线 ===\n"); VdeHandle ctx = vde_create(); /* 创建 3 阶 (4 控制点) Bézier 曲线 */ double cp[] = { 0.0, 0.0, 0.0, /* P0 */ 1.0, 2.0, 0.0, /* P1 */ 2.0, 2.0, 0.0, /* P2 */ 3.0, 0.0, 0.0 /* P3 */ }; VdeCurveHandle curve = vde_curve_create_bezier(ctx, cp, 4, 3); CHECK(curve != NULL, "vde_curve_create_bezier 失败"); printf(" 曲线次数: %d\n", vde_curve_degree(curve)); /* 在参数 t = 0.0, 0.5, 1.0 处求值 */ for (int i = 0; i <= 2; i++) { double t = i * 0.5; double px, py, pz; vde_curve_evaluate(curve, t, &px, &py, &pz); printf(" t=%.1f → (%.3f, %.3f, %.3f)\n", t, px, py, pz); } vde_curve_free(curve); vde_destroy(ctx); printf(" 曲线演示完成\n\n"); return 0; } /* ── 示例 6: B-Rep 实体与布尔运算 ─────────────────────── */ static int demo06_brep_boolean(void) { printf("=== 示例 6: B-Rep 布尔运算 ===\n"); VdeHandle ctx = vde_create(); /* 创建立方体和球体 */ VdeBodyHandle box = vde_body_create_box(ctx, 2.0, 2.0, 2.0); VdeBodyHandle sphere = vde_body_create_sphere(ctx, 1.2, 32, 32); /* 并集: box ∪ sphere */ VdeBodyHandle union_body = vde_body_boolean(ctx, box, sphere, 0); CHECK(union_body != NULL, "B-Rep 并集失败"); VdeMeshHandle union_mesh = vde_body_to_mesh(ctx, union_body, 0.01); printf(" 并集: %zu 顶点, %zu 面\n", vde_mesh_num_vertices(union_mesh), vde_mesh_num_faces(union_mesh)); /* 深拷贝演示 */ VdeBodyHandle clone = vde_body_clone(ctx, union_body); CHECK(clone != NULL, "vde_body_clone 失败"); printf(" 深拷贝成功\n"); vde_mesh_free(union_mesh); vde_body_free(clone); vde_body_free(union_body); vde_body_free(sphere); vde_body_free(box); vde_destroy(ctx); printf(" B-Rep 布尔演示完成\n\n"); return 0; } /* ── 示例 7: SDF 隐式曲面 ──────────────────────────────── */ static int demo07_sdf(void) { printf("=== 示例 7: SDF 隐式曲面 ===\n"); VdeHandle ctx = vde_create(); /* 创建球体和盒子 SDF 节点 */ VdeSdfHandle s1 = vde_sdf_sphere(ctx, 1.5); VdeSdfHandle s2 = vde_sdf_box(ctx, 1.0, 1.0, 1.0); /* SDF 差集:球体减去盒子(得到一个带方形空腔的球) */ VdeSdfHandle diff = vde_sdf_difference(ctx, s1, s2); CHECK(diff != NULL, "SDF 差集失败"); /* 转为网格(注意:s1, s2 所有权已移交给 diff) */ VdeMeshHandle mesh = vde_sdf_to_mesh(ctx, diff, 64); if (mesh) { printf(" SDF → Mesh: %zu 顶点, %zu 面 (resolution=64)\n", vde_mesh_num_vertices(mesh), vde_mesh_num_faces(mesh)); vde_save_mesh(ctx, mesh, "/tmp/vde_capi_demo_sdf.obj", "obj"); vde_mesh_free(mesh); } /* 注意: s1, s2 已由 diff 拥有,只释放 diff */ vde_sdf_free(diff); vde_destroy(ctx); printf(" SDF 演示完成\n\n"); return 0; } /* ── 示例 8: 序列化 ────────────────────────────────────── */ static int demo08_serialize(void) { printf("=== 示例 8: 序列化/反序列化 ===\n"); VdeHandle ctx = vde_create(); /* 创建网格 */ VdeBodyHandle cyl = vde_body_create_cylinder(ctx, 1.0, 3.0, 24); VdeMeshHandle mesh = vde_body_to_mesh(ctx, cyl, 0.01); printf(" 原始网格: %zu 顶点, %zu 面\n", vde_mesh_num_vertices(mesh), vde_mesh_num_faces(mesh)); /* 序列化 */ uint8_t* data = NULL; size_t len = vde_serialize_mesh(ctx, mesh, &data); printf(" 序列化数据: %zu 字节\n", len); /* 反序列化 */ VdeMeshHandle mesh2 = vde_deserialize_mesh(ctx, data, len); if (mesh2) { printf(" 反序列化网格: %zu 顶点, %zu 面\n", vde_mesh_num_vertices(mesh2), vde_mesh_num_faces(mesh2)); vde_mesh_free(mesh2); } /* 释放序列化缓冲区 */ vde_free_buffer(data); vde_mesh_free(mesh); vde_body_free(cyl); vde_destroy(ctx); printf(" 序列化演示完成\n\n"); return 0; } /* ── 示例 9: 错误处理 ──────────────────────────────────── */ static void demo09_error_handling(void) { printf("=== 示例 9: 错误处理 ===\n"); VdeHandle ctx = vde_create(); /* 尝试加载不存在的文件 */ VdeMeshHandle bad = vde_load_mesh(ctx, "/nonexistent_file.obj"); if (!bad) { printf(" 加载失败 (预期): %s\n", vde_last_error(ctx)); } vde_destroy(ctx); printf(" 错误处理演示完成\n\n"); } /* ── main ───────────────────────────────────────────────── */ int main(void) { printf("╔══════════════════════════════════════════╗\n"); printf("║ ViewDesignEngine C API 基础使用示例 ║\n"); printf("╚══════════════════════════════════════════╝\n\n"); demo01_lifecycle(); int ret = 0; ret |= demo02_mesh_io(); ret |= demo03_mesh_process(); ret |= demo04_collision(); ret |= demo05_curve(); ret |= demo06_brep_boolean(); ret |= demo07_sdf(); ret |= demo08_serialize(); demo09_error_handling(); if (ret == 0) { printf("所有演示通过 ✓\n"); } else { printf("部分演示失败 ✗\n"); } return ret; }