【问题标题】:What are the maths behind 3D billboard sprites? (was: 3D transformation matrix to 2D matrix)3D 广告牌精灵背后的数学原理是什么? (原为:3D 变换矩阵到 2D 矩阵)
【发布时间】:2014-02-25 12:52:22
【问题描述】:

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

我想在这一点上画一个billboard (3D Sprite)我知道该点的投影位置(即3D->2D);广告牌正对着相机,所以这也很有帮助。 我不知道广告牌应该有的缩放比例!

为了让事情变得更复杂,4x4 矩阵可能有各种变换:3D 旋转、3D 缩放、3D 转置。假设相机尽可能简单:定位在 (0,0,0),不旋转。

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

-

曾经:

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

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

任何人都可以帮助计算每个 six 4 值的方程式吗? (假设 tx, ty 也是已知的)

其他信息:

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

我知道如何将 3D 点投影到 2D 空间,我正在寻找的是在位置之外保留额外的变换信息,即 scaling:如您所知,scaling 在 2D 平面上投影点时,属性也会改变。

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

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

【问题讨论】:

    标签: graphics matrix 3d transformation


    【解决方案1】:

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

    你有两个选择(除非我忽略了什么):

    1. 应用 3D 变换矩阵

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

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

      并在应用它之前或之后添加偏移向量。请注意,这种方法不使用齐次坐标!!!

    [Edit1] 清晰的方程式

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

    通过改变轴方向向量的大小来实现缩放

    顺便说一句。如果您的投影平面也是 XY-plane 没有旋转,那么:

    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)
      

    [Edit3] 仅缩放

    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
    

    【讨论】:

    • 您能否详细说明(2)?我不想丢弃 Z,我只想将 SCALING 与 X、Y 坐标一起投影
    • 这是一个非常广泛的答案......但是 AFAICS,你给了我得到投影点的方程。正如我最初所说,我知道如何获得投影点。我正在重新编辑整个问题,因为我认为我造成了混乱。
    • 谢谢Spektre!但我觉得你会因此而激怒我:你给了我广告牌的 4 个边缘,虽然我使用的不是 OpenGL 而是 Flash。为了正确渲染我的广告牌,我需要传递两件事:投影点(我已经有了)和缩放因子(scaleX 和 scaleY)。根据您的数学,我想一种计算比例的方法是: scaleX=(D-A)/(billboard_original_sizeX) 。但是你的数学是否有一个“捷径”,这样我就可以在不计算广告牌的所有四个边缘的情况下获得 SCALING?不好意思一直打扰你!!!
    • @Bill Kotsias 我认为 edit3 是您所寻求的(如果我正确理解您渲染的缩放因子)
    • 太好了,我会检查一下并把结果告诉你(当然是在赏金到期之前!)
    【解决方案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

    希望对你有帮助

    【讨论】:

    • 确实很有帮助,但不是我问题的答案。我重新编辑了这个问题,希望我能得到正确的答案......
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-02-04
    • 1970-01-01
    • 2015-12-08
    • 1970-01-01
    • 1970-01-01
    • 2011-01-16
    相关资源
    最近更新 更多