QEM网格简化算法学习

《Surface Simplification Using Quadric Error Metrics》这篇论文介绍了一种网格简化的算法,通过“edge contraction”(边收缩)的方法来简化网格。边收缩的结果就是将两个顶点合成一个顶点,因此可以按照任意的顶点数目去简化网格。

image-20230908190941719

假设有一个二次函数 Δ ( v ) = v T Q v \Delta(\mathbf{v})=\mathbf{v}^T\mathbf{Q}\mathbf{v} Δ(v)=vTQv 可以描述顶点 v \mathbf{v} v的“变形程度”,这篇论文的算法目的就是最小化总体的“变形程度”,即:
minimize ∑ v v T Q v \text{minimize} \quad \sum_{\mathbf{v}} \mathbf{v}^T\mathbf{Q}\mathbf{v} minimizevvTQv
但是由于直接最小化不太现实,因为顶点数目会发生改变,所以这篇论文的算法步骤是这样的:

  1. 对每个顶点计算其初始的 Q \mathbf{Q} Q,满足 v T Q v = 0 \mathbf{v}^T\mathbf{Q}\mathbf{v}=0 vTQv=0
  2. 保存所有合法的“点对”,包括所有的边对应的点对,以及距离小于一定阈值的顶点对;
  3. 对于每个合法的点对( v 1 , v 2 \mathbf{v}_1,\mathbf{v}_2 v1,v2),生成合成的顶点 v s \mathbf{v}_s vs,这一步边收缩的代价为 Δ ( v s ) = v s T ( Q 1 + Q 2 ) v s \Delta(\mathbf{v}_s)=\mathbf{v}_s^T(\mathbf{Q}_1+\mathbf{Q}_2)\mathbf{v}_s Δ(vs)=vsT(Q1+Q2)vs,也就是新顶点的“变形程度”。这里合成顶点的方法有很多,可以是中点、其中一个顶点、或者最小化 Δ ( v s ) \Delta(\mathbf{v}_s) Δ(vs) 对应的顶点位置;
  4. 重复选择 Δ ( v s ) \Delta(\mathbf{v}_s) Δ(vs) 最小的顶点对进行边收缩,然后更新mesh、相关顶点的 Q \mathbf{Q} Q、以及相关合成顶点的代价,直到目标顶点数目。可以用一定的数据结构来维护。

接下来我用我的理解来描述这个二次误差函数 Δ ( v ) = v T Q v \Delta(\mathbf{v})=\mathbf{v}^T\mathbf{Q}\mathbf{v} Δ(v)=vTQv 的构造过程:

首先我们用一种启发式的思想去思考,要如何度量一个mesh的微小变形的程度呢?

image-20230908192054364

假如只有一个平面三角形,当它的一个顶点A有一个微小的偏移时,这个顶点相对于对边BC的距离h也会发生变化,因此可以用h来度量点A的“变形程度”,亦即
Δ ( A ) = h 。 \Delta(A)=h 。 Δ(A)=h
也许当A的位移平行于BC时,用h无法表示这样的变形,但是这只是一种思想,既考虑了简洁性,也考虑了在实际变形中大概率不会有这种特殊的变形。

类比到空间中的一个三角网格(triangular mesh),当一个顶点 v \mathbf{v} v发生轻微变形时,我们用点到面的距离去度量其“变形程度”,顶点已经给出了,那么“面”有哪些呢?我们先假定每个顶点都保存了一些用于度量的面 planes ( v ) \text{planes}(\mathbf{v}) planes(v),在这种情况下,顶点 v = [ v x , v y , v z , 1 ] T \mathbf{v}=[v_x,v_y,v_z,1]^T v=[vx,vy,vz,1]T 的“变形程度”的度量可以写作
Δ ( v ) = ∑ p ∈ planes ( v ) ( p T v ) 2 , \Delta(\mathbf{v})=\sum_{\mathbf{p}\in\text{planes}(\mathbf{v})} (\mathbf{p}^T \mathbf{v})^2 , Δ(v)=pplanes(v)(pTv)2,
其中 p = [ a , b , c , d ] T \mathbf{p}=[a,b,c,d]^T p=[a,b,c,d]T表示平面 a x + b y + c z + d = 0 ax+by+cz+d=0 ax+by+cz+d=0,其中 a 2 + b 2 + c 2 = 1 a^2+b^2+c^2=1 a2+b2+c2=1,这个单位化的限制就是告诉我们平面 p \mathbf{p} p的法向量就是 ( a , b , c ) (a,b,c) (a,b,c),因此点到面的距离就是 p T v \mathbf{p}^T\mathbf{v} pTv ,高中时不是学过点到平面的距离公式吗,单位化后就不需要分母的那个法向量长度了。

现在回到"edge contraction",在边收缩前我们有两个顶点 v 1 \mathbf{v}_1 v1 v 2 \mathbf{v}_2 v2,收缩完之后变成了一个顶点 v s \mathbf{v}_s vs,而与 v s \mathbf{v}_s vs关联的面的集合就变成了 planes ( v s ) = planes ( v 1 ) ⋃ planes ( v 2 ) \text{planes}(\mathbf{v}_s)=\text{planes}(\mathbf{v}_1) \bigcup \text{planes}(\mathbf{v}_2) planes(vs)=planes(v1)planes(v2) ,用集合的表示形式不太方便,因此我们写成矩阵的形式:
Δ ( v ) = ∑ ( p T v ) 2 = v T ( ∑ p p T ) v = v T ( ∑ Q i ) v \Delta(\mathbf{v})=\sum (\mathbf{p}^T \mathbf{v})^2 = \mathbf{v}^T (\sum\mathbf{p}\mathbf{p}^T) \mathbf{v} = \mathbf{v}^T (\sum\mathbf{Q_i}) \mathbf{v} Δ(v)=(pTv)2=vT(ppT)v=vT(Qi)v
就对应上之前算法里说的“变形程度”的度量公式了。所以前面讲到的保存每个顶点关联的面的集合,实际上就是保存这些面对应的矩阵之和,而边收缩的过程中,新的顶点需要保存的,就是旧的两个顶点保存的矩阵之和。

因此在算法中每个顶点保存的 Q \mathbf{Q} Q,初始化时就是将每个顶点相邻的面作为其关联的面,然后计算 Q \mathbf{Q} Q,在后续做边收缩时,只需要将收缩的两个顶点的 Q \mathbf{Q} Q相加即可。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值