Web 技术研究所

我一直坚信着,Web 将会成为未来应用程序的主流

视图矩阵(View Matrix)的推导

  前面两篇已经把旋转都说完了,还冒出个视图矩阵的推导是不是觉得有些内容重复了?一点都不重复,虽然视图矩阵确实是由各种旋转的叠加而成的,那它到底都做了那些旋转呢?我们要如何通过几个参数来生成一个视图矩阵呢?这些就是这篇文章要说的。
  视图矩阵就是觉得摄像机属性的矩阵吧?但是,决定摄像机的属性都有哪些呢?摄像机可以移动,所以有了移动属性。在固定位置时可以摇动摄像机来旋转镜头朝向,这是镜头朝向属性。而且即使位置和镜头朝向都固定了,它还可以自传。自传可以看作是摄像机顶部的朝向在改变,所以是顶部朝向属性。需要三个向量才能决定一个摄像机的所有属性,或者说在生成视图矩阵时需要用到这三个参数。
  其实根据这些资料可以就推导出一个很简单的矩阵。首先,我们知道默认的视线方向是(0,0,-1),除此之外我们还只有默认的上方向是(0,1,0),还有我们的右边是x轴的增加方向是(1,0,0)。现在,我要把这三个坐标变换到视线方向(Fx,Fy,Fz)、上方向(Ux,Uy,Uz)和右方向(Rx,Ry,Rz)上。也就是需要一个矩阵能同时把那三个初始向量变换到我们给定的向量上去。我们把这些向量写成矩阵的形式更容易理解。
M ×
{ 100 }
010
00-1
=
{ RxUxFx }
RyUyFy
RzUzFz
  现在需要找到一个矩阵M来把原矩阵变换成等号右边的矩阵。这很容易吧?因为我们给原矩阵的定义几乎的单位矩阵一样了,只是在zz的位置多了个负号而已。很容易就可以得出
M =
{ RxUx-Fx }
RyUy-Fy
RzUz-Fz
  R、U、F,都是表示方向的,通常都用单位向量。而且这三个向量在三维空间中互相垂直,所以,只要有其中两个向量,做叉积就能得出第三个。比如我前面说的已知条件中有视线方向和上方向,缺少右方向。那么只有对F和U做叉积就可以得到R,不过要注意我们对初始方向向量定义时xyz是左手坐标系的,所以做叉积时也要注意左手坐标系。
R = F×U =
| ijk |
FxFyFz
UxUyUz
= (FyUz-FzUy,FzUx-FxUz,FxUy-FyUx)
  M就是我们的旋转矩阵,虽然你看不到三角函数。如果你已知的是角度,把角度用三角函数换算成坐标再使用这个矩阵就都是三角函数了。不过如果已经有了旋转角度,就别再使用这个方法了。因为方向参数必须是垂直的向量,这个我们不太容易保证,如果不垂直就会造成变换的扭曲。很多封装的视图矩阵会多一个处理的过程,就是对这些参数多做几次叉积,让它们永远垂直。不过那种做法也有很大局限性。叉积虽然可以保证垂直,但是对两条平行的向量做叉积会得到零向量,这就没办法计算了。所以这个方法无法让摄像机朝向某些角度。
  其实还可以这样理解。把初始视线向量和相关的几个向量看作刚体的几个顶点。这些单位向量永远都是互相垂直的,它们不能缩放和扭曲,这样就具有了刚体性质。我们可以用对刚体的它操作来操作它,这个方法就是普通的变换矩阵而已,我就不拿出例子了。
  最后是平移的操作。上面的计算只有旋转,我们还需要把它平移到目标位置(Px,Py,Pz)。这个操作在WebGL摄像机操作那篇中就说过了,虽然逻辑上是对视线方向的变换,但实际上是操作整个世界的坐标,所以它的操作是相反的。摄像机往正方向移动就意味着整个世界的坐标都往负方向移动。而且,对于平移和旋转是先平移后旋转,这也是和普通的变换矩阵相反的。因为世界坐标要绕着摄像机旋转,而不是原来的原点了。
vMatrix = T×M =
{ 1000 }
0100
0010
-Px-Py-Pz1
×
{ RxUx-Fx0 }
RyUy-Fy0
RzUz-Fz0
0001
vMatrix =
{ RxUx-Fx0 }
RyUy-Fy0
RzUz-Fz0
-P·R-P·UP·F1
  这个矩阵的推导方式也不止一种啦,得到的最终矩阵也未必相同的。总之它是不固定的,使用哪种推导过程要根据你的已知参数是什么来决定。不过很多库都有封装成类,而不是单一的函数。如果要开发3D项目,这个类是必封装的东西,要不然代码会凌乱死。
网名:
52.91.185.*
电子邮箱:
仅用于接收通知
提交 悄悄的告诉你,Ctrl+Enter 可以提交哦
神奇海螺
[查看全部主题]
各类Web技术问题讨论区
发起新主题
本模块采用即时聊天邮件通知的模式
让钛合金F5成为历史吧!
次碳酸钴的技术博客,文章原创,转载请保留原文链接 ^_^