#pragma once /** * @file sdf_to_mesh.h * @brief SDF 到三角网格的转换 * * 使用 Marching Cubes 算法将隐式曲面(SDF)转换为显式三角网格。 * * ## Marching Cubes 算法 * * 在指定的包围盒内以固定分辨率采样 SDF 场,通过查表确定每个体素内的等值面三角形配置。 * * **流程:** * 1. 在 `[bmin, bmax]` 范围内构建分辨率 `res³` 的三维规则网格 * 2. 在每个网格点求值 SDF * 3. 利用 Marching Cubes 查找表在等值面处生成三角形 * 4. 返回包含顶点和三角形索引的 MCMesh * * ## 注意事项 * * - 分辨率越高网格越精细,但计算量按 O(res³) 增长 * - 推荐分辨率 64~256,取决于几何复杂度 * - 结果网格需在 Marching Cubes 模块中定义(vde::mesh::MCMesh) * * @ingroup sdf */ #include "vde/sdf/sdf_tree.h" #include "vde/mesh/marching_cubes.h" #include namespace vde::sdf { /** * @brief 将 SDF 表达式树转换为三角网格 * * 使用 Marching Cubes 算法在 SDF 树的包围盒内采样并生成网格。 * 包围盒由 estimate_bbox() 自动确定。 * * **算法步骤:** * 1. 调用 estimate_bbox(root) 确定采样范围 * 2. 构建分辨率 `resolution³` 体素网格 * 3. 在每个体素角点求值 SDF * 4. 用 Marching Cubes 提取 iso_level 等值面 * * @param root SDF 表达式树的根节点 * @param resolution 每轴的网格分辨率(例如 64 表示 64³ 体素网格) * @param iso_level 等值面水平(0.0 = 隐式表面) * @return 包含顶点和三角形索引的 MCMesh * * @note 分辨率推荐为 2 的幂(32, 64, 128, 256)以获得最佳缓存性能。 * @note 对于大尺寸但细节少的几何体,使用较低的 resolution 即可获得光滑结果。 * * @code{.cpp} * auto root = SdfNode::sphere(2.0); * auto mesh = sdf_to_mesh(root, 128); // 128³ 体素网格 * // mesh.vertices 和 mesh.indices 可直接用于渲染或导出 * @endcode * * @see sdf_to_mesh_lambda Lambda 版本的 SDF 转网格(Python 友好) * @see estimate_bbox 包围盒估算 */ [[nodiscard]] mesh::MCMesh sdf_to_mesh(const SdfNodePtr& root, int resolution = 64, double iso_level = 0.0); /** * @brief 将 Lambda SDF 函数转换为三角网格 * * 接受 C++ lambda 或 std::function 作为 SDF 定义,适合 Python 绑定场景。 * 与 sdf_to_mesh() 不同,本函数需要调用方显式提供包围盒。 * * @param f SDF 函数,签名为 double(double x, double y, double z) → 有符号距离 * @param bmin 采样包围盒最小角点 * @param bmax 采样包围盒最大角点 * @param resolution 每轴分辨率 * @param iso_level 等值面水平(默认 0.0) * @return MCMesh 三角网格 * * @code{.cpp} * // 球体 lambda * auto sphere_lambda = [](double x, double y, double z) { * return std::sqrt(x*x + y*y + z*z) - 1.0; * }; * auto mesh = sdf_to_mesh_lambda(sphere_lambda, * Point3D(-1.5, -1.5, -1.5), Point3D(1.5, 1.5, 1.5), 64); * @endcode * * @see sdf_to_mesh 基于 SDF 树的网格转换 */ [[nodiscard]] mesh::MCMesh sdf_to_mesh_lambda( const std::function& f, const Point3D& bmin, const Point3D& bmax, int resolution = 64, double iso_level = 0.0); } // namespace vde::sdf