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

时间:2013-09-06 17:54:08

标签: c# math 3d texture-mapping plane

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

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

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

如何将3d点转换或映射到一对(u,v)坐标?

这一定非常简单,但我无法理解。

2 个答案:

答案 0 :(得分:10)

首先,您需要计算uv向量。 uv应与您平面的法线正交,并且彼此正交。没有独特的方法来定义它们,但方便快捷的方式可能是这样的:

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])

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

即使你的矢量[x0 y0 z0]没有完全位于飞机上,这也会有效。如果是这种情况,它只会将其投影到飞机上。

答案 1 :(得分:3)

假设您想要找到平面中任何点的坐标,以坐标(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)

接下来,我们选择与N和V1正交的第二矢量V2。同样,矢量交叉产品也可以做到这一点。将该向量标准化以具有单位长度。 (因为我们现在知道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,或者我们可以找到不在平面内的点的法线投影,投射到那架飞机上。