设计一个灵活的Camera类
来源:互联网 发布:郝斌c语言 编辑:程序博客网 时间:2024/04/30 05:36
设计一个灵活的Camera类
1.Camera类的设计
我们用4个摄像机向量:右向量(right vector)、上向量(up vector)、观察向量(look vector)以及位置向量(position vector)来定义摄像机相对于世界坐标系的位置和朝向。这些向量实质上为相对世界坐标系描述的摄像机定义了一个局部坐标系。由于右向量、上向量和观察向量定义了摄像机在世界坐标系中的朝向,有时我们也将这三个向量统称为方向向量。方向向量必须是标准正交的。如果一个向量集中的向量都彼此正交,且模为1,则称为标准正交。
用上述4个向量来描述摄像机,我们可以对摄像机实施如下6种变换:
² 绕向量right的旋转(俯仰,pitch)
² 绕向量up的旋转(偏航,yaw)
² 绕向量look的旋转(滚动,roll)
² 沿向量right方向的扫视(strafe)
² 沿向量up方向的升降(fly)
² 沿向量look方向的平动
我们的摄像机支持两种摄像机模型——LANDOBJECT模型和AIRCRAFT模型。AIRCRAFT模型允许摄像机在空间自由运动,具有6个自由度。但是在某些游戏中,射击者是不可能飞行的。所以我们必须限制射击者只能沿某些特定轴进行移动。如果将摄像机类型指定为LANDOBJECT,便自动满足了上述约束。
2.实现细节
1) 观察矩阵(取景变换矩阵,View Matrix)的计算
令向量p = (px, py, pz)、r = (rx, ry, rz)、u = (ux, uy, uz)、d = (dx, dy, dz)分别表示position, right, up和look这4个向量。
取景变化所解决的问题就是世界坐标系中的物体在以摄像机为中心的坐标系中如何进行描述。等价于将世界坐标系中的物体随摄像机一起进行变换,以使摄像机坐标系与世界坐标系完全重合。
所以我们希望变换矩阵V能够实现:
l pV = (0, 0, 0) 矩阵V将摄像机移至世界坐标系的原点。
l rV = (1, 0, 0) 矩阵V将摄像机的right向量与世界坐标系的x轴重合。
l uV = (0, 1, 0) 矩阵V将摄像机的up向量与世界坐标系的y轴重合。
l dV = (0, 0, 1) 矩阵V使摄像机的look向量与世界坐标系的z轴重合。
这样我们就可以将计算这种矩阵的任务分为两步:首先将摄像机平移到世界坐标系的原点;然后通过旋转变换使摄像机各向量与世界坐标系对应各轴重合。
第一步:平移
将摄像机的位置向量p平移到原点可通过将其与向量-p做向量加法实现,因为p-p=0。所以我们可以用如下矩阵来描述取景变换中的平移变换部分。
第二步:旋转
要想使摄像机各向量与世界坐标系各轴重合的工作量稍大一些。我们需要一个3 * 3的旋转矩阵A以使向量right、up和look分别与世界坐标系的x, y, z轴重合。该矩阵需要满足如下3个方程:
注意:我们这里使用的是3 * 3矩阵,因为我们不需要用齐次坐标来表示旋转。
由于这3个方程组都具有相同的系数矩阵A,联立之后我们可立即解出矩阵A。我们将上述3个方程组整合为:
矩阵A有多种求解方法,但是我们可以立即看出A其实是B的逆矩阵。由于矩阵B是标准正交矩阵,所以其逆矩阵与其转置矩阵相等。所以,使摄像机各轴与世界坐标系各轴重合的变换可用如下矩阵表示:
前两步的整合
最后,将A拓展为4 * 4矩阵,并将其取景变换的前两步整合,得到完整的观察矩阵V。
2) 绕任意轴的旋转
实现摄像机的旋转方法时,我们应使得能够绕任意轴进行旋转。D3DX库提供了如下函数实现该功能:
D3DXMATRIX *D3DXMatrixRotationAxis(
D3DXMATRIX *pOut, //returns rotation matrix
CONST D3DXVECTOR3 *pV, //axis to rotate around
FLOAT Angle //angle, in radians, to ratate
);
3) 俯仰、偏航和滚动
由于方向向量描述了摄像机在世界坐标系中的朝向,所以当摄像机发生俯仰、偏航或滚动时,我们必须指定方向向量应如何更新。下面几个图分别展示了这几种情况:
从图中可以知道,摄像机发生俯仰时,我们需要将向量up和look绕着向量right转动指定的角度。类似的,发生偏航时,我们需要将向量look和right绕着向量up转动指定的角度;发生翻滚时,我们需要将向量right和up绕着向量look转动指定的角度。
4) 行走、扫视和升降
这里的“行走”是指沿着摄像机的观察方向(look方向)的平动。“扫视”是指保持观察方向不变,沿向量right方向从一边平移到另一边。“升降”是沿着向量up方向的平动。为了能够沿这些轴中的任意一个进行平动,我们只需要将摄像机当前位置和一个与该轴方向相同的向量相加即可。
- 设计一个灵活的Camera类
- opengl构造一个灵活的camera
- 灵活Camera类
- 一个灵活的打印控制
- 构建一个灵活的用户界面
- 个人封装的一个Camera类
- 一个简单的camera管理类
- c++类设计--灵活的构造函数和虚函数
- 一个简单而又灵活的数据库操作类
- 利用JDOM写一个较为灵活的JDBC工具类
- onScreenHint,一个比toast更加灵活的提示类
- 《设计模式解析》第3章 一个迫切需要灵活代码的问题
- 设计模式精解-第三章-一个急需灵活代码的问题
- 《设计模式解析》第3章 一个迫切需要灵活代码的问题
- 设计一个(安全、通用、灵活、可扩展)的用户登录系统
- Javascript设计模式 -- 灵活的javascript
- [转贴] 一个灵活的索引工具
- 一个非常灵活的ODBC编程方法
- Eclipse 常用快捷键
- 如何避免协同办公系统在维护过程中误删数据库和文档
- SQL Pretty Printer V3.12绿色破解版
- C# 线程用法总结
- Windows自带的小巧的调试利器(转)
- 设计一个灵活的Camera类
- Linux 下文件操作
- POJ 1143 Number Game
- 排序算法总结
- SQL Pretty Printer 破解版
- workbench
- 自动生成.NET项目帮助生成
- Android开发之android命令大全
- 100个最常见Linux守护进程简介