测量uv映射失真的公式

有没有人知道一个简单的方法来计算(离线)纹理扭曲的数量映射到如下三角形时?

Vertex Position UV Coordinates A (Ax, Ay, Az) (Au, Av) B (Bx, By, Bz) (Bu, Bv) C (Cx, Cy, Cz) (Cu, Cv) 

我期待两个输出:沿着两个垂直轴的每一个的一个缩放因子。 (这些轴可能会或可能不会与u和v坐标轴alignment,例如对于已经被对角拉伸的纹理)

就我目前的目的而言,我不需要知道拉伸/压缩的方向,只是有多less。 我不想要一个单一的面积比例因子,因为一个方向上的拉伸加上另一个方向上的压缩可以抵消,从而得到一个接近于等面积但远离未失真的结果。

我可以通过计算一个将(Bxyz – Axyz)映射到((Buv – Auv),0)&(Cxyz – Axyz)上的matrix((Cuv – Auv),0) 0,0,1)),然后find它的特征值,但似乎这应该简化或提供一些捷径。 在纸上制定所有的中间体变得非常多毛。

到目前为止,我的search返回了很多关于使用三维建模软件包主观处理失真的建议,而不是用于测量失真的分析方法。

编辑:我原来的解决scheme没有工作。 映射matrix的特征值只对应于特殊定位情况下的比例因子。

幸运的是,我find了一个通用的解决scheme。

如果我们在U​​V空间中采集单位vector的集合并将它们映射到3D中,它们将形成椭圆,其长轴和短轴对应于我们想要的拉伸因子。

我们不关心转换后这些向量的绝对方向,而是根据以原点为中心的椭圆方程式来改变它们长度的变化:

 A * u*u + B * u*v + C * v*v = l*l 

所以首先我们需要find参数A,B和C(我将把这些顶点重命名为V1,V2,V3,这样它们就不会和这些系数的传统标签相冲突)

考虑三角形边缘(在3D和UV空间中)的集合:

 E1 = V1 - V3 E2 = V2 - V1 E3 = V3 - V2 

我们可以构造一个方程组来查找参数如下:

 ┌ ┐┌ ┐ ┌ ┐ | E1.u * E1.u E1.u * E1.v E1.v * E1.v || A | | dot(E1.xyz, E1.xyz) | | E2.u * E2.u E2.u * E2.v E2.v * E2.v || B | = | dot(E2.xyz, E2.xyz) | | E3.u * E3.u E3.u * E3.v E3.v * E3.v || C | | dot(E3.xyz, E3.xyz) | └ ┘└ ┘ └ ┘ 

请注意,通过构建,这对3D中三角形的旋转不敏感,这是一个好的开始,并且不需要任何正常化来达到那里不像我以前的解决scheme。

如果系数matrix的行列式为零,那么UV三角形是退化的(至less其中一个比例因子是无穷大的),并且需要特殊情况下的处理,我现在要去掉。

在用你最喜欢的方法解决这个问题之后(我用Cramer's Rule进行一个粗略的testing),我们有两个用于查找轴比例因子的例子:

 float p; float q; if(ApproximatelyEqual(A, C)) { // Ellipse is symmetrical across the line u=v. // (Either theta = PI/4, or B = 0 and scaling is uniform). p = A - 0.5f * B; q = A + 0.5f * B; } else { // Ellipse is non-uniformly scaled and arbitrarily rotated. // (Or a rounding error makes it appear slightly so) // Find its angle: float theta = atan(B/(C - A))/2f; // cos squared float c = cos(theta); c *= c; // sin squared float s = 1f - c; float divisor = 1f/(c - s); p = (A * c - C * s) * divisor; q = (C * c - A * s) * divisor; } // Note that numerical errors can sometimes cause p & q to be slightly negative. // This isn't meaningful, so clamp to a non-negative value before taking the root. float scale1 = sqrt(pos(p)); float scale2 = sqrt(pos(q)); 

虽然我不需要它,但是这也计算了非均匀拉伸的方向(theta)。 它不直接检测reflection,但可以通过检查uv空间中三角形的缠绕来添加。