基于DirectX的灵活相机效果的实现

时间:2022-10-23 10:56:34

基于DirectX的灵活相机效果的实现

摘要:DirectX是由微软公司创立的多媒体编程接口。在DirectX中,世界中的物体经过世界变换,观察变换,投影变换最终渲染在屏幕上,本文主要论述在观察变换过程中,通过改变观察矩阵来实现不同的相机效果。

关键词:DirectX 观察矩阵 相机

中图分类号:TP3 文献标识码:A 文章编号:1007-9416(2012)11-0175-01

1、地球场景

目前我们在展示地理信息时,通常会在DirextX的世界空间中渲染一个球体,再在其表面叠加上DEM数据和高清影像数据,构成了一个地球场景,例如google earth。有了地球场景这个平台,对于地上的建筑,地表的道路,地下的矿山等等空间实体信息都可以在地球场景中进行展示。地球场景建立好以后,我们就需要设计一个相机类,来控制地球的缩放,旋转,俯仰等操作,使我们可以方便地从各个角度去观察渲染到地球场景上的物体。

2、三种操作

2.1 以世界中任意一点为中心进行缩放

为了实现以相机以任意一点为中心缩放的效果,需要两个过程,一是缩放,二是旋转。

首先进行缩放,缩放即改变相机的位置,使其沿着观察矩阵Z轴的方向向前或向后移动一段距离。假设当前的观察矩阵为ViewMatrix,当前的相机位置为CamPosition,

//定义相机移动的距离

Double length=10;

//定义观察矩阵的Z轴

Vector3 zAxis=new Vector3();

//定义相机移动后的位置

Vector3 TarPosition=new Vector3();

则计算过程为:

//从观察矩阵中提取Z轴

zAxis.X=ViewMatrix.M13;

zAxis.Y=ViewMatrix.M23;

zAxis.Z=ViewMatrix.M33;

zAxis.Normalize();

//计算新的相机位置

TarPosition=CamPosition+ length* zAxis;

最后再将TarPosition传入观察矩阵即完成了相机的缩放。如果缩放前鼠标位于地球上的A点,那么缩放后由于观察矩阵的变化,投影到屏幕上的地球会变大或变小,鼠标的位置会改变到B点,为了达到始终以A点为中心缩放的效果,需要将地球旋转一个角度,使鼠标位置的位置重新回到A点,于是我们需要进行第二步旋转。

旋转需要确定两个参数,一个是旋转轴,另一个是旋转角度。我们已知缩放前后鼠标在地球上的位置A和B,那么我们可以定义两个向量:

//向量a表示点A与地球球心构成的向量

Vector3 a=A-new Vector3(0,0,0);

//向量b表示点B与地球球心构成的向量

Vector3 b=B-new Vector3(0,0,0);

则旋转轴为:

//计算旋转轴,aXis由a和b的叉乘得到

Vector3 aXis=Vector3.Cross(a,b);

旋转角度为:

//计算旋转角度,为向量a与向量b的夹角

Double angle

=Math.Acos(Vector3.Dot(a,b)/a.norm()*b.norm());

旋转矩阵为:

Matrix m=Matrix.RotationAxis(aXis,-angle);

最后将m作用到缩放后的观察矩阵上就能实现始终以点A为中心进行缩放的效果。

2.2 以世界中任意一点为中心进行俯仰和旋转

当我们在地球表面加载一个物体,并希望以这个物体为中心进行观察时会需要用到本操作。假设物于世界中的点A(x,y,z),那么我们得可以出点A与地球球心O(0,0,0)的向量OA,因此我们可以构造一个绕OA旋转的旋转矩阵RotationMatrix,

// rotationAngle为旋转角度

Matrix rotationMatrix

=Matrix.RotationAxis(OA,rotationAngle);

将rotationMatrix作用到设备的观察矩阵上就能使相机绕着物体所在的OA轴旋转。要实现相机绕A点俯仰,需要三个步骤:

(1)使相机沿着OA轴的反方向移动OA的距离

Matrix m1=Matrix.Translation(-x,-y,-z);

(2)使相机绕观察矩阵的X轴旋转

//定义观察矩阵的X轴

Vector3 xAxis=new Vector3();

//从观察矩阵中提取Z轴

xAxis.X=ViewMatrix.M11;

xAxis.Y=ViewMatrix.M21;

xAxis.Z=ViewMatrix.M31;

xAxis.Normalize();

//tiltAngle为俯仰角度

Matrix m2=Matrix.RotationAxis(xAxis,tiltAngle);

(3)再使相机沿着OA轴的正方向移动OA的距离

Matrix m3=Matrix.Translation(x,y,z);

(4)将上面三个矩阵相乘得出俯仰矩阵

Matrix tiltMatrix=m1*m2*m3;

最后将tiltMatrix作用到观察矩阵上以实现俯仰效果。

3、结语

在进行三维场景漫游时,最基本的相机操作就是平移,缩放和旋转,本文介绍了一种缩放方式和两种旋转方式,这三种操作比较适合于球场景,因为三种操作的计算过程都以鼠标与球面的交点为基础。对于那些没有边界的开放空间,如地下,空中就并不合适,因此我们需要针对不同的目标场景开发出不同的操作方式以满足实际应用的需要。

上一篇:烟台数字化社区的发展之路 下一篇:基于MSP430F149和MMA7260的动作感应手柄设计