代码之家  ›  专栏  ›  技术社区  ›  tigrou

如何将平面上的三维点转换为UV坐标?

  •  10
  • tigrou  · 技术社区  · 12 年前

    我有一个三维点,由 [x0, y0, z0] .

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

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

    如何将三维点转换或映射为一对 (u,v) 协调?

    这一定很简单,但我想不通。

    2 回复  |  直到 12 年前
        1
  •  15
  •   sbabbi    8 年前

    首先,您需要计算 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])
    

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

    即使您的矢量 [x0 y0 z0] 并没有完全躺在飞机上。如果是这样的话,它只会将其投影到平面上。

        2
  •  6
  •   user85109 user85109    12 年前

    假设你想找到平面中任何一点的坐标,用坐标(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是一个具有单位范数的向量,所以我们可以除以范数(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,或者我们可以找到不在平面中的点的法线投影,投影到该平面中。