DirectX中的坐标转换相关技术

原创 2006年06月04日 17:47:00
   首先我们借助一个结构来描述物体的定位:
struts Object
{
   D3DMATRIX matLocal;
}
用该矩阵中的三个向量分别表示物体的朝向:Look,Up,Right,这个里的含义如同openGL里边相机的Look,Up,Right是一样的。然而实际上定位一个物体除了上述三个向量表示的姿态以外,还需要一个位置信息,于是我们用第四行来记录位置。将该矩阵设置为单位阵表示物体的变换从原点开始,沿坐标轴方向。这样表示以后,物体绕Look轴转就是横滚(pitch),绕Up轴转就是偏航(yaw),绕Right轴转就是俯仰(roll)。
------------------------------------
   下面说一下用到的API。将一个向量按照指定矩阵变换的API是:D3DXVectorTransformCoord(D3DXVector* vNew,D3DXVector* vOld,D3DXMatrix* mat),那么旋转用的矩阵mat又来源于D3DMatrixRotationAxis(D3DXMatrix* mat,D3DXVector* vAxis,FLOAT fRad),表示绕某一向量旋转一个角度产生一个变换矩阵。有了这两个API我们就可以通过将三个姿态向量指定给vAxis和vOld来获取到新的姿态向量。
   需要注意的是,由于计算精度问题,上述计算进行多次以后会存在舍入误差,使三个姿态向量不再垂直。为了解决这个问题需要在旋转之前对三个向量进行归一化。这里的归一化不是对三个向量各自归一,而是按照下述方式进行:
D3DXVec3Normalize(&vLook,&vLook);
D3DXVec3Cross(&vRight,&vUp,&vLook);
D3DXVec3Normalize(&vRight,&vRight);
D3DXVec3Cross(&vUp,&vLook,&vRight);
D3DXVec3Normalize(&vUp,&vUp);
可以看到是通过向量单独归一和叉乘的方式进行,既保证向量归一,又保证垂直。
   matLocal矩阵的保存形式如下:第一行是Right,第二行是Up,第三行是Look,第四行是Position:
m_pObjects[0].matLocal._11 = vRight.x;
m_pObjects[0].matLocal._12 = vRight.y;
m_pObjects[0].matLocal._13 = vRight.z;
m_pObjects[0].matLocal._21 = vUp.x;
m_pObjects[0].matLocal._22 = vUp.y;
m_pObjects[0].matLocal._23 = vUp.z;
m_pObjects[0].matLocal._31 = vLook.x;
m_pObjects[0].matLocal._32 = vLook.y;
m_pObjects[0].matLocal._33 = vLook.z;
m_pObjects[0].matLocal._41 = vPos.x;
m_pObjects[0].matLocal._42 = vPos.y;
m_pObjects[0].matLocal._43 = vPos.z;
   下面我们把上述变换过程总结一下:
  1. 确定旋转角度和旋转轴。
  2. 取出当前的vRight,vLook,vUp,vPos向量;
  3. 对三个向量进行归一化;
  4. 利用D3DMatrixRotationAxis(D3DXMatrix* mat,D3DXVector* vAxis,FLOAT fRad)产生旋转矩阵;
  5. 利用D3DXVectorTransformCoord(D3DXVector* vNew,D3DXVector* vOld,D3DXMatrix* mat)对当前的vRight,vLook,vUp向量进行变换,得到新的vRight,vLook,vUp向量。
  6. 移动位置,获得新的vPos;
  7. 将新的vRight,vLook,vUp,vPos向量设置到matLocal中。

----------------------------

上边的表示方法我们看到要7个过程,这略微有些复杂,那么下面我们来看另外一种简洁的计算方法-四元数(Quaternion)。

  我们先对比一下实现的差别,然后再具体解释API的含义。

  1.  确定旋转角度和旋转轴。
  2. 利用D3DXQuaternionRotationYawPitchRoll(D3DXMatrix* mat,Float fYaw,FLOAT fPitch,FLOAT fRoll)的到变换矩阵。
  3. 把上述得到的矩阵同matLocal相乘得到新的matLocal;
  4. 做位置的变换。

   四元数的原理有点复杂,由于速成关系我也没有怎么看,只是知道可以简单想象成一个向量加上一次旋转,具体的运算推导有机会再研究吧。但这个东西用途的确很广泛,因此被作为一种专门的方法被D3D介绍。

   上边只用到了一个API,那就是D3DXQuaternionRotationYawPitchRoll(D3DXMatrix* mat,Float fYaw,FLOAT fPitch,FLOAT fRoll),给定绕三个轴的旋转角度,返回一个变换矩阵。

-----------------------------

   下边看一下观察变换,观察矩阵同物体定位矩阵唯一不同的就是其存储方式,它采取列向量的存储方式。相机的各种变换同物体的变换没有任何不同,最后也是得到一个矩阵,只是D3D提供了一个根据视点位置,相机朝向和向上方向构造矩阵的函数:D3DXMatrixLookAtLH(D3DXMatrix* mat,D3DXVECTOR3* pEye,D3DXVECTOR3* pAt,D3DXVECTOR3* pUp),省着自己算了。最后用m_pd3Device->SetTransform(D3DTS_VIEW,&mat)设置一下就可以了。

   这里需要注意的是D3DXMatrixLookAtLH()只适合于简单的头罩式显示或者视点跟随,对于具有复杂旋转的飞行模拟器这类相机最好还是自己来算。计算的方式同前边介绍的物体变换的方式一样,也有两种方式,一种是复杂的7步变换,一种是简单的四元数变换。最后将得到的向量按照列向量的形式赋给视矩阵,再利用SetTransform()设置一下就好了。这实际上是一种自己维护相机的方式。

