Direct3D学习笔记(二)——顶点坐标变换
2008-07-23 14:24 libiver 阅读(1036) 评论(0) 编辑 收藏 举报
Direct3D学习笔记(二)——顶点坐标变换
在Direct3D中,一个三维物体是被分成许许多多的三角形面来表示,而且是需要使用三维坐标来描述,但实际上显示器是一个二维表面,所以要想在二维显示器上显示三维物体就必须先将空间物体的三维坐标转换为二维坐标。
在Direct3D中有四种坐标,分别为
1、 世界坐标系
三维物体被划分为众多的三角形面表示后,物体表面的图行方位可以通过三角形面的顶点来确定,而为了从数值上定量三维图形的方位数据,需要引入一个世界坐标系(Direct3D中使用的是笛卡尔左手坐标系),这样就可以准确地用一个坐标(x,y,z)来定位,以实现图形到数据的转换。
世界坐标系是Direct3D中的一个最基本的坐标系,观察坐标系等都是以它为基准。三维物体在场景中通常是以一个中心点作为远点建立自己的坐标系,而这种坐标系就是世界坐标系中的局部坐标系。三维物体在三维空间的运动和变形的过程称为世界变换,这些过程包括平移,旋转,缩放等。而这个物体运动的三维空间也即是世界空间。
从上面就可以看出世界坐标系的作用就是对世界空间中三维物体的一个统一标量,保证其中所有的三维物体都能够映射到一个统一的坐标系中,方便处理。
上面操作就是将一个三维物体设置到一个世界坐标系的过程,也即是实现三维物体从本地坐标系到世界坐标系的转换。它先利用D3DXMatrixIdentity函数将世界坐标系矩阵单位化,再通过函数D3DXMatrixIdentity矩阵将物体分别X轴、Y轴平移2.5f单位,最后调用D3DXMatrixScaling将物体在X轴和Y轴上缩放fAngle / 3.0f倍。设置完成后调用SetTransform设置顶点变换矩阵,具体函数参数说明可以查阅文档。
2、 观察坐标系
由于三维场景是无限的,但计算机屏幕是有限的空间,一次不可能将全部无限的场景显示在显示屏上,所以在显示的时候要进行取舍,也就是裁剪,决定那些显示,那些不需要显示。为了完成这个操作,在世界坐标系中引入一个观察者来确定显示区域,而这个观察者可以理解为是一台摄像机或者照相机什么的。这样就产生了一个观察空间,在观察空间中建立的坐标系就是观察坐标系(也叫摄影坐标系),将世界坐标系中的顶点变换到观察坐标系的操作就是观察变换(也叫取景变换)。在这个摄影空间中,观察者或者摄像机位于坐标原点,向着Z轴方向。
函数D3DXMatrixLookAtLH可以建立一个左手笛卡尔三维观察坐标系。
3、 投影坐标系
在设置了观察坐标系中的摄像机的位置和方向后,就要将处于摄像机摄影空间中的三维物体投影到二维的胶片上,也即是Direct3D中的屏幕。这种变换就是取景空间到投影空间的变换,相应的坐标系就是投影坐标系。投影变换比较复杂,它分为两种变换:正交变换和透视变换。它们的区别是正交变换的取景截头体是个长方体,而透视变换的取景截头体(viewing frusturn)是棱台体。使用透视变换得到的三维物体比较符合人们的观察习惯。
D3DXMATRIX * D3DXMatrixOrthoLH(//正交透视
D3DXMATRIX *pOut,//生成的正交投影矩阵
FLOAT w, //取景长方体的宽度
FLOAT h, //取景长方体的高度
FLOAT zn, //取景长方体离摄像机的最近距离
FLOAT zf //取景长方体离摄像机的最远距离
);
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(//透视投影
D3DXMATRIX *pOut,//生成的透视投影矩阵
FLOAT fovy, //摄像机在Y轴上的程序角度(弧度)
FLOAT Aspect, //取景棱台体的纵横比
FLOAT zn, //取景棱台体离摄像机的最近距离
FLOAT zf //取景棱台体离摄像机的最远距离
);
4、 屏幕坐标系
物体在投影坐标系表示的为浮点坐标,而显示屏的显示区域是以像素为单位的整形坐标,将浮点坐标变换到整形坐标的过程就是视区变换,相应的坐标系就是屏幕坐标系。结构体D3DVIEWPORT9定义了视区参数,结构体如下:
typedef struct D3DVIEWPORT9 {
DWORD X; //视区左上角X轴坐标
DWORD Y; //视区左上角Y轴坐标
DWORD Width; //视区宽度
DWORD Height; //视区高度
float MinZ; //视区内景物的最小深度,
float MaxZ; //视区内景物的最大深度
} D3DVIEWPORT9, *LPD3DVIEWPORT9;
eg:RECT rect;
GetClientRect(hwnd, &rect);
D3DVIEWPORT9 vp;
vp.X = 0;
vp.Y = 0;
vp.Height = rect.bottom;
vp.Width = rect.right;
vp.MaxZ = 1.0f;
vp.MinZ = 0.0f;
m_pD3Device->SetViewport(&vp);