我在太空中有一个3D点。点的精确方向/位置通过 4x4变换矩阵表示。
我想在这一点上画一个billboard (3D Sprite)。 我知道该点的投射位置(即3D-> 2D);广告牌面向相机,这也非常有用。 我不知道的是广告牌应该具有的缩放比例!
为了使事情变得更复杂, 4x4矩阵可能会有各种变换:3D旋转,3D缩放,3D换位。假设相机尽可能简单:位于(0,0,0),无旋转。
那么,我可以从这个4x4矩阵“提取”广告牌精灵的缩放吗?
我有一个3D仿射变换4x4矩阵。我需要将它(项目)转换为2D仿射变换3x3矩阵,如下所示:
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)
答案 0 :(得分:3)
如果您不使用球面坐标系,则此任务无法解决,因为在投影前丢弃Z坐标将从投影点移除距离,因此您不知道如何应用透视。
你有两个选择(除非我忽视了一些事情):
应用3D变换矩阵
然后只使用结果的x,y坐标
为旋转/投影创建3x3转换矩阵
并在应用之前或之后添加偏移矢量。请注意,此方法不使用同源坐标!!!
[Edit1]等式
不要忘记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]
- 本地坐标系
如果你知道投影矩阵
我认为它是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)
如果您的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]仅限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
,则它是R
,T
和S
矩阵的多次乘法的结果。查看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)
希望这能帮到你