如何将平面上的3D点转换为UV坐标?

10

我有一个由[x0, y0, z0]定义的三维点。

此点属于由[a, b, c, d]定义的平面。

normal = [a, b, c],并且ax + by + cz + d = 0

如何将三维点转换或映射为(u,v)坐标对?

这一定是极其简单的事情,但我想不出来。


你是在谈论通用的(u,v)坐标吗?还是你试图将世界空间中的一个点映射到定义在三角形上的纹理坐标? - sbabbi
我想给平面贴上纹理。 - tigrou
2个回答

15

首先,您需要计算您的u向量和v向量。 u向量和v向量应该与所在平面的法向量正交,并且彼此之间也应该正交。没有唯一定义它们的方法,但可能有一种方便快捷的方法,如下:

n = [a, b, c] 
u = normalize([b, -a, 0]) // Assuming that a != 0 and b != 0, otherwise use c.
v  = cross(n, u) // If n was normalized, v is already normalized. Otherwise normalize it.

现在只需要一个简单的点积:

u_coord = dot(u,[x0 y0 z0])
v_coord = dot(v,[x0 y0 z0])

请注意,这假定v-v坐标的原点是世界坐标原点(0,0,0)。

即使向量 [x0 y0 z0] 不完全位于平面上,此方法仍可奏效。如果情况如此,它将只是将其投影到平面上。     


一个问题:您对t向量做什么?当计算v_coord时,v向量来自哪里? - tigrou
@tigrou,抱歉,我把“v”写成了“t”。已经修改。 - sbabbi
我在加注释之前尝试过对 vt 进行替换,但没有奏效,真正的原因是我的程序中 n 不正确。我修复了它,并且现在可以运行了。谢谢 - tigrou

6
假设您想以坐标(u,v)的形式找到平面上任意点的坐标...
如果点[x0,y0,z0]位于平面上,则我们知道:
dot([a,b,c],[x0,y0,z0]) = -d

其中dot是两个向量的点积。这只是平面方程的简单重写。

关键在于找到跨越平面子空间的两个向量。为此,我们选择一个长度为3的随机向量。称其为V0。我将称其为平面法向量。

N = [a,b,c]

接下来,使用法向量N与V0的叉积。
V1 = cross(N,V0)

该向量将与法向量垂直,除非我们极其不幸,N 和 V0 共线。在这种情况下,只需选择另一个随机向量 V0 即可。我们可以通过检查两个向量是否共线来判断,因为此时 V1 将是向量 [0 0 0]。
所以,如果 V1 不是零向量,则将每个元素除以 V1 的范数。向量的范数仅是元素平方和的平方根。
V1 = V1/norm(V1)

接下来,我们选择第二个向量V2,使其垂直于N和V1。同样地,向量叉积可以轻易地完成这一步骤。同样将该向量归一化为单位长度。(由于我们现在知道V1是一个单位范数的向量,所以我们也可以通过除以norm(N)来实现。)

V2 = cross(N,V1)
V2 = V2/norm(V2)

现在可以将平面上的任何一点简单地描述为(u,v)的函数,如下所示:

[x0,y0,z0] + u*V1 + v*V2

例如,当(u,v)=(0,0)时,很明显我们会得到[x0,y0,z0],因此我们可以将该点视为(u,v)坐标系中的“原点”。
同样,我们可以从任何已知位于平面上的点[x,y,z]中恢复u和v,或者我们可以找到不在平面上但投影到该平面上的点的法线投影。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接