View Transform(视图变换)详解
http://www.cnblogs.com/graphics/archive/2012/07/12/2476413.html
什么是View Transform
我们可以用照相机的原理来阐释3D图形的绘制过程,想象一下,我们在摄影的时候都需要做哪些工作,大致可分为如下几个步骤
- 摆放好待拍摄的物品,或者人物。
- 调整好拍摄角度。
- 调整焦距。
- 拍摄。
好了,来分析一下,上面的第一步就相当于世界变换了,将一个模型置于一个公认的坐标系中,这里所谓的公认,也就是大家都遵守的,目的是保证待拍摄的物体和照相机在同一个坐标系。第二步相当于视图变换,这个过程是调整Camera到合适的位置以便拍摄,在3D程序中,也就是设置View Matrix了。第三步调整焦距,这就相当于3D编程中的投影变换。
View Transform的过程就是在世界坐标系中摆放Camera的过程,并将顶点由世界坐标系转换到Camera Space,在Camera Space中,观察者(Camera)位于坐标原点,观察方向指向Z轴正方向。
为什么要进行View Transform?
在world space中,camera并不一定位于坐标原点,并且观察方向不一定指向Z轴正方向,对于投影变换及其他的一些操作来说,如果不满足这两个条件,后续的的操作就会变得非常低效,所以为了提高效率,我们需要进行view transform。
View Transform的作用
View Transform主要有下面两个作用。
- 移动camera,使其位于world space的坐标原点
- 旋转camera,使其朝向z轴正方向,也就是视线由原点指向z轴正方向。
这两个过程,前一个实际上是平移,后一个实际上是旋转。你可以想象成Camera也有三个坐标轴x,y,z,视图变换的过程就是将Camera的坐标轴与世界坐标系的坐标轴对齐的过程。
注意:view transform中,所有位于world space中的models都随着camera一起变换,所以视野并未发生变化,具体过程见下图

如何求解View Matrix?
使用D3D函数
使用下面的D3D函数可以计算view matrix,第一个参数是输出参数,返回求得的视图矩阵,第二个参数是眼睛的位置,第三个参数是观察点中心,最后一个参数是向上向量。该函数的最后两个字母表示左手系(Left Hand)。
D3DXMatrixLookAtLH(&M, &eyePt, &lookCenter, &upVec) ;
手动求解
手动求解View matrix并不是难事,一个camera一般有如下四个属性,
- 向前向量(direction),相当于Z轴
- 向上向量(up vector),相当于Y轴
- 向右向量(right vector),相当于X轴
- 位置(position)
其中前三个向量要求是相互垂直的。假设我们分别用d, u, v和p来表示这四个变量。并假设待求的视图矩阵为V,根据前面的介绍我们知道,V的作用就是将摄像机移动到原点,并将摄像机的三个向量分别与坐标轴对齐,d与z轴正方向对齐,u与y轴正方向对齐,r与x轴正方向对齐。假设将摄像机与坐标轴对齐的矩阵为V,那么V的推导过程如下。



通常在实际的编程中,只会给出如下三个量。至于d和r这两个量,只能通过计算求得。
- 摄像机(眼睛)的位置(eye point),相当于p
- 观察点中心(look at),假设为向量c
- 向上向量(up vector),相当于u
可以通过下面方法求得d, r和u。
- d = c - p,下面第一幅图
- r = d x u,下面第二幅图
- u = r x d,下面第三幅图



注意上面的x是叉积运算(cross product),现在p,d,r,u四个量都已经知道,于是就可以根据上面的矩阵M求得视图变换矩阵了,对应的代码如下。该函数有三个参数,分别是摄像机位置p,向上向量u和视点中心lookAt。

D3DXMATRIX buildViewMatrix(D3DXVECTOR3& p, D3DXVECTOR3& u, D3DXVECTOR3& lookAt)
{
// Calculate d
D3DXVECTOR3 d = lookAt - p;
D3DXVec3Normalize(&d, &d); // Calculate r
D3DXVECTOR3 r;
D3DXVec3Cross(&r, &u, &d);
D3DXVec3Normalize(&r, &r); // Calculate up
D3DXVec3Cross(&u, &r, &d);
D3DXVec3Normalize(&u, &u); // Fill in the view matrix entries.
float x = -D3DXVec3Dot(&p, &r);
float y = -D3DXVec3Dot(&p, &u);
float z = -D3DXVec3Dot(&p, &d); D3DXMATRIX M;
M(0,0) = r.x;
M(1,0) = r.y;
M(2,0) = r.z;
M(3,0) = x; M(0,1) = u.x;
M(1,1) = u.y;
M(2,1) = u.z;
M(3,1) = y; M(0,2) = d.x;
M(1,2) = d.y;
M(2,2) = d.z;
M(3,2) = z; M(0,3) = 0.0f;
M(1,3) = 0.0f;
M(2,3) = 0.0f;
M(3,3) = 1.0f; return M;
}

