3D 图形处理 - 如何计算模型视图矩阵

2024-02-17

我无法理解从对象空间转换为视图空间的数学。我在硬件中执行此操作,并且我有下面的 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 代码不直接相关的内容,我只是想了解将点从对象坐标转换为眼睛坐标背后的数学原理。


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

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

M = [ s t ]
    [ 0 1 ]

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

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

当我们乘以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  ]

所以如果我们赋值给s and t,然后我们对一维“三角形”进行各种变换。缩放会改变“点”之间的距离,而纯平移会相对于原点移动它们,同时保持间距不变:

   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

值得注意的是,转换的顺序至关重要。这些一维变换规模和then翻译。如果您要先平移,那么“点”距原点的距离将不同,因此缩放因子会对它产生不同的影响。因此,变换通常保存在单独的矩阵中,以便顺序清晰。

如果我们上升到二维,我们得到矩阵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).

也就是说,我们可以讨论对象、世界和眼睛坐标方面的变换。如果眼睛位于世界的原点,向下看世界的负 z 轴,+x 向右,+y 向上,物体(一个立方体)位于向下 10 个单位 -z(以 z 为中心)轴),沿世界 x 的宽度为 2,沿 z 的深度为 3,沿世界 y 的高度为 4。然后,如果立方体的中心是对象的局部参考系,并且其局部轴可以方便地与世界轴对齐。那么物体坐标中盒子的顶点就是[+/-1,+/-2,+/-1.5]^T。近、上、右(从眼睛的角度来看)顶点有物体坐标 [1,2,1.5]^T, in 世界坐标,同一个顶点是[1,2,-8.5]^T(1.5-10=-8.5)。由于眼睛的位置、指向的方向,以及我们以与 OpenGL 相同的方式定义眼睛的事实,该顶点具有相同的眼睛坐标 as 世界坐标。因此,让我们移动并旋转眼睛,使眼睛x is 右(rt)和眼睛的y is up和眼睛的-z is look(lk)眼睛位于[eyeright(ex) eyeup(ey) eyelook(ez)]^T。由于我们希望将对象坐标转换为眼睛坐标(这意味着我们将眼睛视为原点),因此我们将取这些转换的逆并将它们应用到对象顶点(在它们转换为世界坐标之后)。所以我们会有:

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

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

[ 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 轴,但为了制作标准旋转矩阵,我们希望使用正值。

不管怎样,我可以继续下去,但这也许已经回答了你的问题。


继续:

进一步解释一下上面的内容,将眼睛的变换分成两个部分也使得找到逆矩阵变得更容易。很容易看出,如果翻译tx将眼睛相对于世界上的物体移动到某个位置,我们可以通过移动世界上的所有东西来保持眼睛和世界上的点之间相同的相对位置-tx并保持眼睛静止。

同样,考虑默认定义的眼睛方向right, up, and look向量:

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

创建一个将这三个向量指向新方向的旋转矩阵很容易。我们只需将三个新轴对齐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]

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


例如:

分配(在世界坐标中):

   [ 0]    [0]    [-1]     [-2]     [1.5]
rt=[ 0] up=[1] lk=[ 0] eye=[ 0] obj=[ 0 ]
   [-1]    [0]    [ 0]     [ 1]     [-3 ]
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

