3D 图形处理 - 如何计算模型视图矩阵
我无法理解从对象空间转换为视图空间的数学。我在硬件中执行此操作,并且我有下面的 Atranspose 矩阵:
ATranspose =
[rightx upx lookx 0]
[righty upy looky 0]
[rightz upz lookz 0]
[-eyeright -eyeup -eyelook 1]
然后找到我们要做的点:
[x,y,z,1] = [x',y',z',1]*ATranspose
xnew = xold*rightx + xold*righty + xold*rightz + xold*(-eyeright)
但我不确定这是否正确。
也可能
[x,y,z,1]=atranspose*[x',y',z',1]T
有人可以向我解释一下吗?我在网上找不到任何与 opengl 代码不直接相关的内容,我只是想了解将点从对象坐标转换为眼睛坐标背后的数学原理。
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 =
[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.
It could also be
[x,y,z,1]=atranspose*[x',y',z',1]T
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.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这个答案可能比需要的要长得多。如果您已经了解了大部分矩阵数学,请跳至底部 2 段左右。
从查看一维问题开始可能是最简单的。在一维中,我们在一条线上有点。我们可以缩放它们或者翻译它们。考虑三个点i,j,k和变换矩阵M。
当我们乘以 M 时,我们得到:
因此,如果我们将值分配给 s 和 t,那么我们会在 1D 三角形上得到各种变换'。缩放会改变“点”之间的距离,而纯平移会相对于原点移动它们,同时保持间距不变:
值得注意的是,变换的顺序至关重要。这些一维变换先进行缩放,然后进行平移。如果您要先平移,那么“点”与原点的距离将不同,因此缩放因子会对它产生不同的影响。因此,变换通常保存在单独的矩阵中,以便顺序清晰。
如果我们移动到二维,我们得到矩阵N:
该矩阵将1)将点缩放sx,sy,2 ) 将点绕原点旋转 a 度,然后 3 将点平移 tx,ty。请注意,该矩阵是在以下假设下构建的:点表示为列向量,并且乘法将以 Np 形式进行。正如 datenwolf 所说,如果您想使用点的行向量表示但应用相同的变换,您可以转置所有内容并交换顺序。这是矩阵乘法的一般性质:(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 位于右(rt),并且眼睛的 y 位于上 > 眼睛的 -z 是 look(lk) 并且眼睛位于[eyeright(ex) eyeup(ey) eyelook(ez)]^T
。由于我们希望将对象坐标转换为眼睛坐标(这意味着我们将眼睛视为原点),因此我们将取这些转换的逆并将它们应用到对象顶点(在它们转换为世界坐标之后)。因此,我们将:更具体地说,对于我们感兴趣的顶点,我们将:
为方便起见,我将眼睛旋转影响它的平移分开。其实写了这么多,可能这就是我比较困惑的地方。您给出的矩阵将旋转然后平移。我假设眼睛的平移是在世界坐标中。但正如您在问题中所写的那样,它实际上是在眼睛坐标中执行翻译。我还否定了lk,因为我们将眼睛定义为向下看负 z 轴,但为了制作标准旋转矩阵,我们希望使用正值。
不管怎样,我可以继续下去,但这也许已经回答了你的问题。
继续:
进一步解释一下上面的内容,将眼睛的变换分成两个部分也使得找到逆矩阵变得更容易。很容易看出,如果平移tx将眼睛相对于世界上的物体移动到某个位置,我们可以通过移动世界上的所有东西来保持眼睛和世界上的点之间相同的相对位置-tx 并保持眼睛静止。
同样,考虑由其默认的 right、up 和 look 向量定义的眼睛方向:
创建一个旋转矩阵,将这三个向量指向一个新的方向很容易。我们只需将三个新轴 rt、up、lk (作为列向量)排列起来:
很容易看出,如果您增强 d_rt, d_up 和 d_lk 并乘以上面的矩阵,分别得到 rt、up 和 lk。所以我们已经应用了我们想要的转换。为了实现正确的旋转,三个向量必须正交。这实际上只是基础的改变。因此,我们可以通过转置该矩阵来非常方便地找到该矩阵的逆矩阵。这就是我上面所做的。如果将该转置矩阵应用于世界坐标中的所有点并使眼睛保持静止,则这些点将相对于眼睛保持相同的位置,就好像眼睛旋转了一样。
例如:
分配(在世界坐标中):
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.
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.
When we multiply by M, we get:
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:
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.
If we move up to 2D, we get matrix N:
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).
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:More specifically, for our vertex of interest, we'll have:
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.
Continuing:
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.
Likewise, consider the eye's orientation as defined by its default right, up, and look vectors:
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):
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.
For Example:
Assign (in world coordinates):
如果您在第二个变体中转置 ATranspose,即
顺便说一句,
^T
表示转置,因此原作者可能意味着并重写
,那么所有这些公式都同样正确。
If you transpose ATranspose in the second variant, i.e.
BTW,
^T
means transpose so the original author probably meantand rewritten
then all these formulations are equally correct.