注意事项,在求取View Matrix的时候有几点是需要注意的:
- 叉积满足右手法则。
- 叉积不满足交换律。 a x b = - b x a
- DirectX使用左手系,满足左手法则。
只要最终求得的三个向量,up, right和d满足左手法则即可。如果应用了View Matrix之后发现模型左右或者上下颠倒了,那么就说明求取的时候没有满足左手系。
好了,矩阵求解完毕,赶快使用SetTransform(D3DTS_VIEW, &M) ;来试试吧,效果和使用函数D3DXMatrixLookAtLH是一样的!
Happy Coding!!!
我们看DX9帮助文档中,D3DXMatrixLookAtLH函数的计算公式也是这样的:
zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)
xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
唯一的不同就是D3DXMatrixLookAtLH的函数参数只有四个,即摄像机位置Eye、摄像机朝向At、摄像机上向量Up,通过简单的运算就可以转换成我们上面所说的那四个描述量了,在这里就不赘言了。
View Transform(视图变换)详解的更多相关文章
- 第98天:CSS3中transform变换详解
transform变换详解 本文主要介绍变形transform. Transform字面上就是变形,改变的意思.在CSS3中transform主要包括以下几种:旋转rotate.扭曲skew.缩放sc ...
- 【转载】D3DXMatrixLookAtLH视图变换函数详解
原文:D3DXMatrixLookAtLH视图变换函数详解 /*D3DXMatrixLookAtLH函数返回的是世界->视图变换矩阵. 视图坐标系和局部坐标系是一样的,都是世界坐标系转换为指定的 ...
- ThinkPHP视图查询详解
ThinkPHP视图查询详解 参考http://www.jb51.net/article/51674.htm 这篇文章主要介绍了ThinkPHP视图查询,需要的朋友可以参考下 ThinkP ...
- Android 通过Java代码生成创建界面。动态生成View,动态设置View属性。addRules详解
废话不多说,本文将会层层深入给大家讲解如何动态的生成一个完整的界面. 本文内容: Java代码中动态生成View Java代码中动态设置View的位置,以及其他的属性 LayoutParams详解 一 ...
- matlab-霍夫变换详解(判断正方形长方形)
霍夫变换 霍夫变换是1972年提出来的,最开始就是用来在图像中过检测直线,后来扩展能检测圆.曲线等. 直线的霍夫变换就是 把xy空间的直线 换成成 另一空间的点.就是直线和点的互换. 我们在初中数学中 ...
- 新版本Xcode 6的视图调试详解
开发者会经常遇到视图或者Auto Layout约束中存在bug的情况,并且这种bug很难通过代码发现,所以开发者很有必要熟知如何进行简单高效的视图调试,而Xcode 6的发布使得视图调试变得前所未有的 ...
- 【OpenGL】法线变换详解(Normal Transform)[转]
http://blog.csdn.net/xiajun07061225/article/details/7762711 在图形学中,同样的一个模型视图变换矩阵可以用来变换点.线.多边形以及其它几何体, ...
- SpringMVC视图机制详解[附带源码分析]
目录 前言 重要接口和类介绍 源码分析 编码自定义的ViewResolver 总结 参考资料 前言 SpringMVC是目前主流的Web MVC框架之一. 如果有同学对它不熟悉,那么请参考它的入门bl ...
- Cocoa编程中视图控制器与视图类详解
iPhone编程规则是:一个窗口,多个视图.UIView是iPhone屏幕上很多控件的基础类.每个iPhone用户界面都是由显示在UIWindow(这其实也是个特殊的UIView)内的众多UIView ...
- Android 自定义View修炼-Android开发之自定义View开发及实例详解
在开发Android应用的过程中,难免需要自定义View,其实自定义View不难,只要了解原理,实现起来就没有那么难. 其主要原理就是继承View,重写构造方法.onDraw,(onMeasure)等 ...
随机推荐
- __cdecl __stdcall __fastcall之函数调用约定讲解
首先讲解一下栈帧的概念: 从逻辑上讲,栈帧就是一个函数执行的环境:函数参数.函数的局部变量.函数执行完后返回到哪里等等. 实现上有硬件方式和软件方式(有些体系不支持硬件栈) 首先应该明白,栈是从高地址 ...
- .NET设计模式(16):模版方法(Template Method)(转)
摘要:Template Method模式是比较简单的设计模式之一,但它却是代码复用的一项基本的技术,在类库中尤其重要. 主要内容 1.概述 2.Template Method解说 3..NET中的Te ...
- 不定义JQuery插件,不要说会JQuery
转自:http://www.cnblogs.com/xcj26/p/3345556.html 一:导言 有些WEB开发者,会引用一个JQuery类库,然后在网页上写一写$("#") ...
- winform中的时间轴控件
我现在做的项目遇到一个需求,就是有没有类似的控件: 我要实现的功能是:播放录像. 某个时间段内假如有2个录像,这个坐标表示的是时间,假如我现在拖动时间轴,拖到第一个录像里面开始播放第一个录像,拖到2个 ...
- 算术编码Arithmetic Coding-高质量代码实现详解
关于算术编码的具体讲解我不多细说,本文按照下述三个部分构成. 两个例子分别说明怎么用算数编码进行编码以及解码(来源:ARITHMETIC CODING FOR DATA COIUPRESSION): ...
- UITextField中文搜索
导入头文件 #import "ChineseInclude.h"#import "PinYinForObjc.h" NSMutableArray *search ...
- strrchr函数
C语言函数 函数简介 函数名称: strrchr 函数原型:char *strrchr(char *str, char c); 所属库: string.h 函数功能:查找一个字符c在另一个字符串str ...
- js的正则表达式
正则表达式(regular expression)是一中描述字符模式的对象,js的RegExp类表示正则表达式,String与RegExp都定义了相应的方法来操作正则表达式,比如模式匹配,文本检索和替 ...
- 初学Ajax(三)
$.ajax() $.ajax()是所有ajax方法中最底层的方法,所有其他方法都是基于$.ajax()方法的封装.这个方法只有一个参数,传递一个各个功能键值对的对象. $.ajax()方法对象参数表 ...
- 使用jmeter对websocket进行压力测试[转载]
前段时间本着练习angularJS+requireJS的目的写了一个基于nodeJS和socket.io的聊天室,github地址为:https://github.com/towersxu/node- ...