3D 图形处理 - 如何计算模型视图矩阵 [英] 3D Graphics Processing - How to calculate modelview matrix

查看:28
本文介绍了3D 图形处理 - 如何计算模型视图矩阵的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我无法理解从对象空间转换为视图空间的数学运算.我在硬件中这样做,我有下面的 Atranspose 矩阵:

I am having trouble understanding the math to convert from object space to view space. I am doing this in hardware and I have the Atranspose matrix below:

ATranspose =

ATranspose =

         [rightx      upx     lookx    0]
         [righty      upy     looky    0]
         [rightz      upz     lookz    0]
         [-eyeright -eyeup -eyelook    1]

然后找到我们要做的点:

Then to find the point we would do:

  [x,y,z,1] = [x',y',z',1]*ATranspose

  xnew = xold*rightx + xold*righty + xold*rightz + xold*(-eyeright)

但我不确定这是否正确.

but I am not sure if this is correct.

也可以

   [x,y,z,1]=atranspose*[x',y',z',1]T

有人可以向我解释一下吗?我在网上找不到任何与 opengl 代码不直接相关的内容,我只想了解将点从对象坐标转换为眼睛坐标背后的数学原理.

Can someone please explain this to me? I can't find anything online about it that isn't directly opengl code related I just want to understand the math behind transforming points from object coordinates to eye coordinates.

推荐答案

这个答案可能比它需要的要长得多.如果您已经了解大部分矩阵数学,请跳到底部 2 段左右.

This answer is probably much longer than it needs to be. Jump down to the bottom 2 paragraphs or so if you already understand most of the matrix math.

从一维问题开始可能是最简单的.在 1D 中,我们在一条线上有点.我们可以缩放它们,也可以翻译它们.考虑三个点i,j,k和变换矩阵M.

It might be easiest to start by looking at a 1 dimensional problem. In 1D, we have points on a line. We can scale them or we can translate them. Consider three points i,j,k and transformation matrix M.

M = [ s t ]
    [ 0 1 ]

i = [1]   j = [-2]   k = [0]
    [1]       [ 1]       [1]

 j     k  i
─┴──┴──┴──┴──┴─
-2 -1  0  1  2

当我们乘以 M 时,我们得到:

When we multiply by M, we get:

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  ]

因此,如果我们为 st 赋值,那么我们会在一维三角形"上得到各种变换.缩放会改变点"之间的距离,而纯平移会相对于原点移动它们,同时保持间距不变:

So if we assign values to s and t, then we get various transformations on our 1D 'triangle'. Scaling changes the distance between the 'points', while pure translation moves them around with respect to the origin while keeping the spacing constant:

   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

需要注意的是,转换的顺序很重要.这些 1D 变换会缩放并然后平移.如果您要先平移,那么点"与原点的距离将不同,因此缩放因子会对它产生不同的影响.出于这个原因,转换通常保存在单独的矩阵中,以便顺序清晰.

It's important to note that order of the transformations is critical. These 1D transformations scale and then translate. If you were to translate first, then the 'point' would be a different distance from the origin and so the scaling factor would affect it differently. For this reason, the transformations are often kept in separate matrices so that the order is clear.

如果我们向上移动到 2D,我们得到矩阵 N:

If we move up to 2D, we get matrix 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 ]

这个矩阵将1)sx,sy缩放一个点,2)将点绕原点旋转a 度,然后 3 将点转换为 tx,ty.请注意,此矩阵是在假设点表示为列向量并且乘法将作为 Np 发生的假设下构建的.正如 datenwolf 所说,如果您想使用点的行向量表示但应用相同的变换,则可以转置所有内容并交换顺序.这是矩阵乘法的一般性质:(AB)^T = (B^T)(A^T).

This matrix will 1) scale a point by sx,sy, 2) rotate the point around the origin by a degrees, and then 3 translate the point by tx,ty. Note that this matrix is constructed under the assumption that points are represented as column vectors and that the multiplication will take place as Np. As datenwolf said, if you want to use row vector representation of points but apply the same transformation, you can transpose everything and swap the order. This is a general property of matrix multiplication: (AB)^T = (B^T)(A^T).

也就是说,我们可以讨论对象、世界和眼睛坐标方面的变换.如果眼睛坐在世界的原点,向下看世界的负 z 轴,+x 向右,+y 向上,物体,一个立方体,位于向下 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 right(rt) 和眼睛的 y 向上> 并且眼睛的 -zlook(lk) 并且眼睛位于 [eyeright(ex) eyeup(ey) eyelook(ez)]^T.由于我们希望将对象坐标转换为眼睛坐标(意味着我们将眼睛视为原点),我们将取这些转换的逆并将它们应用于对象顶点(在它们转换为世界坐标之后).所以我们将有:

