71 lines
2.5 KiB
C++
71 lines
2.5 KiB
C++
#pragma once
|
||
#include "vde/core/point.h"
|
||
#include <vector>
|
||
#include <array>
|
||
#include <functional>
|
||
|
||
namespace vde::curves {
|
||
using core::Point3D;
|
||
using core::Vector3D;
|
||
|
||
/**
|
||
* @brief 均匀参数化曲面三角化
|
||
*
|
||
* 在参数域 [0,1]×[0,1] 上生成 res_u×res_v 均匀采样点,
|
||
* 调用 eval(u,v) 求值后将每个四边形拆为两个三角形。
|
||
*
|
||
* @param eval 曲面求值函数 eval(u,v) -> Point3D,参数 (u,v) ∈ [0,1]×[0,1]
|
||
* @param res_u u 方向子分段数(≥ 1)
|
||
* @param res_v v 方向子分段数(≥ 1)
|
||
* @return {顶点数组, 三角形索引数组},三角形为 {i0,i1,i2}
|
||
*
|
||
* @note 总顶点数 = (res_u+1)×(res_v+1),三角形数 = 2×res_u×res_v
|
||
* @code{.cpp}
|
||
* auto [verts, tris] = tessellate(
|
||
* [&](double u, double v) { return surface.evaluate(u,v); },
|
||
* 20, 20);
|
||
* @endcode
|
||
* @see adaptive_tessellate
|
||
* @ingroup curves
|
||
*/
|
||
std::pair<std::vector<Point3D>, std::vector<std::array<int, 3>>>
|
||
tessellate(const std::function<Point3D(double,double)>& eval,
|
||
int res_u, int res_v);
|
||
|
||
/**
|
||
* @brief 自适应曲面三角化
|
||
*
|
||
* 基于法向角度偏差的自适应细分策略:
|
||
* 从 min_res×min_res 初始网格开始,对每个四边形检查四个角点的法向偏差。
|
||
* 若任意相邻角点间的法向夹角超过 angle_threshold_deg,则将该四边形四分细分。
|
||
*
|
||
* 相比均匀 tessellate() 的优点:
|
||
* - 曲率大的区域自动增加采样密度
|
||
* - 平坦区域保持粗糙网格,节省面数
|
||
*
|
||
* @param eval 曲面求值函数 eval(u,v) -> Point3D
|
||
* @param normal_fn 单位法向函数 normal_fn(u,v) -> Vector3D
|
||
* @param min_res 初始每向子分段数(≥ 1),默认 2
|
||
* @param max_depth 最大递归深度,限制总面数,默认 6
|
||
* @param angle_threshold_deg 法向角度偏差阈值(度),默认 5.0
|
||
* @return {顶点数组, 三角形索引数组}
|
||
*
|
||
* @note 最终面数上限约为 2·min_res²·4^max_depth(实际远小于此上限)
|
||
* @code{.cpp}
|
||
* auto [verts, tris] = adaptive_tessellate(
|
||
* [&](double u, double v) { return surf.evaluate(u,v); },
|
||
* [&](double u, double v) { return surf.normal(u,v); },
|
||
* 2, 5, 3.0); // 3° 偏差阈值,最大深度 5
|
||
* @endcode
|
||
* @see tessellate
|
||
* @ingroup curves
|
||
*/
|
||
std::pair<std::vector<Point3D>, std::vector<std::array<int, 3>>>
|
||
adaptive_tessellate(
|
||
const std::function<Point3D(double,double)>& eval,
|
||
const std::function<Vector3D(double,double)>& normal_fn,
|
||
int min_res = 2, int max_depth = 6,
|
||
double angle_threshold_deg = 5.0);
|
||
|
||
} // namespace vde::curves
|