2026-07-23 05:27:51 +00:00
|
|
|
|
#pragma once
|
|
|
|
|
|
#include "vde/mesh/halfedge_mesh.h"
|
|
|
|
|
|
|
|
|
|
|
|
namespace vde::mesh {
|
2026-07-23 08:19:24 +00:00
|
|
|
|
using core::Point2D;
|
|
|
|
|
|
using core::Point3D;
|
|
|
|
|
|
using core::Vector3D;
|
2026-07-23 05:27:51 +00:00
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief 网格简化选项
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
struct SimplifyOptions {
|
2026-07-24 11:04:04 +00:00
|
|
|
|
double target_ratio = 0.5; ///< 目标面数比例 (0, 1],0.5 表示保留 50% 的面
|
|
|
|
|
|
int max_iterations = 100; ///< 最大迭代次数(边塌缩上限)
|
|
|
|
|
|
bool preserve_boundary = true; ///< 是否保护边界边不被塌缩
|
2026-07-23 05:27:51 +00:00
|
|
|
|
};
|
|
|
|
|
|
|
2026-07-24 11:04:04 +00:00
|
|
|
|
/**
|
|
|
|
|
|
* @brief QEM(Quadric Error Metrics)网格简化
|
|
|
|
|
|
*
|
|
|
|
|
|
* 基于 Garland & Heckbert 1997 的 QEM 算法,通过迭代边塌缩减少三角面数量。
|
|
|
|
|
|
* 每条边维护一个 4×4 误差二次型 Q = Σ Q_f(面片的顶点-平面距离平方和),
|
|
|
|
|
|
* 塌缩目标点为 argmin v^T Q v,塌缩代价为该最小值。
|
|
|
|
|
|
*
|
|
|
|
|
|
* 算法流程:
|
|
|
|
|
|
* 1. 为每个顶点计算初始 Q(关联所有邻面的平面二次型之和)
|
|
|
|
|
|
* 2. 为每条边计算最优塌缩点及代价,插入最小堆
|
|
|
|
|
|
* 3. 循环弹出最小代价边,执行塌缩,更新受影响边的代价
|
|
|
|
|
|
* 4. 直到面数达到 target_ratio 或堆为空
|
|
|
|
|
|
*
|
|
|
|
|
|
* @param mesh 输入三角网格
|
|
|
|
|
|
* @param opts 简化选项
|
|
|
|
|
|
* @return 简化后的网格
|
|
|
|
|
|
*
|
|
|
|
|
|
* @note preserve_boundary 模式下,边界边通过惩罚项(大代价)被保护
|
|
|
|
|
|
* @code{.cpp}
|
|
|
|
|
|
* SimplifyOptions opts;
|
|
|
|
|
|
* opts.target_ratio = 0.1; // 保留 10% 面
|
|
|
|
|
|
* auto lod = simplify_mesh(high_res_mesh, opts);
|
|
|
|
|
|
* @endcode
|
|
|
|
|
|
* @ingroup mesh
|
|
|
|
|
|
*/
|
2026-07-23 05:27:51 +00:00
|
|
|
|
HalfedgeMesh simplify_mesh(const HalfedgeMesh& mesh, const SimplifyOptions& opts = {});
|
|
|
|
|
|
|
|
|
|
|
|
} // namespace vde::mesh
|