2026-07-23 05:27:51 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "vde/core/point.h"
|
|
|
|
|
|
#include <vector>
|
|
|
|
|
|
#include <array>
|
2026-07-23 12:36:39 +00:00
|
|
|
|
#include <functional>
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
|
|
|
|
|
namespace vde::curves {
|
2026-07-23 08:19:24 +00:00
|
|
|
|
using core::Point3D;
|
|
|
|
|
|
using core::Vector3D;
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @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
|
|
|
|
|
|
*/
|
2026-07-23 12:36:39 +00:00
|
|
|
|
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);
|
|
|
|
|
|
|
2026-07-23 05:27:51 +00:00
|
|
|
|
} // namespace vde::curves
|