• 沒有找到結果。

場景繪製核心

在文檔中 虛擬寵物與市場設計實作 (頁 34-40)

第三章 虛擬寵物實作

3.3 場景繪製核心

第一人稱視角的移動

遊戲中玩家的視角是採用第一人稱視角,當玩家轉彎時,就要利 用對 Y 軸旋轉的旋轉矩陣作視界轉換。而當玩家移動時,就要利用對 軸、Z 軸位移的位移矩陣作視界轉換,才能改變玩家所看到的畫面。

下面的旋轉矩陣將原來的點(x、y、z)繞 Y 軸旋轉θ角:

下面的位移矩陣將點(x、y、z)移動到新的點(x', y', z'),T 是 位移量:

然後依據使用者的輸入改變視界矩陣:

D3DXMATRIX matView;

if( m_UserInput.bRotateLeft

&& !m_UserInput.bRotateRight ) //往左轉 {

m_fTheta += m_fRotSpeed; //旋轉角度 //建立旋轉矩陣

D3DXMatrixRotationY( &matView,

D3DXToRadian(-m_fRotSpeed));

//作用旋轉矩陣

D3DXVec3TransformNormal(

&m_vecCurLookAt,

&(m_vecCurLookAt-m_vecCurLoc),

&matView );

m_vecCurLookAt += m_vecCurLoc;

}

else if( m_UserInput.bRotateRight

&& !m_UserInput.bRotateLeft ) //往右轉 {

m_fTheta -= m_fRotSpeed; //旋轉角度 //建立旋轉矩陣

D3DXMatrixRotationY( &matView,

D3DXToRadian(m_fRotSpeed) );

//作用旋轉矩陣

D3DXVec3TransformNormal(

&m_vecCurLookAt,

&(m_vecCurLookAt-m_vecCurLoc),

&matView );

m_vecCurLookAt += m_vecCurLoc;

}

if( m_UserInput.bRotateUp

&& !m_UserInput.bRotateDown ) //往前移動 {

//位移

D3DXVECTOR3 offset = D3DXVECTOR3(

m_fMoveSpeed*cosf(D3DXToRadian(m_fTheta)), 0.0f,

m_fMoveSpeed*sinf(D3DXToRadian(m_fTheta)) );

m_vecCurLoc += offset;

m_vecCurLookAt += offset;

}

else if( m_UserInput.bRotateDown

&& !m_UserInput.bRotateUp ) //往後移動

{

D3DXVECTOR3 offset = D3DXVECTOR3(

m_fMoveSpeed*cosf(D3DXToRadian(m_fTheta)), 0.0f,

m_fMoveSpeed*sinf(D3DXToRadian(m_fTheta)) );

m_vecCurLoc -= offset;

m_vecCurLookAt -= offset;

}

//產生視界轉換矩陣

D3DXMatrixLookAtLH( &matView, &m_vecCurLoc,

&m_vecCurLookAt, &m_vecUp );

//設定觀測矩陣

m_pd3dDevice->SetTransform( D3DTS_VIEW, &matView );

3D 場景建構

在場景的建立方面,為了讓繪製的場景更真實,我們在 3D 物件上 使用貼圖來模擬真實視界所看到的影像及環境。

要使用貼圖首先必須指定貼圖座標。所謂貼圖就是一個 2 維的色 彩值陣列。陣列中的每個元素都有一個唯一的貼圖位址,基本上就是 行和列的位址,分別定義成 u(列)和 v(行)。這個位址稱為貼圖座 標,是以貼圖本身的座標空間來表示的。在貼圖空間中的位址則是相 對於貼圖原點。Direct3D 要求貼圖中的所有貼圖圖素都用統一的位址 範圍,才能把貼圖圖素對應到物件上。為了達成這個目的,Direct3D 使用正規化的位址體系。

struct ThreeDVERTEX {

D3DXVECTOR3 position; //頂點座標 D3DCOLOR color; //色彩 FLOAT tu,tv; //貼圖座標

#define D3DFVF_ThreeDVERTEX (D3DFVF_XYZ|D3DFVF_DIF FUSE|D3DFVF_TEX1)

ThreeDVERTEX* pVertices;

//需先鎖定才能填入模型資料

if( FAILED( hr = m_pVB->Lock( 0, 0,

(BYTE**)&pVertices, 0 ) ) ) return DXTRACE_ERR_NOMSGBOX( "Lock", hr );

// 建立一個地板模型

FLOAT range = m_fRight - m_fLeft; //地板範圍 for( int i=0; i<4; i++ )

{

//一個四方形的地板

pVertices[i].position = D3DXVECTOR3(

(float)pow(-1,i/2)*-range*5.0f, 0.0f,

(float)pow(-1,i+1)*range*5.0f );

pVertices[i].color = 0xffffffff;

pVertices[i].tu = (i/2)*range*2.0f;

pVertices[i].tv = ((i+1)%2)*range*2.0f;

}

// 建立樹木模型

for( i=4; i<8; i++ ) {

pVertices[i].position = D3DXVECTOR3(

0.0f,

(i%2)*3.02f*2.0f,

(float)pow(-1,i/2)*1.33f*2.0f );

pVertices[i].color = 0xffffffff;

pVertices[i].tu = ((i-4)/2)*1.0f;

}

//讀入草地貼圖檔案

D3DXCreateTextureFromFile( pd3dDevice,

"草皮.jpg",

&m_pTexture[0] );

//讀入樹木貼圖檔案

D3DXCreateTextureFromFile( pd3dDevice,

"tree02S.tga",

&m_pTreeTexture //設定世界轉換

D3DXMatrixIdentity( &matWorld );

pd3dDevice->SetTransform( D3DTS_WORLD,

&matWorld );

//指定貼圖

pd3dDevice->SetTexture( 0, m_pTexture[0] );

//繪製地板模型

pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 0, 2 );

//設定 ALPHA 混合透明

pd3dDevice->SetRenderState( D3DRS_ALPHABLENDENABLE , TRUE );

//設定 ALPHA 型態

pd3dDevice->SetRenderState( D3DRS_SRCBLEND

, D3DBLEND_SRCALPHA );

pd3dDevice->SetRenderState( D3DRS_DESTBLEND

, D3DBLEND_INVSRCALPHA );

//設定 ALPHA TEST

pd3dDevice->SetRenderState( D3DRS_ALPHATESTENABLE , TRUE );

//設定 ALPHA 值

pd3dDevice->SetRenderState( D3DRS_ALPHAREF , 0x08 );

, D3DCMP_GREATEREQUAL );

//繪製樹木

pd3dDevice->SetTexture( 0, m_pTreeTexture );

for( int j=0 ; j<40 ; j++ ) {

//讓樹木面向畫面繪製

D3DXMatrixRotationY( &matRotWorld,

-D3DXToRadian( theta ) );

//根據隨機值改變樹木的位置

D3DXMatrixTranslation( &matWorld, TreeLoc[j].x, 0.0f,

TreeLoc[j].z );

D3DXMatrixMultiply( &matWorld,

&matRotWorld,

&matWorld );

//設定世界矩陣

pd3dDevice->SetTransform( D3DTS_WORLD,

&matWorld );

//繪製

pd3dDevice->DrawPrimitive( D3DPT_TRIANGLESTRIP, 8, 2 );

D3DXMatrixIdentity( &matWorld );

pd3dDevice->SetTransform( D3DTS_WORLD,

&matWorld );

}

在文檔中 虛擬寵物與市場設計實作 (頁 34-40)

相關文件