3D 图形处理 - 如何计算模型视图矩阵 的相关文章

  • 如何在给定目标大小的情况下在 python 中调整图像大小,同时保留纵横比?

    首先 我觉得这是一个愚蠢的问题 对此感到抱歉 目前 我发现计算最佳缩放因子 目标像素数的最佳宽度和高度 同时保留纵横比 的最准确方法是迭代并选择最佳缩放因子 但是必须有更好的方法来做到这一点 一个例子 import cv2 numpy as
  • 对齐坐标系

    Let s say I have 2 coordinate systems as it is shown in image attached 如何对齐这个坐标系 我知道我需要将第二个坐标系围绕 X 平移 180 度 然后将其平移到第一个坐标
  • Java中如何对整数除法进行四舍五入并得到int结果? [复制]

    这个问题在这里已经有答案了 我刚刚写了一个小方法来计算手机短信的页数 我没有选择使用Math ceil 老实说 它看起来很丑陋 这是我的代码 public class Main param args the command line arg
  • OpenGL 与 Eclipse CDT + MinGW + GLEW + GLFW:未定义的参考

    Edit 与此同时 我已经弄清楚了这一点 并在下面写了详细的答案 我刚刚尝试在 Win7 上从 Express 版本的 MSVC 10 切换到 Eclipse CDT 在配置时遇到了以下简单 OpenGL 代码的问题 在 Visual St
  • glBlitFramebuffer 渲染缓冲区和渲染全屏纹理哪个更快?

    哪个更快更高效 使用 OpenGL 纹理作为 CUDA 表面并在四边形上渲染 新样式 使用渲染缓冲区作为 CUDA 表面并使用 glBlitFramebuffer 进行渲染 None
  • Python 小数.InvalidOperation 错误

    当我运行这样的东西时 我总是收到此错误 from decimal import getcontext prec 30 b 2 3 Decimal b Error Traceback most recent call last File Te
  • 使用 OpenGL 着色器进行数学计算 (C++)

    我有一个矩阵 例如 100x100 尺寸 我需要对每个元素进行计算 matrix i j tt 8 5例如 我有一个巨大的矩阵 我想使用 OpenGL 着色器来实现该算法 我想使用着色器 例如 uniform float val unifo
  • 矩阵向量变换

    我正在编写一个代码来制作软件蒙皮器 骨骼 皮肤动画 并且我正处于 优化 阶段 蒙皮器工作得很好 并且在 Core 上 1 09 毫秒内对 4900 个三角形网格与 22 个骨骼进行蒙皮Duo 2 Ghz 笔记本 我需要知道的是 1 有人可以
  • 如果我用opengl绘图的话SDL Renderer就没用了吗?

    我正在学习 SDL2 但我也在使用使用 OpenGL 调用的 imgui 库 从我在网上各种博客上读到的内容来看 我无法轻松混合 SDL2 渲染器和 opengl 调用 我要么使用其中之一 要么使用另一个 我读过的大多数教程都使用渲染器 所
  • 如何安全地将 CGFloat 降低或提高到 int?

    我经常需要在地板或天花板上安装CGFloat to an int 用于计算数组索引 我永远看到的问题floorf theCGFloat or ceilf theCGFloat 是浮点不准确可能会带来麻烦 那如果我的CGFloat is 2
  • 无法在 WSL2 上运行 OpenGL

    我尝试在 WSL2 上运行 OpenGL 代码 但在尝试运行可执行文件时出现以下错误 GLFW error 65543 GLX Failed to create context GLXBadFBConfig Unable to create
  • 如何将一组重叠范围划分为不重叠范围?

    假设您有一组范围 0 100 一 0 75 b 95 150 c 120 130 d 显然 这些范围在某些点上重叠 您将如何剖析这些范围以生成不重叠范围的列表 同时保留与其原始范围相关的信息 在本例中为范围后面的字母 例如 运行算法后的上述
  • 使用 Scipy/Numpy 在浊点的二维插值中仅获取“有效”点

    我有一个通过人的背部摄影测量获得的浊点 我正在尝试对其进行插值以获得规则网格 为此我正在使用scipy interpolate到目前为止取得了良好的成果 问题是 我正在使用的函数 scipy interpolate griddata 使用平
  • 预乘 Alpha 合成

    我正在尝试实现预乘阿尔法混合 在本页 什么是颜色混合 https learn microsoft com en us previous versions windows xna bb976070 v xnagamestudio 41 它们确
  • 两组数的最小公等和及组合

    我目前正在用 C 创建一个程序 该程序将查找两组数字的尽可能低的相等总和 您可以在其中根据需要多次重复这些数字 比如我有这两套 10 13 18 and 12 16 22 我能得到的最低金额是28 10 18 and 12 16 另一个例子
  • 这个按位运算如何检查 2 的幂?

    我正在看一些应该很简单的代码 但我的数学在这里严重失败 下面是一个使用以下条件检查数字是否为 2 的幂的条件 if num 1 num num 1 make num pow of 2 我的问题是 如何在 num 和 num 1 之间使用按位
  • 在 Linux 上运行我自己的程序的权限被拒绝? [关闭]

    Closed 这个问题不符合堆栈溢出指南 help closed questions 目前不接受答案 我有Ubuntu 9 4 我已经构建了程序 一些基本的 OpenGL 该程序只是制作一个旋转的正方形 然后运行它并 sh blabla p
  • 计算两点之间的最短路线

    过去几周我一直在开发一款多人 HTML5 游戏 使用nodejs and websockets 我已经被这个问题困扰了一段时间 想象一下 我用数组实现了这个平铺地图 如下所示 1 or 棕色瓷砖 路上有障碍物 玩家无法通过 0 or 绿色瓷
  • Visual Studio 2010 中的 SOIL 设置

    我无法得到SOIL http www lonesock net soil html正确使用 Visual Studio 2010 我远非 VS 专家 但据我所知 只需执行以下步骤即可使环境正常运行 属性 gt gt C C gt 常规 gt
  • 有 JavaScript 的微积分库吗? [关闭]

    Closed 此问题正在寻求书籍 工具 软件库等的推荐 不满足堆栈溢出指南 help closed questions 目前不接受答案 有人知道 JavaScript 的微积分库吗 我做了一些谷歌搜索 但没有想出任何东西 我申请了 Wolf

随机推荐