games301曲面参数化 作业1讲解 Floater权重tutte’s参数化

课程链接:

GAMES301曲面参数化
曲面参数化说白了就是研究建模展uv贴图、研究如何把一个曲面展开到平面上的,在建模软件和游戏引擎里面应用很广。

对本次作业中主要要解的线性方程组的理解

原理:对于没有隧道并且有且只有一条边界线的流型网格体,将其边界顶点有序地落在一个凸多边形上,并且保证内部的顶点是其邻居的凸线性组合,那么得到的(u,v)坐标参数化是双射的。
也就是说以这种方式展uv,得到的uv图结果不存在自交、重叠。

对于参数化后的每一个非边界顶点 P i P_i Pi,要保证其为为邻居顶点 P i , j P_{i,j} Pi,j的凸线性组合,则有:
W i , 0 P i , 0 + W i , 1 P i , 1 + W i , 2 P i , 2 + … = ( ∑ W i , j ) P i W_{i,0}P_{i,0}+W_{i,1}P_{i,1}+W_{i,2}P_{i,2}+\ldots=(\sum W_{i,j})P_{i} Wi,0Pi,0+Wi,1Pi,1+Wi,2Pi,2+=(Wi,j)Pi W i , j > 0 W_{i,j}>0 Wi,j>0
移项得到:
W i , 0 P i , 0 + W i , 1 P i , 1 + W i , 2 P i , 2 + … − ( ∑ W i , j ) P i + … = 0 W_{i,0}P_{i,0}+W_{i,1}P_{i,1}+W_{i,2}P_{i,2}+\ldots-(\sum W_{i,j})P_{i}+\ldots=0 Wi,0Pi,0+Wi,1Pi,1+Wi,2Pi,2+(Wi,j)Pi+=0
写成矩阵形式:
[ W i , 0 W i , 1 W i , 2 ⋯ − ( ∑ W i , j ) ⋯ ] [ P i , 0 P i , 1 P i , 2 ⋮ P i ⋮ ] = 0 \begin{bmatrix}W_{i,0}&W_{i,1}&W_{i,2}&{\cdots} &-(\sum W_{i,j})&{\cdots}\end{bmatrix} \begin{bmatrix}P_{i,0}\\ P_{i,1}\\ P_{i,2}\\ {\vdots}\\ P_{i}\\ {\vdots}\\ \end{bmatrix}=0 [Wi,0Wi,1Wi,2(Wi,j)] Pi,0Pi,1Pi,2Pi =0
将所有顶点都表示出来,就可以能得到
主要线性方程组

(其中u0 Bound v0 Bound等等,代表的是边界顶点固定到平面后的坐标)
可简写为方程 A X = B AX=B AX=B
在我的代码中我把等号左边的稀疏矩阵命名为A,等号右边的矩阵为B,中间的那个矩阵命名为X,其中代表u轴坐标的一列被我命名为Xu,代表v轴坐标的一列被我命名为Xv,并分别使用Eigen数学库中求解稀疏矩阵的方法求解XuXv

而什么样的权重,能使该线性方程组解出的uv图相比原网格体形变更小,更合理,就是后面权重计算的任务

权重计算

对于均匀权重的计算,不必过度赘述。直接来到Floater权重的计算

Floater权重的核心思想是:
对于每个非边界顶点 P i P_i Pi,新建一个以 P i P i , 0 ⃗ \vec{P_iP_{i,0}} PiPi,0 ( P i , 0 P_{i,0} Pi,0可以为 P i P_{i} Pi的任意邻居顶点)方向为x轴的平面直角坐标系,并把它放到该坐标系的原点,然后把它的某一个邻居顶点将点的1-邻域保角度比例、保长度地映射到该平面区域。求得在此坐标系下 P i P_i Pi点相对于其邻居顶点的重心权重并填入矩阵A,这样解出的uv图就能尽量吻合原本的形状

∣ ∣ P i , j − P i ∣ ∣ = ∣ ∣ X i , j − X i ∣ ∣ ||P_{i,j}-P_{i}||=||X_{i,j}-X_{i}|| ∣∣Pi,jPi∣∣=∣∣Xi,jXi∣∣
a n g ( P i , k − 1 , P i , P i , k ) = 2 π a n g ( X i , k − 1 , X i , X i , k ) / θ i ang(P_{i,k-1},P_i,P_{i,k})=2\pi ang(X_{i,k-1},Xi,X_{i,k})/\theta_i ang(Pi,k1,Pi,Pi,k)=2πang(Xi,k1,Xi,Xi,k)/θi

