3D广告牌精灵背后的数学是什么? (是:3D转换矩阵到2D矩阵)

时间:2014-02-01 20:59:17

标签: graphics matrix 3d transformation

我在太空中有一个3D点。点的精确方向/位置通过 4x4变换矩阵表示。

我想在这一点上画一个billboard (3D Sprite)我知道该点的投射位置(即3D-> 2D);广告牌面向相机,这也非常有用。 我不知道的是广告牌应该具有的缩放比例!

为了使事情变得更复杂, 4x4矩阵可能会有各种变换:3D旋转,3D缩放,3D换位。假设相机尽可能简单:位于(0,0,0),无旋转。

那么,我可以从这个4x4矩阵“提取”广告牌精灵的缩放吗?

-

WAS:

我有一个3D仿射变换4x4矩阵。我需要将它(项目)转换为2D仿射变换3x3矩阵,如下所示:

enter image description here

3D旋转是无关紧要的,如果存在则可能被丢弃;我只对翻译感兴趣,最重要的是缩放。

任何人都可以为每个 4 值的方程式提供帮助吗? (假设 t x ,t y 也是已知的)

其他信息:

Matrix3D是3D点的全局变换,比如说(0,0,0)。其目的是投影在2D平面(计算机屏幕)上。

我知道如何将3D点投影到2D空间,我正在寻找的是保留超出位置的其他转换信息,即缩放:正如您所知,缩放< / strong>在2D平面上投影点时也会改变属性。

我也忘了提及透视投影属性也是已知的,即:

field of view (single value)
focal length (single value)
projection center (viewpoint position - 2D value)

enter image description here

2 个答案:

答案 0 :(得分:3)

如果您不使用球面坐标系,则此任务无法解决,因为在投影前丢弃Z坐标将从投影点移除距离,因此您不知道如何应用透视。

你有两个选择(除非我忽视了一些事情):

  1. 应用3D变换矩阵

    然后只使用结果的x,y坐标

  2. 为旋转/投影创建3x3转换矩阵

    并在应用之前或之后添加偏移矢量。请注意,此方法不使用同源坐标!!!

  3. 为了清晰起见,

    [Edit1]等式

    3x3 vs. 4x4 transform matrix

    不要忘记3x3矩阵+矢量变换不是累积的!这就是为什么使用4x4转换的原因。现在你可以扔掉矩阵/向量(Xz,Yz,Zz), (z0)的最后一行,然后输出向量只是(x', y')。当然,在此之后你不能使用逆变换,因为你丢失了Z坐标。

    通过更改轴方向矢量的大小来完成缩放

    顺便说一下。如果你的投影平面也是XY - 平面没有旋转那么:

    x' = (x-x0)*d/(z-z0)
    y' = (y-y0)*d/(z-z0)
    


    (x,y,z) - 指向项目
    (x',y') - 预计点
    (x0,y0,z0) - 投射原点
    d - 焦距

    [Edit2]在问题编辑之后,意思完全不同

    我假设您希望精灵始终面向相机。它很丑陋但简化了草,树等......


    M - 你的矩阵
    P - M内的投影矩阵
    如果你的M = (0,0,0)原点没有旋转/缩放/倾斜,那么M=P
    pnt - 您的广告牌点(我假设的中心)(w=1[GCS]
    dx,dy - 广告牌的一半大小[LCS]
    A,B,C,D - 广告牌的投影边[GCS]
    [GCS] - 全球坐标系
    [LCS] - 本地坐标系

    1. 如果你知道投影矩阵

      我认为它是glFrustrum或gluPerspective ......然后:

      (x,y,z,w)=(M*(P^-1))*pnt  // transformed center of billboard without projection
      A=P*(x-dx,y-dy,z,w)
      B=P*(x-dx,y+dy,z,w)
      C=P*(x+dx,y+dy,z,w)
      D=P*(x+dx,y-dy,z,w)
      
    2. 如果您的M矩阵过于复杂,无法使用#1

      MM=(M*(P^-1))     // transform matrix without projection
      XX=MM(Xx,Xy,Xz)   // X - axis vector from MM [GCS](look at the image above on the right for positions inside matrix)
      YY=MM(Yx,Yy,Yz)   // Y - axis vector from MM [GCS]
      X =(M^-1)*XX*dx   // X - axis vector from MM [LCS] scaled to dx
      Y =(M^-1)*YY*dy   // Y - axis vector from MM [LCS] scaled to dy
      A = M*(pnt-X-Y)
      B = M*(pnt-X+Y)
      C = M*(pnt+X+Y)
      D = M*(pnt+X-Y)
      
    3. [Edit3]仅限scalling

      MM=(M*(P^-1))      // transform matrix without projection
      sx=|MM(Xx,Xy,Xz)|  // size of X - axis vector from MM [GCS] = scale x
      sy=|MM(Yx,Yy,Yz)|  // size of Y - axis vector from MM [GCS] = scale y
      

答案 1 :(得分:2)

比例矩阵S如下所示:

sx 0  0  0
0  sy 0  0
0  0  sz 0
0  0  0  1

翻译矩阵T如下所示:

1  0  0  0
0  1  0  0
0  0  1  0
tx ty tz 1

Z轴旋转矩阵R如下所示:

 cos(a) sin(a)  0  0
-sin(a) cos(a)  0  0
   0      0     1  0
   0      0     0  1

如果您有转换矩阵M,则它是RTS矩阵的多次乘法的结果。查看M,这些乘法的顺序和数量是未知的。但是,如果我们假设M=S*R*T我们可以将它分解为单独的矩阵。首先让我们计算S*R*T

        ( sx*cos(a) sx*sin(a) 0  0)       (m11 m12 m13 m14)
S*R*T = (-sy*sin(a) sy*cos(a) 0  0) = M = (m21 m22 m23 m24)
        (     0         0     sz 0)       (m31 m32 m33 m34)
        (     tx        ty    tz 1)       (m41 m42 m43 m44)

因为我们知道它是2D转换,所以获得翻译很简单:

translation = vector2D(tx, ty) = vector2D(m41, m42)

要计算轮换和比例,我们可以使用sin(a)^2+cos(a)^2=1

(m11 / sx)^2 + (m12 / sx)^2 = 1
(m21 / sy)^2 + (m22 / sy)^2 = 1

m11^2 + m12^2 = sx^2
m21^2 + m22^2 = sy^2

sx = sqrt(m11^2 + m12^2)
sy = sqrt(m21^2 + m22^2)

scale = vector2D(sx, sy)

rotation_angle = atan2(sx*m22, sy*m12)

Source

希望这能帮到你