------------------------------

下面看一下投影变换。提到投影就会想到视锥,就会有视域角(FOV-field of view)、宽高比(aspect)和远近裁减面这四个参数。在D3D里边可以利用D3DXMatrixPerspectiveFoVLH(D3DXMATRIX* pOut,FLOAT fovY,FLOAT Aspect,FLOAT zn,FLOAT zf),通过给定的四个参数获得投影矩阵,然后用m_pd3Device->SetTranform(D3DTS_PROJECTION,&pOut)来设置投影矩阵即可。

-------------------------------
   视口的使用上次已经说过了,下面就看一下深度缓冲的使用。
   在框架里边使用深度缓冲只要让m_d3dEnumeration.AppUsesDepthBuffer = TRUE.然后在每一帧绘制前用m_pd3Device->Clear()方法清空缓冲区。
   HRESULT Clear(
                 DWORD Count,//矩形数量
                 const D3DRECT *pRects,//矩形指针
                 DWORD Flags,//要清除的缓冲类型
                 float Z,//Z缓冲设置的值
                 DWORD Stencil)//模板缓冲设置的值
   书中还讲了一个深度缓冲精度影响渲染质量的问题,为了达到无错误的稳定效果可以是用W缓冲器。方法如下:
   m_pd3Device->SetRenderState(D3DTS_ZNABLE,D3DZB_USEW).
但是这需要硬件的支持,为了稳妥起见还是使用Z缓冲比较好。
-------------------------------
  总结来说,D3D要设置的矩阵分为三种:除了上次提到的世界坐标矩阵,其实我理解也就是openGL里边对应的模型视图矩阵中的模型矩阵,还有视矩阵和投影矩阵。它们的设置函数都是pDeviceObject->SetTransform(),只不过参数不同而已。所有的其他函数也好,表示也好最终都是为了获得这三个矩阵,这让我们拨开云雾见太阳,只要心中挂念这矩阵就可以了。

Unity3D 摄像机(Camera)属性详解

摄像机的设备捕获和显示世界玩家。 通过定制和操作相机,你可以使你的游戏真正独特的演讲。 你可以有一个无限数量的摄像机在场景。他们可以在任何顺序集呈现在屏幕上的任何地方,或只有某些部分的屏幕。 Uni...
  • jbjwpzyl3611421
  • jbjwpzyl3611421
  • 2013年10月14日 12:05
  • 37481

软件光栅器(Directx11)四之从相机空间到视平面的坐标变换

从上一篇技术博客  软件光栅器三之世界矩阵,相机变换矩阵,透视投影矩阵,透视除法,视口变换矩阵  我们直接给出了各大变换矩阵的表示形式以及实现的代码 这一节博客 我将讲述从一个顶点从相机空间到到视平面...
  • qq_29523119
  • qq_29523119
  • 2016年11月30日 22:28
  • 560

Directx9.0 学习教程4 - 坐标系以及变换知识小记

坐标系   左图是左手坐标系    右图是右手坐标系   Direct3d用的是左手坐标系     顶点和法向     光栅化 变换 1世界变换 2观察变换 D...
  • cq361106306
  • cq361106306
  • 2014年09月29日 10:31
  • 1770

DX 中的坐标变换

Directx中的坐标变换 (1)世界变换和世界坐标系:物体在三维空间的运动和变形过程称为世界变换,如平移、旋转、缩放等。物体在其中运动的三维空间称为世界空间,它的三维坐标系表示称为世界坐标系,物体顶...
  • Henzox
  • Henzox
  • 2015年05月12日 16:27
  • 1935

用DirectX绘制使用纹理的立方体

下面将学习DirectX的3D渲染基础部分,但不会对3D数学或图形理论有太详细的介绍。 首先要了解DirectX中的坐标系,要记住的是DirectX采用左手坐标系。 在Direct3D中...
  • woshiyuanlei
  • woshiyuanlei
  • 2015年07月10日 16:38
  • 1569

DirectX 9.0 (12) FPS相机

详细讲解了如何在DirectX中实现一个FPS的相机
  • i_dovelemon
  • i_dovelemon
  • 2014年09月25日 20:16
  • 2256

DirectX技术与Windows应用程序

1.1. DirectX是简介DirectX是微软开发的多媒体应用程序接口(API)(包括图形,声音,输入,网络)。Direct代表直接的意思,X代表很多部分,DirectX 就是一系列的 DLL (...
  • tinya0913
  • tinya0913
  • 2010年12月10日 17:56
  • 2608

Java领域的相关技术

Java虚拟机分三种主要用于Web开发
  • u013126771
  • u013126771
  • 2014年05月23日 18:57
  • 2395

Directx11地形渲染教程一之FirstCamera(第一人称相机)

前一段时间打了一周的魔兽RPG,现在开始更新Directx11进阶的系列教程,估计写20篇博客左右,涵盖DX11入门教程系列未提及的,比如地形,天空盒等等。 这节教程是关于如何实现FirstCam...
  • qq_29523119
  • qq_29523119
  • 2016年12月21日 19:48
  • 655

dx11学习笔记-3.三维空间变换(自己整理,基础详尽)

三维空间变换其实是图形学的基本知识,和DX倒没有什么特定关系。但MS关于这块儿的文档教程解释得很详尽。看完之后我觉得我对于坐标变换的理解又深入了一步。此处我截取自己觉得精要的地方来说明。资料参考:1、...
  • code_xbug
  • code_xbug
  • 2016年02月17日 12:41
  • 2626
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:DirectX中的坐标转换相关技术
举报原因:
原因补充:

(最多只允许输入30个字)