第03讲 顶点坐标变换.docx
《第03讲 顶点坐标变换.docx》由会员分享,可在线阅读,更多相关《第03讲 顶点坐标变换.docx(44页珍藏版)》请在冰豆网上搜索。
第03讲顶点坐标变换
顶点坐标变换
1、坐标系
(1)、左手法则:
(2).世界坐标系
世界坐标系也被称作全局坐标系,它用于建立一个描述其他坐标系所需要的参考框架,以便指定物体在该坐标系中的位置、方向及大小,如下图所示。
(3)局部坐标系
局部坐标系又被称作模型坐标系,用于描述物体自身属性的独立坐标系。
局部坐标系相对于物体的中心位置构成一个模型空间,如下图所示。
(4)观察坐标系
观察坐标系是与观察者密切相关的坐标系,用于指定观察三维空间中的物体的方向和位置。
观察坐标系的原点指定了摄像机(即观察视角)的位置,而左手坐标系统中的x轴和y轴描述摄像机的x和y方向上的正方向,而z轴正方向描述了观察的方向,如下图所示。
2、D3d中的向量定义
在D3DX库中,我们能用D3DXVECTOR3类表示3维空间中的向量。
它的定义是:
typedefstructD3DXVECTOR3:
publicD3DVECTOR
{
public:
D3DXVECTOR3(){};
D3DXVECTOR3(CONSTFLOAT*);
D3DXVECTOR3(CONSTD3DVECTOR&);
D3DXVECTOR3(CONSTD3DXFLOAT16*);
D3DXVECTOR3(FLOATx,FLOATy,FLOATz);
//casting
operatorFLOAT*();
operatorCONSTFLOAT*()const;
//assignmentoperators
D3DXVECTOR3&operator+=(CONSTD3DXVECTOR3&);
D3DXVECTOR3&operator-=(CONSTD3DXVECTOR3&);
D3DXVECTOR3&operator*=(FLOAT);
D3DXVECTOR3&operator/=(FLOAT);
//unaryoperators
D3DXVECTOR3operator+()const;
D3DXVECTOR3operator-()const;
//binaryoperators
D3DXVECTOR3operator+(CONSTD3DXVECTOR3&)const;
D3DXVECTOR3operator-(CONSTD3DXVECTOR3&)const;
D3DXVECTOR3operator*(FLOAT)const;
D3DXVECTOR3operator/(FLOAT)const;
friendD3DXVECTOR3operator*(FLOAT,CONSTstructD3DXVECTOR3&);
BOOLoperator==(CONSTD3DXVECTOR3&)const;
BOOLoperator!
=(CONSTD3DXVECTOR3&)const;
}D3DXVECTOR3,*LPD3DXVECTOR3;
(1)计算向量的大小:
FLOATD3DXVec3Length(//Returnsthemagnitude.
CONSTD3DXVECTOR3*pV//Thevectortocomputethelengthof.
);
D3DXVECTOR3v(1.0f,2.0f,3.0f);
floatmagnitude=D3DXVec3Length(&v);//=sqrt(14)
(2)标准化向量(单位化):
D3DXVECTOR3*D3DXVec3Normalize(
D3DXVECTOR3*pOut,//Result.
CONSTD3DXVECTOR3*pV//Thevectortonormalize.
);
(3)向量的点积:
FLOATD3DXVec3Dot(//Returnstheresult.
CONSTD3DXVECTOR3*pV1,//Leftsidedoperand.
CONSTD3DXVECTOR3*pV2//Rightsidedoperand.
);
D3DXVECTOR3u(1.0f,-1.0f,0.0f);
D3DXVECTOR3v(3.0f,2.0f,1.0f);
//1.0*3.0+-1.0*2.0+0.0*1.0
//=3.0+-2.0
floatdot=D3DXVec3Dot(&u,&v);//=1.0
(4)向量的叉积:
D3DXVECTOR3*D3DXVec3Cross(
D3DXVECTOR3*pOut,//Result.
CONSTD3DXVECTOR3*pV1,//Leftsidedoperand.
CONSTD3DXVECTOR3*pV2//Rightsidedoperand.
);
你能通过左手法则确定叉积返回的向量。
按照第一个向量指向第二个向量弯曲你的左手,这时拇指所指的方向就是叉积向量所指的方向。
(5)向量使用实例:
#include
#include
intmain(){
//二维向量C2=A2-B2
D3DXVECTOR2A2(6.0f,3.0f);
D3DXVECTOR2B2(4.0f,2.0f);
D3DXVECTOR2C2=A2-B2;
printf("二维向量C2=A2-B2=(6.0f,3.0f)-(4.0f,2.0f)=(%f,%f)\n",C2.x,C2.y);
//三维向量C3=A3-B3
D3DXVECTOR3A3(5.0f,2.6f,10.f);
D3DXVECTOR3B3(2.0f,3.4f,3.0f);
D3DXVECTOR3C3=A3-B3;
printf("三维向量C3=A3-B3=(5.0f,2.6f,10.f)-(2.0f,3.4f,3.0f)=(%f,%f,%f)\n",
C3.x,C3.y,C3.z);
//三维向量点积d=u.v,叉积w=uxv
D3DXVECTOR3u(5.0f,2.6f,10.f);
D3DXVECTOR3v(2.0f,3.4f,3.0f);
floatd;
d=D3DXVec3Dot(&u,&v);
printf("三维向量点积d=u.v=(5.0f,2.6f,10.f).(2.0f,3.4f,3.0f)=(%f)\n",d);
D3DXVECTOR3w;
D3DXVec3Cross(&w,&u,&v);
printf("三维向量叉积w=uxv=(5.0f,2.6f,10.f)x(2.0f,3.4f,3.0f)=((%f,%f,%f)\n",
w.x,w.y,w.z);
return0;
}
3、D3DX中的矩阵
(1)矩阵的概念:
在线性代数中,矩阵就是以行和列形式组织的矩形数字块。
可以使用m×n表示矩阵的组成,它表示该矩阵具有m行和n列。
例如,一个3×3的矩阵M和一个4×4的矩阵N的表示形式如下:
(2)单位矩阵
单位矩阵是一个特殊的方形矩阵,其中的对角线元素全部都是1,而非对角线元素都是0。
一个m×m的单位矩阵记作Im。
例如,3×3的单位矩阵Im和4×4的单位矩阵In如下:
(3)转置矩阵、逆矩阵、矩阵的加减(转置、逆、数乘)运算:
略
(4)矩阵乘法:
在某些情况下,两个矩阵可以相乘。
此时,参与相乘的第一个矩阵的列数必须与第二个矩阵的行数相同,其相乘得到的矩阵的行数为第一个矩阵的行数,而列数为第二个矩阵的列数。
例如,一个4×2的矩阵A与一个2×3的矩阵B相乘,其相乘的结果将是4×3的矩阵,记作AB。
(5)向量与矩阵的乘法
在将向量与矩阵相乘时,需要确定是将向量是看作行向量还是看作列向量。
其中,行向量只能够左乘矩阵,其相乘的结果仍是一个行向量;列向量只能够右乘矩阵,其相乘的结果是一个列向量。
例如,一个3D向量V与一个3×3矩阵M相乘,其计算过程如下:
(6)D3DX中矩阵用法
当设计Direct3D应用程序时,使用4×4矩阵和1×4行矩阵(向量)是有代表性的。
注意使用这两种矩阵意味着可以进行下列定义的矩阵乘法。
向量-矩阵乘法:
即,假如1×4的单行矩阵V,和4×4的矩阵T,那么积VT可计算并且返回的结果是一个1×4的单行矩阵(向量)。
矩阵-矩阵乘法:
即,假如4×4的矩阵T,和4×4的矩阵R,那么积TR和RT可计算并且两者返回的结果都是一个4×4的矩阵。
注意因为矩阵乘法不满足交换律所以TR和RT不一定相等。
在D3DX中表示1×4的行矩阵(向量),我们用D3DXVECTOR3和D3DXVECTOR4向量类。
当然D3DXVECTOR3只有3个成员,不是4个。
然而,第4个成员缺省是1或0。
在D3DX中表示4×4的矩阵,我们用D3DXMATRIX类,定义如下:
typedefstructD3DXMATRIX:
publicD3DMATRIX{
public:
D3DXMATRIX(){};
D3DXMATRIX(CONSTFLOAT*);
D3DXMATRIX(CONSTD3DMATRIX&);
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
);
//accessgrants
FLOAT&operator()(UINTRow,UINTCol);
FLOAToperator()(UINTRow,UINTCol)const;
//castingoperators
operatorFLOAT*();
operatorCONSTFLOAT*()const;
//assignmentoperators
D3DXMATRIX&operator*=(CONSTD3DXMATRIX&);
D3DXMATRIX&operator+=(CONSTD3DXMATRIX&);
D3DXMATRIX&operator-=(CONSTD3DXMATRIX&);
D3DXMATRIX&operator*=(FLOAT);
D3DXMATRIX&operator/=(FLOAT);
//unaryoperators
D3DXMATRIXoperator+()const;
D3DXMATRIXoperator-()const;
//binaryoperators
D3DXMATRIXoperator*(CONSTD3DXMATRIX&)const;
D3DXMATRIXoperator+(CONSTD3DXMATRIX&)const;
D3DXMATRIXoperator-(CONSTD3DXMATRIX&)const;
D3DXMATRIXoperator*(FLOAT)const;
D3DXMATRIXoperator/(FLOAT)const;
friendD3DXMATRIXoperator*(FLOAT,CONSTD3DXMATRIX&);
BOOLoperator==(CONSTD3DXMATRIX&)const;
BOOLoperator!
=(CONSTD3DXMATRIX&)const;
}D3DXMATRIX,*LPD3DXMATRIX;//记住这个矩阵结构体名称,用来定义矩阵
typedefstruct_D3DMATRIX{
union{
struct{
float_11,_12,_13,_14;
float_21,_22,_23,_24;
float_31,_32,_33,_34;
float_41,_42,_43,_44;
};
floatm[4][4];
};
}D3DMATRIX;
矩阵单位化运算函数:
D3DXMATRIX*D3DXMatrixIdentity(
D3DXMATRIX*pout//将矩阵转换为单位矩阵
);
D3DXMATRIXM;
D3DXMatrixIdentity(&M);//M=单位矩阵
矩阵乘法函数:
D3DXMATRIX*D3DXMatrixMultiply(
D3DXMATRIX*pOut,
CONSTD3DXMATRIX*pM1,
CONSTD3DXMATRIX*pM2
);
pOut=pM1*pM2;
4、矩阵的基本变换
平移变换:
平移变换是对3D空间中某点P(x,y,z),分别沿X、Y、Z坐标轴平移dx、dy和dz个单位,那么点P平移后所处的位置的坐标可以通过以下公式计算:
如果将P点的坐标以3D齐次坐标表示(x,y,z,w=1),并且在计算新位置的坐标时,同时将齐次坐标的每个分量都参与计算,那么点坐标的计算公式就为:
然后将公式中除齐次坐标分量外的所有因子构成一个4×4的矩阵,那么就得到一个平移变换矩阵:
则:
对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,//返回平移后的矩阵.
FLOATx,//x轴移动的单位
FLOATy,//y轴移动的单位
FLOATz//z轴移动的单位
);
世界变换包括平移、旋转和缩放变换,可以通过D3DX库中D3DXMatrixTranslation、D3DXMatrixRotation*和D3DXMatrixSaling函数实施变换,并得到一个世界变换矩阵。
然后调用IDirect3DDevice9接口的SetTransform方法应用世界变换。
SetTransform方法的声明如下:
HRESULTIDirect3DDevice9:
:
SetTransform(
D3DTRANSFORMSTATETYPEState,//变换的类型
CONSTD3DMATRIX*pMatrix//应用的变换矩阵
);
其中,State参数是一个D3DTRANSFORMSTATETYPE枚举类型,用于表示应用变换的类型,其枚举值D3DTS_WORLD、D3DTS_VIEW、D3DTS_PROJECTION分别表示进行世界变换、取景变换和投影变换。
平移变换完整代码实例:
//=============================================================================
//Desc:
坐标变换
//=============================================================================
#include
#include//D3DX实用库函数,该头文件中又包含了d3d9.h头文件
//-----------------------------------------------------------------------------
//Desc:
全局变量
//-----------------------------------------------------------------------------
LPDIRECT3D9g_pD3D=NULL;//Direct3D对象
LPDIRECT3DDEVICE9g_pd3dDevice=NULL;//Direct3D设备对象
LPDIRECT3DVERTEXBUFFER9g_pVB=NULL;//顶点缓冲区对象
HWNDg_Wnd=NULL;//窗口句柄
//-----------------------------------------------------------------------------
//Desc:
顶点结构
//-----------------------------------------------------------------------------
structCUSTOMVERTEX
{
D3DXVECTOR3position;
DWORDcolor;
};
#defineD3DFVF_CUSTOMVERTEX(D3DFVF_XYZ|D3DFVF_DIFFUSE)
/*以下的观察变换、投影和视口变换*/
//-----------------------------------------------------------------------------
//Desc:
设置观察矩阵和投影矩阵
//-----------------------------------------------------------------------------
VOIDSetupViewandProjMatrices()
{
//建立并设置观察矩阵
D3DXVECTOR3vEyePt(0.0f,3.0f,-20.0f);
D3DXVECTOR3vLookatPt(0.0f,0.0f,0.0f);
D3DXVECTOR3vUpVec(0.0f,1.0f,0.0f);
D3DXMATRIXmatView;
D3DXMatrixLookAtLH(&matView,&vEyePt,&vLookatPt,&vUpVec);
g_pd3dDevice->SetTransform(D3DTS_VIEW,&matView);
//建立并设置投影矩阵
D3DXMATRIXmatProj;
D3DXMatrixPerspectiveFovLH(&matProj,D3DX_PI/4,1.0f,1.0f,100.0f);
g_pd3dDevice->SetTransform(D3DTS_PROJECTION,&matProj);
}
//-----------------------------------------------------------------------------
//Desc:
设置视区
//-----------------------------------------------------------------------------
VOIDSetupViewPort()
{
RECTrect;
GetClientRect(g_Wnd,&rect);
D3DVIEWPORT9vp;
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
//-----------------------------------------------------------------------------
HRESULTInitD3D(HWNDhWnd)
{
//创建Direct3D对象,该对象用于创建Direct3D设备对象
if(NULL==(g_pD3D=Direct3DCreate9(D3D_SDK_VERSION)))
returnE_FAIL;
//设置D3DPRESENT_PARAMETERS结构,准备创建Direct3D设备对象
D3DPRESENT_PARAMETERSd3dpp;
ZeroMemory(&d3dpp,sizeof(d3dpp));
d3dpp.Windowed=TRUE;
d3dpp.SwapEffect=D3DSWAPEFFECT_DISCARD;
d3dpp.BackBufferFormat=D3DFMT_UNKNOWN;
//创建Direct3D设备对象
if(FAILED(g_pD3D->CreateDevice(D3DADAPTER_DEFAULT,D3DDEVTYPE_HAL,hWnd,
D3DCREATE_SOFTWARE_VERTEXPROCESSING,
&d3dpp,&g_pd3dDevice)))
{
returnE_FAIL;
}
//设置剔出模式为不剔出任何面(正面和反面)
//g_pd3dDevice->SetRenderState(D3DRS_CULLMODE,D3DCULL_NONE);
//关闭光照处理,默认情况下启用光照处理
g_pd3dDevice->SetRenderState(D3DRS_LIGHTING,FALSE);
//设置观察和投影矩阵
SetupViewandProjMatrices();
//设置视区
SetupViewPort();
returnS_OK;
}
//-----------------------------------------------------------------------------
//Desc:
创建场景图形
//-----------------------------------------------------------------------------
HRESULTInitVB()
{
//顶点数据
CUSTOMVERTEXvertices[]=
{
{D3DXVECTOR3(1.0f,4.0f,0.5f),0xffff0000},
{D3DXVECTOR3(3.0f,5.0f,0.5f),0xf