sli*_*mbo 9 hardware opengl math 3d graphics
我无法理解从对象空间转换到视图空间的数学.我在硬件中这样做,我有下面的Atranspose矩阵:
ATranspose =
[rightx upx lookx 0]
[righty upy looky 0]
[rightz upz lookz 0]
[-eyeright -eyeup -eyelook 1]
Run Code Online (Sandbox Code Playgroud)
然后找到我们要做的观点:
[x,y,z,1] = [x',y',z',1]*ATranspose
xnew = xold*rightx + xold*righty + xold*rightz + xold*(-eyeright)
Run Code Online (Sandbox Code Playgroud)
但我不确定这是否正确.
它也可能是
[x,y,z,1]=atranspose*[x',y',z',1]T
Run Code Online (Sandbox Code Playgroud)
有人可以向我解释一下吗?我无法在网上找到任何不直接与opengl代码相关的内容,我只是想了解从对象坐标到眼睛坐标转换点背后的数学.
JCo*_*per 13
这个答案可能比它需要的时间长得多.如果您已经理解了大部分矩阵数学,那么请跳至最后2段左右.
从一维问题开始可能最简单.在1D中,我们在一条线上有点.我们可以扩展它们或者我们可以翻译它们.考虑三个点I,J,K和变换矩阵中号.
M = [ s t ]
[ 0 1 ]
i = [1] j = [-2] k = [0]
[1] [ 1] [1]
j k i
???????????????
-2 -1 0 1 2
Run Code Online (Sandbox Code Playgroud)
当我们乘以M时,得到:
i' = Mi = [ s t ][ 1] = [ s+t ]
[ 0 1 ][ 1] [ 1 ]
j' = Mj = [ s t ][-2] = [-2s+t]
[ 0 1 ][ 1] [ 1 ]
k' = Mk = [ s t ][ 0] = [ t ]
[ 0 1 ][ 1] [ 1 ]
Run Code Online (Sandbox Code Playgroud)
因此,如果我们为s和t赋值,那么我们就可以在我们的1D'三角形'上进行各种变换.缩放会改变"点"之间的距离,而纯粹的平移会相对于原点移动它们,同时保持间距不变:
s=1 t=0 s=2 t=1 s=1 t=2
j k i j k i j k i
??????????????? ??????????????? ???????????????
-2 -1 0 1 2 -3 -1 1 3 5 0 1 2 3 4
Run Code Online (Sandbox Code Playgroud)
重要的是要注意转换的顺序是至关重要的.这些1D变换缩放然后翻译.如果你要先翻译,那么'点'将与原点的距离不同,因此缩放因子会对它产生不同的影响.出于这个原因,转换通常保存在单独的矩阵中,以便顺序清晰.
如果我们向上移动到2D,我们得到矩阵N:
[1 0 tx][ cos(a) sin(a) 0][sx 0 0] [ sx*cos(a) sx*sin(a) tx ]
N =[0 1 ty][-sin(a) cos(a) 0][ 0 sy 0]=[-sy*sin(a) sy*cos(a) ty ]
[0 0 1 ][ 0 0 1][ 0 0 1] [ 0 0 1 ]
Run Code Online (Sandbox Code Playgroud)
该矩阵将1)由缩放点SX,SY,2)旋转围绕原点通过一个度,然后3平移由点TX,TY.注意,该矩阵是在假设点被表示为列向量并且乘法将作为Np发生的情况下构造的.正如datenwolf所说,如果你想使用点的行向量表示但应用相同的转换,你可以转置所有内容并交换顺序.这是矩阵乘法的一般性质:(AB)^ T =(B ^ T)(A ^ T).
也就是说,我们可以谈论对象,世界和眼睛坐标方面的变换.如果眼睛坐在世界的原点,向下俯视世界的负z轴,向右+向上+ +向上+对象,一个立方体,坐下10个单位-z(以z为中心)轴),沿世界x的宽度为2,沿z的宽度为3,沿世界y的高度为4.然后,如果立方体的中心是对象的本地参照系,并且其局部轴方便地与世界轴对齐.然后,对象坐标中框的顶点是变体[+/-1,+/-2,+/-1.5]^T.近,上,右(从眼睛的视点)顶点有对象坐标 [1,2,1.5]^T,在世界坐标中,相同的顶点是[1,2,-8.5]^T(1.5-10 = -8.5).由于映入眼帘的是,它指向的方式,而我们定义我们的眼睛一样的OpenGL的事实,该顶点具有相同的眼坐标为世界坐标.因此,让我们继续前进并转动眼球,使得眼球的X是正确的(RT)和眼睛的Ÿ是向上和眼睛的-z是看(LK)和眼睛定位在[eyeright(ex) eyeup(ey) eyelook(ez)]^T.由于我们希望将对象坐标转换为眼睛坐标(意味着我们将眼睛视为原点),我们将采用这些转换的反转并将它们应用于对象顶点(在它们被转换为世界坐标之后).所以我们将:
ep = [WORLD_TO_EYE]*[OBJECT_TO_WORLD]*wp;
Run Code Online (Sandbox Code Playgroud)
更具体地说,对于我们感兴趣的顶点,我们将:
[ rt.x rt.y rt.z 0][1 0 0 -ex][1 0 0 0 ][ 1 ]
[ up.x up.y up.z 0][0 1 0 -ey][0 1 0 0 ][ 2 ]
[-lk.x -lk.y -lk.z 0][0 0 1 -ez][0 0 1 -10][1.5]
[ 0 0 0 1][0 0 0 1 ][0 0 0 1 ][ 1 ]
Run Code Online (Sandbox Code Playgroud)
为方便起见,我已经将眼睛的旋转影响了它.实际上,既然我已经写了这么多,这可能是混乱的一点.您提供的矩阵将旋转然后翻译.我假设眼睛的翻译是在世界坐标中.但正如你在问题中写的那样,它实际上是在眼睛坐标中进行翻译.我也否定了lk因为我们已经将眼睛定义为俯视负z轴,但是为了制作标准旋转矩阵,我们想要使用正值.
无论如何,我可以坚持下去,但也许这已经回答了你的问题.
继续:
进一步解释上述内容,将眼睛的变换分成两个部分也使得更容易找到逆.很容易看出,如果平移tx将眼睛移动到相对于世界物体的某个地方,我们可以通过-tx移动世界上的所有东西并保持眼睛静止,从而在眼睛和世界各点之间保持相同的相对位置.
同样,考虑眼睛的方向由其默认的右,向上和外观向量定义:
[1] [0] [ 0]
d_rt=[0] d_up=[1] d_lk=[ 0]
[0] [0] [-1]
Run Code Online (Sandbox Code Playgroud)
创建一个将这三个向量指向新方向的旋转矩阵很容易.我们只是排列我们的三个新轴rt,up,lk(作为列向量):
[rt.x up.x -lk.x 0]
[rt.y up.y -lk.y 0]
[rt.z up.z -lk.z 0]
[ 0 0 0 1]
Run Code Online (Sandbox Code Playgroud)
很容易看出,如果你增加d_rt,d_up和d_lk并乘以上面的矩阵,你会分别得到rt,up和lk.所以我们应用了我们想要的转型.要成为正确的旋转,三个向量必须是正交的.这实际上只是基础的变化.由于这个事实,我们可以通过其转置非常方便地找到该矩阵的逆.这就是我上面所做的.如果将该转置矩阵应用于世界坐标中的所有点并使眼睛保持静止,则这些点将相对于眼睛保持相同的位置,就像眼睛旋转一样.
例如:
分配(以世界坐标):
[ 0] [0] [-1] [-2] [1.5]
rt=[ 0] up=[1] lk=[ 0] eye=[ 0] obj=[ 0 ]
[-1] [0] [ 0] [ 1] [-3 ]
Run Code Online (Sandbox Code Playgroud)
