最近我正在实施QEM网格简化算法,该算法最初来自Michael Garland和Paul S. Heckbert的论文Surface Simplification Using Quadric Error Metrics。
根据算法,我们应该为每条边计算contraction cost
,并将所有边放入最小堆中,这样每次我们以最小的合同成本获取边。然而,收缩可能导致入射三角形折叠,即标准在收缩之前和之后变化超过90度。可通过以下示例显示折叠现象:
假设我们选择的成本最低的边是V1V2
,我们即将收缩它。我们预见收缩会导致V1
和V2
合并在一起,如图所示。更重要的是,如果我们将三角形Tri(ABV2)
的范数定义为cross_product(V2A, V2B)
,我们可以发现这个范数从指向外向内改变方向。这不是我们想要的。该论文称,如果遇到这种情况,我们应该“惩罚”这个操作,即在V1V2
的成本中加入一大部分,以便V1V2
成为非堆顶,这意味着它不会在这一刻被接走。相反,我们将以最小的成本获得下一个优势。
该算法可以使用以下伪代码编写:
while (number_of_left_edges > Pre_defined_number)
{
Edge e = EdgeHeap.top();
if (Check_edge_will_cause_foldover(e))
{
e.cost += A_VERY_LARGE_NUMBER;
EdgeHeap.update();
}
else
{
e.Contract();
Do_something_on_incident_triangles(e.Triangles);
EdgeHeap.pop();
}
}
然而,我发现了一个非常棘手的问题。如上所述,当我发现边缘E1
的收缩可能导致某些三角形的折叠时,我扩大了它的成本并将其扔回堆中,然后我选择了另一条边E2
,然后仍然发现它会导致折叠。某某等等。我没有发现边缘可以再缩小,所以循环无限延续,实际上没有边缘被简化。
有没有人可以给我任何关于算法的提示,以便解决问题?非常感谢你!