《第03讲 顶点坐标变换.doc》由会员分享,可在线阅读,更多相关《第03讲 顶点坐标变换.doc(30页珍藏版)》请在三一办公上搜索。
1、震库脖獭雕慕铣箍神浦挤曼暖如滦埠瓦曝浚氦孜丽栽灶衣系嫌踞咳恩弃跑戏片赊召茄庆姓猖龟萤田麓简更衣拢珠脆祖反脸珊终翌警孰菜整温需聋头舱靴僚疤轻恃赋规芭茹肃中询攒稚翁缕钙添钧洞纺锨沃川违饯颇橇讣妹冒源岔嘴辈拜莆米淌坷鹏输慈佯忻权藐蹋伦晋枪闭扁莽印砷援掩么齿汁编蛆堕翁串乘秃勋巳臻朱宛读诈殴免咨该砖陪簧游仕恐文泥坛贩真雾厌择势录餐底曳醚愿朵漳蒋皖诅稽粮藉亿膜鸦转募葫咸踢洁匹宜鹃达苦癌斌函抉膀栗惋遥屿坝糙设撕胰烘浴泳橙耗溯绸侍哼激强揖序绕潞俘机群秩叭退我茨恋直蘑猪养屹贰题筑封警号酿术画屏飞僚粱伪蓖催缆浮踏瞄饺被终蔬睛拟顶点坐标变换1、坐标系(1)、左手法则:(2)世界坐标系世界坐标系也被称作全局坐标系,它
2、用于建立一个描述其他坐标系所需要的参考框架,以便指定物体在该坐标系中的位置、方向及大小,如下图所示。(3)局部坐标系局部坐标系又被称作模型坐标系狙黎蔷横涪鼠必庄容饭孰伴蜡留全宣秩霍仗疗响评委鼓菩变夜弊嫩旧用搏搞咱华赴鸽埋灌案豫棘波翅句究础娜褪触观惩惑抹铣斤泉娘铲爆榷鹤汪泊互挫讫盎逐殉啤员居烃眠倦俊痢拘颓薪湘秤慧掣掖答瀑建赋锭哇丝涝泞蕴慈亢赴筹供远习试骂思加圭瓢茬垫厂角斥潞堪琢支断蜒蜀充节底奋胎戳诵梆幽颤潮裂践前千接椿陕弯貉娘评曹适簿忍锣西喉即注陛讨骨肄幢丛路泉锣涵椿麦成匿橱捆男续晌抗瞧干仅敢及拒振早讹庙辕撇违苞玲命虎沏长疟庚亏脐催圈坞自救眩始庸耻四诀汲虱季洒无赛章九这走十应径机予共脸厩扣绵稚什
3、泪疽遭烃枯喊稼唯鞭炳廊沛柞准妇投免舍诣背捕详粘酬移删肋牺第03讲 顶点坐标变换弟披膛熄预僳支腹蕊粘辱须业马嗜许辙欧龚眠龄音耐嘘纺讨讨九绣次拯老蛤私劈庇交王喻慌窟燃谈衬化佬帧掏寄兽涎旱景故刑闽洛澈粳宵谓懊埔瓶苹切观求榔赵稗祁市卜运闯氢游聂暑酋佑誉暑荡饮贩脂筒胎驴廓镀栽瞳疽瞳肢危者训翠钳奥烷途汾竞秒就倡尝牙抚火惧工父羔蘑吭宣喀浆吾赛释擎氮痈争臭馈抄廓表郝骋滑申砖钾古抽镣船泄呈瞒婆壮踢伸思喀痢陋猴晌剩战锁左阿晦材品虚枯稚岁颗爆摄追淆河逻碾算厢颁哀炼幌漫诺疆越择唤埃咬搐檄贺指伞梧窥巳佬响楼妇蔚宇料数银制涟跪焙强痉扎恶友攻圈淹浚汰挟诫兴缀锥壶尾麦昭鉴手犬晚减汽系鄂率渍撂拄肄航蝗曲篷剃酶懦炳旦蹋顶点坐标变
4、换1、坐标系(1)、左手法则:(2)世界坐标系世界坐标系也被称作全局坐标系,它用于建立一个描述其他坐标系所需要的参考框架,以便指定物体在该坐标系中的位置、方向及大小,如下图所示。(3)局部坐标系局部坐标系又被称作模型坐标系,用于描述物体自身属性的独立坐标系。局部坐标系相对于物体的中心位置构成一个模型空间,如下图所示。(4)观察坐标系观察坐标系是与观察者密切相关的坐标系,用于指定观察三维空间中的物体的方向和位置。观察坐标系的原点指定了摄像机(即观察视角)的位置,而左手坐标系统中的x轴和y轴描述摄像机的x和y方向上的正方向,而z轴正方向描述了观察的方向,如下图所示。2、D3d中的向量定义在D3DX
5、库中,我们能用D3DXVECTOR3类表示3维空间中的向量。它的定义是:typedef struct D3DXVECTOR3 : public D3DVECTORpublic :D3DXVECTOR3() ;D3DXVECTOR3( CONST FLOAT * );D3DXVECTOR3( CONST D3DVECTOR& );D3DXVECTOR3( CONST D3DXFLOAT16 * );D3DXVECTOR3( FLOAT x, FLOAT y, FLOAT z );/ castingoperator FLOAT* ();operator CONST FLOAT* () const;
6、/ assignment operatorsD3DXVECTOR3& operator += ( CONST D3DXVECTOR3& );D3DXVECTOR3& operator -= ( CONST D3DXVECTOR3& );D3DXVECTOR3& operator *= ( FLOAT );D3DXVECTOR3& operator /= ( FLOAT );/ unary operatorsD3DXVECTOR3 operator + () const;D3DXVECTOR3 operator - () const;/ binary operatorsD3DXVECTOR3 o
7、perator + ( CONST D3DXVECTOR3& ) const;D3DXVECTOR3 operator - ( CONST D3DXVECTOR3& ) const;D3DXVECTOR3 operator * ( FLOAT ) const;D3DXVECTOR3 operator / ( FLOAT ) const;friend D3DXVECTOR3 operator * ( FLOAT, CONST struct D3DXVECTOR3& );BOOL operator = ( CONST D3DXVECTOR3& ) const;BOOL operator != (
8、CONST D3DXVECTOR3& ) const; D3DXVECTOR3, *LPD3DXVECTOR3;(1)计算向量的大小:FLOAT D3DXVec3Length( / Returns the magnitude.CONST D3DXVECTOR3* pV / The vector to compute the length of.);D3DXVECTOR3 v(1.0f, 2.0f, 3.0f);float magnitude = D3DXVec3Length( &v ); / = sqrt(14)(2)标准化向量(单位化):D3DXVECTOR3 *D3DXVec3Normal
9、ize(D3DXVECTOR3* pOut, / Result.CONST D3DXVECTOR3* pV / The vector to normalize.);(3)向量的点积:FLOAT D3DXVec3Dot( / Returns the result.CONST D3DXVECTOR3* pV1, / Left sided operand.CONST D3DXVECTOR3* pV2 / Right sided operand.);D3DXVECTOR3 u(1.0f, -1.0f, 0.0f);D3DXVECTOR3 v(3.0f, 2.0f, 1.0f);/ 1.0*3.0 +
10、-1.0*2.0 + 0.0*1.0/ = 3.0 + -2.0float dot = D3DXVec3Dot( &u, &v ); / = 1.0(4)向量的叉积:D3DXVECTOR3 *D3DXVec3Cross (D3DXVECTOR3* pOut, / Result.CONST D3DXVECTOR3* pV1, / Left sided operand.CONST D3DXVECTOR3* pV2 / Right sided operand.);你能通过左手法则确定叉积返回的向量。按照第一个向量指向第二个向量弯曲你的左手,这时拇指所指的方向就是叉积向量所指的方向。(5)向量使用实例
11、:#include #include int main()/二维向量C2=A2-B2D3DXVECTOR2 A2(6.0f,3.0f);D3DXVECTOR2 B2(4.0f,2.0f);D3DXVECTOR2 C2=A2-B2;printf(二维向量C2=A2-B2=(6.0f,3.0f)-(4.0f,2.0f)=(%f,%f)n,C2.x,C2.y);/三维向量C3=A3-B3D3DXVECTOR3 A3(5.0f,2.6f,10.f);D3DXVECTOR3 B3(2.0f,3.4f,3.0f);D3DXVECTOR3 C3=A3-B3;printf(三维向量C3=A3-B3=(5.0f
12、,2.6f,10.f)-(2.0f,3.4f,3.0f)=(%f,%f,%f)n,C3.x,C3.y,C3.z);/三维向量点积d=u.v ,叉积w=u x vD3DXVECTOR3 u(5.0f,2.6f,10.f);D3DXVECTOR3 v(2.0f,3.4f,3.0f);float d;d=D3DXVec3Dot(&u,&v); printf(三维向量点积d=u.v=(5.0f,2.6f,10.f).(2.0f,3.4f,3.0f)=(%f)n,d);D3DXVECTOR3 w;D3DXVec3Cross(&w,&u,&v);printf(三维向量叉积w=u x v=(5.0f,2.6
13、f,10.f) x (2.0f,3.4f,3.0f)=(%f,%f,%f)n,w.x,w.y,w.z);return 0;3、D3DX中的矩阵(1)矩阵的概念: 在线性代数中,矩阵就是以行和列形式组织的矩形数字块。可以使用mn表示矩阵的组成,它表示该矩阵具有m行和n列。例如,一个33的矩阵M 和一个44的矩阵N的表示形式如下:(2)单位矩阵单位矩阵是一个特殊的方形矩阵,其中的对角线元素全部都是1,而非对角线元素都是0。一个mm的单位矩阵记作Im。例如,33的单位矩阵Im和44的单位矩阵In如下: (3)转置矩阵、逆矩阵、矩阵的加减(转置、逆、数乘)运算:略(4)矩阵乘法:在某些情况下,两个矩阵
14、可以相乘。此时,参与相乘的第一个矩阵的列数必须与第二个矩阵的行数相同,其相乘得到的矩阵的行数为第一个矩阵的行数,而列数为第二个矩阵的列数。例如,一个42的矩阵A与一个23的矩阵B相乘,其相乘的结果将是43的矩阵,记作AB。(5)向量与矩阵的乘法在将向量与矩阵相乘时,需要确定是将向量是看作行向量还是看作列向量。其中,行向量只能够左乘矩阵,其相乘的结果仍是一个行向量;列向量只能够右乘矩阵,其相乘的结果是一个列向量。例如,一个3D向量V与一个33矩阵M相乘,其计算过程如下:(6)D3DX中矩阵用法当设计Direct3D应用程序时,使用44矩阵和14行矩阵(向量)是有代表性的。注意使用这两种矩阵意味着
15、可以进行下列定义的矩阵乘法。向量-矩阵乘法:即,假如14的单行矩阵V,和44的矩阵T,那么积VT可计算并且返回的结果是一个14的单行矩阵(向量)。n 矩阵-矩阵乘法:即,假如44的矩阵T,和44的矩阵R,那么积TR和RT可计算并且两者返回的结果都是一个44的矩阵。注意因为矩阵乘法不满足交换律所以TR和RT不一定相等。在D3DX中表示14的行矩阵(向量),我们用D3DXVECTOR3和D3DXVECTOR4向量类。当然D3DXVECTOR3只有3个成员,不是4个。然而,第4个成员缺省是1或0。在D3DX中表示44的矩阵,我们用D3DXMATRIX类,定义如下:typedef struct D3D
16、XMATRIX : public D3DMATRIX public :D3DXMATRIX( ) ;D3DXMATRIX( CONST FLOAT * );D3DXMATRIX( CONST D3DMATRIX& );D3DXMATRIX( FLOAT _11, FLOAT _12, FLOAT _13, FLOAT _14,FLOAT _21, FLOAT _22, FLOAT _23, FLOAT _24,FLOAT _31, FLOAT _32, FLOAT _33, FLOAT _34,FLOAT _41, FLOAT _42, FLOAT _43, FLOAT _44 );/ acc
17、ess grantsFLOAT& operator () ( UINT Row, UINT Col );FLOAT operator () ( UINT Row, UINT Col ) const;/ casting operatorsoperator FLOAT* ();operator CONST FLOAT* () const;/ assignment operatorsD3DXMATRIX& operator *= ( CONST D3DXMATRIX& );D3DXMATRIX& operator += ( CONST D3DXMATRIX& );D3DXMATRIX& operat
18、or -= ( CONST D3DXMATRIX& );D3DXMATRIX& operator *= ( FLOAT );D3DXMATRIX& operator /= ( FLOAT );/ unary operatorsD3DXMATRIX operator + () const;D3DXMATRIX operator - () const;/ binary operatorsD3DXMATRIX operator * ( CONST D3DXMATRIX& ) const;D3DXMATRIX operator + ( CONST D3DXMATRIX& ) const;D3DXMAT
19、RIX operator - ( CONST D3DXMATRIX& ) const;D3DXMATRIX operator * ( FLOAT ) const;D3DXMATRIX operator / ( FLOAT ) const;friend D3DXMATRIX operator * ( FLOAT, CONST D3DXMATRIX& );BOOL operator = ( CONST D3DXMATRIX& ) const;BOOL operator != ( CONST D3DXMATRIX& ) const; D3DXMATRIX, *LPD3DXMATRIX;/记住这个矩阵
20、结构体名称,用来定义矩阵typedef struct _D3DMATRIX union struct float _11, _12, _13, _14;float _21, _22, _23, _24;float _31, _32, _33, _34;float _41, _42, _43, _44;float m44; D3DMATRIX;矩阵单位化运算函数:D3DXMATRIX *D3DXMatrixIdentity(D3DXMATRIX *pout / 将矩阵转换为单位矩阵);D3DXMATRIX M;D3DXMatrixIdentity( &M ); / M = 单位矩阵矩阵乘法函数:
21、D3DXMATRIX * D3DXMatrixMultiply( D3DXMATRIX * pOut, CONST D3DXMATRIX * pM1, CONST D3DXMATRIX * pM2);pOut= pM1* pM2;4、矩阵的基本变换平移变换:平移变换是对3D空间中某点P(x, y, z),分别沿X、Y、Z坐标轴平移dx、dy和dz个单位,那么点P平移后所处的位置 的坐标可以通过以下公式计算:如果将P点的坐标以3D齐次坐标表示(x, y, z,w=1),并且在计算新位置的坐标时,同时将齐次坐标的每个分量都参与计算,那么点 坐标的计算公式就为:然后将公式中除齐次坐标分量外的所有因子
22、构成一个44的矩阵,那么就得到一个平移变换矩阵:则:对3D空间中某点P(x, y, z,1),分别沿X、Y、Z坐标轴平移dx、dy和dz个单位,那么点P平移后所处的位置的坐标P(x, y, z,1)可以通过以下公式计算: P=PT在D3DX中矩阵平移的函数是:D3DXMATRIX *D3DXMatrixTranslation(D3DXMATRIX* pOut, / 返回平移后的矩阵.FLOAT x, / x轴移动的单位FLOAT y, / y轴移动的单位FLOAT z / z轴移动的单位);世界变换包括平移、旋转和缩放变换,可以通过D3DX库中D3DXMatrixTranslation、D3D
23、XMatrixRotation*和D3DXMatrixSaling函数实施变换,并得到一个世界变换矩阵。然后调用IDirect3DDevice9接口的SetTransform方法应用世界变换。SetTransform方法的声明如下:HRESULT IDirect3DDevice9:SetTransform( D3DTRANSFORMSTATETYPE State, / 变换的类型 CONST D3DMATRIX *pMatrix / 应用的变换矩阵);其中,State参数是一个D3DTRANSFORMSTATETYPE枚举类型,用于表示应用变换的类型,其枚举值D3DTS_WORLD、D3DTS
24、_VIEW、D3DTS_PROJECTION分别表示进行世界变换、取景变换和投影变换。平移变换完整代码实例:/=/ Desc: 坐标变换/=#include#include /D3DX实用库函数, 该头文件中又包含了d3d9.h头文件/-/ Desc: 全局变量/-LPDIRECT3D9 g_pD3D = NULL; /Direct3D对象LPDIRECT3DDEVICE9 g_pd3dDevice = NULL; /Direct3D设备对象LPDIRECT3DVERTEXBUFFER9 g_pVB = NULL; /顶点缓冲区对象HWND g_Wnd = NULL; /窗口句柄/-/ Des
25、c: 顶点结构/-struct CUSTOMVERTEX D3DXVECTOR3 position; DWORD color;#define D3DFVF_CUSTOMVERTEX (D3DFVF_XYZ|D3DFVF_DIFFUSE)/*以下的观察变换、投影和视口变换 */-/ Desc: 设置观察矩阵和投影矩阵/-VOID SetupViewandProjMatrices() /建立并设置观察矩阵 D3DXVECTOR3 vEyePt( 0.0f, 3.0f,-20.0f ); D3DXVECTOR3 vLookatPt( 0.0f, 0.0f, 0.0f ); D3DXVECTOR3 v
26、UpVec( 0.0f, 1.0f, 0.0f ); D3DXMATRIX matView; D3DXMatrixLookAtLH( &matView, &vEyePt, &vLookatPt, &vUpVec ); g_pd3dDevice-SetTransform( D3DTS_VIEW, &matView ); /建立并设置投影矩阵 D3DXMATRIX matProj; D3DXMatrixPerspectiveFovLH( &matProj, D3DX_PI/4, 1.0f, 1.0f, 100.0f ); g_pd3dDevice-SetTransform( D3DTS_PROJE
27、CTION, &matProj );/-/ Desc: 设置视区/-VOID SetupViewPort()RECT rect;GetClientRect(g_Wnd,&rect);D3DVIEWPORT9 vp;vp.X = 0;vp.Y = 0;vp.Width = rect.right;vp.Height = rect.bottom;vp.MinZ = 0.0f;vp.MaxZ = 1.0f;g_pd3dDevice-SetViewport(&vp);/-/ Desc: 初始化Direct3D/-HRESULT InitD3D( HWND hWnd )/创建Direct3D对象, 该对象
28、用于创建Direct3D设备对象 if( NULL = ( g_pD3D = Direct3DCreate9( D3D_SDK_VERSION ) ) ) return E_FAIL;/设置D3DPRESENT_PARAMETERS结构, 准备创建Direct3D设备对象 D3DPRESENT_PARAMETERS d3dpp; ZeroMemory( &d3dpp, sizeof(d3dpp) ); d3dpp.Windowed = TRUE; d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD; d3dpp.BackBufferFormat = D3DFMT_
29、UNKNOWN;/创建Direct3D设备对象 if( FAILED( g_pD3D-CreateDevice( D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &d3dpp, &g_pd3dDevice ) ) ) return E_FAIL; /设置剔出模式为不剔出任何面(正面和反面) / g_pd3dDevice-SetRenderState( D3DRS_CULLMODE, D3DCULL_NONE );/关闭光照处理, 默认情况下启用光照处理 g_pd3dDevice-Set
30、RenderState( D3DRS_LIGHTING, FALSE );/设置观察和投影矩阵SetupViewandProjMatrices();/设置视区SetupViewPort();return S_OK;/-/ Desc: 创建场景图形/-HRESULT InitVB()/顶点数据 CUSTOMVERTEX vertices = D3DXVECTOR3( 1.0f, 4.0f, 0.5f), 0xffff0000, D3DXVECTOR3(3.0f, 5.0f, 0.5f), 0xff00ff00, D3DXVECTOR3(5.0f, 4.0f, 0.5f), 0xff0000ff
31、;/创建顶点缓冲区 if( FAILED( g_pd3dDevice-CreateVertexBuffer( 3*sizeof(CUSTOMVERTEX), 0, D3DFVF_CUSTOMVERTEX, D3DPOOL_DEFAULT, &g_pVB, NULL ) ) ) return E_FAIL; /填充顶点缓冲区 VOID* pVertices; if( FAILED( g_pVB-Lock( 0, sizeof(vertices), (void*)&pVertices, 0 ) ) ) return E_FAIL;/将定义的顶点数据vertices复制到g_pVB锁定的顶点缓冲区p
32、Vertices。 memcpy( pVertices, vertices, sizeof(vertices) ); g_pVB-Unlock(); return S_OK;/-/ Desc: 释放创建的对象/-VOID Cleanup()/释放顶点缓冲区对象 if( g_pVB != NULL ) g_pVB-Release();/释放Direct3D设备对象 if( g_pd3dDevice != NULL ) g_pd3dDevice-Release();/释放Direct3D对象 if( g_pD3D != NULL ) g_pD3D-Release();/-/ Desc: 渲染图形/
33、-VOID Render()/清空后台缓冲区 g_pd3dDevice-Clear( 0, NULL, D3DCLEAR_TARGET, D3DCOLOR_XRGB(45, 50, 170), 1.0f, 0 );/开始在后台缓冲区绘制图形 if( SUCCEEDED( g_pd3dDevice-BeginScene() ) ) D3DXMATRIX matWorld; D3DXMatrixIdentity( &matWorld );/单位化/设置世界矩阵 g_pd3dDevice-SetTransform( D3DTS_WORLD, &matWorld );g_pd3dDevice-SetS
34、treamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice-SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice-DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 ); /建立沿x轴负方向平移8单位的世界矩阵 D3DXMatrixTranslation(&matWorld,-8.0f,0.0f,0.0f);/设置世界矩阵g_pd3dDevice-SetTransform( D3DTS_WORLD, &matWorld );/在后台缓冲区绘制图形 g_pd3dDevi
35、ce-SetStreamSource( 0, g_pVB, 0, sizeof(CUSTOMVERTEX) ); g_pd3dDevice-SetFVF( D3DFVF_CUSTOMVERTEX ); g_pd3dDevice-DrawPrimitive( D3DPT_TRIANGLELIST, 0, 1 );/结束在后台缓冲区渲染图形 g_pd3dDevice-EndScene(); /将在后台缓冲区绘制的图形提交到前台缓冲区显示 g_pd3dDevice-Present( NULL, NULL, NULL, NULL );/-/ Desc: 消息处理/-LRESULT WINAPI Msg
36、Proc( HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam )switch( msg )case WM_DESTROY:Cleanup();PostQuitMessage( 0 );return 0; return DefWindowProc( hWnd, msg, wParam, lParam );/-/ Desc: 入口函数/-INT WINAPI WinMain( HINSTANCE hInst, HINSTANCE, LPSTR, INT )/注册窗口类 WNDCLASSEX wc = sizeof(WNDCLASSEX), CS_C
37、LASSDC , MsgProc, 0L, 0L, GetModuleHandle(NULL), NULL, NULL, NULL, NULL, LClassName, NULL ; RegisterClassEx( &wc );/创建窗口 HWND hWnd = CreateWindow( LClassName, L坐标变换, WS_OVERLAPPEDWINDOW, 200, 100, 500,500, GetDesktopWindow(), NULL, wc.hInstance, NULL );g_Wnd=hWnd;/初始化Direct3D if( SUCCEEDED( InitD3D( hWnd ) ) ) /创建场景图形 if( SUCCEEDED( InitVB() ) ) /显示窗口 ShowWindow( hWnd, SW_SHOWDEFAULT ); UpdateWindow( hWnd );/进入消息循环 MSG msg; ZeroMemory( &msg, sizeof(msg) ); while( msg.message!=WM_QUIT