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

tig*_*rou 7 c# math 3d texture-mapping plane

我有一个3d点,定义为[x0, y0, z0].

这一点属于一个平面,由[a, b, c, d].

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

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

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

sba*_*bbi 10

首先,您需要计算您的uv向量.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.
Run Code Online (Sandbox Code Playgroud)

现在一个简单的点产品将:

u_coord = dot(u,[x0 y0 z0])
v_coord = dot(v,[x0 y0 z0])
Run Code Online (Sandbox Code Playgroud)

请注意,这假定uv坐标的原点是世界原点(0,0,0).

即使您的矢量[x0 y0 z0]不完全位于平面上,这也会起作用.如果是这种情况,它只会将其投影到飞机上.      


小智 5

假设你想找到平面中任意点的坐标,就坐标 (u,v) 而言......

如果点 [x0,y0,z0] 位于平面内,那么我们知道

dot([a,b,c],[x0,y0,z0]) = -d
Run Code Online (Sandbox Code Playgroud)

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

诀窍是找到两个跨越平面子空间的向量。为此,我们选择一个长度为 3 的随机向量。称之为 V0。我将称之为平面法向量

N = [a,b,c]
Run Code Online (Sandbox Code Playgroud)

接下来,使用法向量 N 与 V0 的叉积。

V1 = cross(N,V0)
Run Code Online (Sandbox Code Playgroud)

这个向量将与法向量正交,除非我们非常不走运并且 N 和 V0 共线。在这种情况下,只需选择另一个随机向量 V0。我们可以判断这两个向量是否共线,因为 V1 将是向量 [0 0 0]。

因此,如果 V1 不是零向量,则将每个元素除以 V1 的范数。向量的范数只是元素平方和的平方根。

V1 = V1/norm(V1)
Run Code Online (Sandbox Code Playgroud)

接下来,我们选择与 N 和 V1 都正交的第二个向量 V2。同样,向量叉积很简单。将该向量归一化为具有单位长度。(因为我们现在知道 V1 是一个具有单位范数的向量,我们可以只除以 norm(N)。)

V2 = cross(N,V1)
V2 = V2/norm(V2)
Run Code Online (Sandbox Code Playgroud)

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

[x0,y0,z0] + u*V1 + v*V2
Run Code Online (Sandbox Code Playgroud)

例如,当 (u,v) = (0,0) 时,显然我们得到 [x0,y0,z0] 返回,因此我们可以将该点视为 (u,v) 坐标中的“原点”。

同样,我们可以做一些事情,比如从已知位于平面内的任何点 [x,y,z] 恢复 u 和 v,或者我们可以找到不在平面内的点的法线投影,投影到平面上飞机。