That said, we can talk about transformations in terms of object, world, and eye coordinates. If the eye is sitting at the origin of the world, looking down the world's negative z-axis, with +x to the right and +y up and the object, a cube, is sitting 10 units down -z (centered on the z axis), with width of 2 along the world's x, depth of 3 along the z, and height of 4 along world y. Then, if the center of the cube is the object's local frame of reference and its local axes conveniently align with the world's axes. Then the vertices of the box in object coordinates are the variations on [+/-1,+/-2,+/-1.5]^T. The near, top, right (from the eye's point-of-view) vertex has object coordinates [1,2,1.5]^T, in world coordinates, the same vertex is [1,2,-8.5]^T (1.5-10=-8.5). Because of where the eye is, which way it's pointing, and the fact that we define our eye the same way as OpenGL, that vertex has the same eye coordinates as world coordinates. So let's move and rotate the eye such that the eye's x is right(rt) and the eye's y is up and the eye's -z is look(lk) and the eye is positioned at [eyeright(ex) eyeup(ey) eyelook(ez)]^T. Since we want object coordinates transformed to eye coordinates (meaning that we'll treat the eye as the origin), we'll take the inverse of these transformations and apply them to the object vertices (after they have been transformed into world coordinates). So we'll have:

ep = [WORLD_TO_EYE]*[OBJECT_TO_WORLD]*wp;

更具体地说,对于我们感兴趣的顶点,我们将:

More specifically, for our vertex of interest, we'll have:

[ 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 ]

为方便起见,我将眼球旋转影响的平移分离出来.其实,写了这么多,这可能是混淆的点.您提供的矩阵将旋转然后平移.我假设眼睛的平移是在世界坐标中.但是正如您在问题中所写的那样,它实际上是在眼睛坐标中执行翻译.我也否定了 lk 因为我们已经定义了眼睛向下看负 z 轴,但是为了制作标准的旋转矩阵,我们想使用正值.

For convenience, I've separated out the translation the rotation of the eye affects it. Actually, now that I've written so much, this may be the point of confusion. The matrix that you gave will rotate and then translate. I assumed that the eye's translation was in world coordinates. But as you wrote it in your question, it's actually performing the translation in eye coordinates. I've also negated lk because we've defined the eye to be looking down the negative z-axis, but to make a standard rotation matrix, we want to use positive values.

无论如何,我可以继续,但也许这已经回答了你的问题.

Anyway, I can keep going, but maybe this answers your question already.

继续:

进一步解释上述内容,将眼睛的变换分成两个部分也可以更容易地找到逆.很容易看出,如果平移 tx 将眼睛相对于世界上的物体移动到某个地方,我们可以通过移动世界上的一切来保持眼睛和世界上的点之间相同的相对位置-tx 并保持眼睛静止.

Explaining the above a little further, separating the eye's transformation into two components also makes it much easier to find the inverse. It's easy to see that if translation tx moves the eye somewhere relative to the objects in the world, we can maintain the same relative positions between the eye and points in the world by moving the everything in the world by -tx and keeping the eye stationary.

同样,考虑由默认的rightuplook向量定义的眼睛方向:

Likewise, consider the eye's orientation as defined by its default right, up, and look vectors:

     [1]      [0]      [ 0]
d_rt=[0] d_up=[1] d_lk=[ 0]
     [0]      [0]      [-1]

创建一个将这三个向量指向新方向的旋转矩阵很容易.我们只是排列我们的三个新轴rtuplk(作为列向量):

Creating a rotation matrix that points these three vectors in a new direction is easy. We just line up our three new axes rt, up, lk (as column vectors):

[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]

很容易看出,如果你增加 d_rt、d_up 和 d_lk 并乘以上述矩阵,你会得到 rtuplk 分别返回.所以我们已经应用了我们想要的转换.要正确旋转,三个向量必须正交.这实际上只是基础的改变.由于这个事实,我们可以通过对其进行转置来非常方便地找到该矩阵的逆矩阵.这就是我上面所做的.如果将该转置矩阵应用于世界坐标中的所有点并保持眼睛静止,则这些点相对于眼睛将保持相同的位置,就好像眼睛已经旋转一样.

It's easy to see that if you augment d_rt, d_up, and d_lk and multiply by the above matrix, you get the rt, up, and lk back respectively. So we've applied the transformation that we wanted. To be a proper rotation, the three vectors must be orthonormal. This is really just a change of bases. Because of that fact, we can find the inverse of this matrix quite conveniently by taking its transpose. That's what I did above. If you apply that transposed matrix to all of the points in world coordinates and leave the eye still, the points will maintain the same position, relative to the eye, as if the eye had rotated.

例如:

分配(在世界坐标中):

Assign (in world coordinates):

   [ 0]    [0]    [-1]     [-2]     [1.5]
rt=[ 0] up=[1] lk=[ 0] eye=[ 0] obj=[ 0 ]
   [-1]    [0]    [ 0]     [ 1]     [-3 ]

这篇关于3D 图形处理 - 如何计算模型视图矩阵的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