95 lines
3.3 KiB
C++
95 lines
3.3 KiB
C++
#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 <functional>
|
||
|
||
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<double(double, double, double)>& f,
|
||
const Point3D& bmin, const Point3D& bmax,
|
||
int resolution = 64, double iso_level = 0.0);
|
||
|
||
} // namespace vde::sdf
|