X i X_i Xi X i , j X_{i,j} Xi,j分别表示原网格体上的中心顶点和其邻居顶点, P i P_i Pi P i , j P_{i,j} Pi,j分别表示“拍平”后的中心顶点和其邻居顶点,其中 θ i \theta_i θi为中心顶点 X i X_i Xi与其邻居顶点 X i , k X_{i,k} Xi,k组成的夹角的总和)

求解 P i P_i Pi点相对于其邻居顶点的重心权重的方法:
首先,对于每条 P i P i , l P_iP_{i,l} PiPi,l直线,( P i P i , l P_iP_{i,l} PiPi,l代指所有 P i P_i Pi点与其邻居点的连线)都要寻找相邻的两个邻居顶点 P i , k − 1 P_{i,k-1} Pi,k1 P i , k P_{i,k} Pi,k,使得线段 P i , k − 1 P i , k P_{i,k-1}P_{i,k} Pi,k1Pi,k与直线 P i P i , l P_iP_{i,l} PiPi,l相交,组成三角形 △ P i , l P i , k − 1 P i , k \triangle P_{i,l}P_{i,k-1}P_{i,k} Pi,lPi,k1Pi,k,并在此三角形中求得其中心顶点 P i P_i Pi的重心权重{a,b,c},分别对应{ P i , l , P i , k − 1 , P i , k P_{i,l},P_{i,k-1},P_{i,k} Pi,l,Pi,k1,Pi,k}这三个顶点。
注意,我们可以使用叉乘的方法来判断 P i , k − 1 P_{i,k-1} Pi,k1 P i , k P_{i,k} Pi,k是否在直线 P i P i , l P_iP_{i,l} PiPi,l两侧;也可以直接计算重心权重,如果重心权重a,b,c的值都在(0,1)区间,那么也可以说明 P i P_i Pi在三角形 △ P i , l P i , k − 1 P i , k \triangle P_{i,l}P_{i,k-1}P_{i,k} Pi,lPi,k1Pi,k内部。
在这里插入图片描述

假设我们遍历到了某个中心顶点 P i P_i Pi,它有4个邻居顶点,分别是 P i , 0 , P i , 1 , P i , 2 , P i , 3 P_{i,0},P_{i,1},P_{i,2},P_{i,3} Pi,0,Pi,1,Pi,2,Pi,3,那么我们就创建一个4*4的矩阵Mu(读做希腊字母μ),把遍历 P i P i , l P_iP_{i,l} PiPi,l直线时,得到的权重{a,b,c},分别填到Mu的第l列的第j行,第k-1行和第k行。然后按行求和得到个列向量Sum_mu
在这里插入图片描述

矩阵A中,权重 W i , j W_{i,j} Wi,j的计算代码如下(*vertex为当前遍历到的中心顶点 neibors为其邻居顶点)

	Eigen::VectorXd Sum_mu = Mu.rowwise().sum();//综合邻居权重
	size_t size = neibors.size();
	double sum_weight = 0;
	for (size_t n = 0; n< size; n++)
	{
		double sum_mu = Sum_mu[n];
		double Wij = sum_mu / n_neibors;
		sum_weight += Wij;
		Eigen::Triplet<double> t((*vertex)->index(), (*neibors.at(n))->index(), Wij);
		triplet_list.push_back(t);
	}
	Eigen::Triplet<double> t((*vertex)->index(), (*vertex)->index(), -sum_weight);
	triplet_list.push_back(t);

作业中遇到的坑

①提前setPositon,把网格体的边界顶点固定了,没有用原始网格体数据,导致后面计算角度时出错,debug了很久才找到原因
②判定三角形时候出错,导致计算出来的A矩阵存在not a number的问题

作业效果图

均匀权重

猫头模型离散网格均匀权重参数化效果图(如果发现是反的,就拖拽旋转一下它)
在这里插入图片描述
半球模型均匀权重离散网格参数化效果图
在这里插入图片描述

Floater权重

猫头模型离散网格Floater权重参数化效果图(如果发现是反的,就拖拽旋转一下它)
在这里插入图片描述
半球模型离散网格Floater权重参数化效果图
在这里插入图片描述

我的作业答案和代码:

games301作业1答案

猜你喜欢

转载自blog.csdn.net/lifesize/article/details/127526985