1 //設(shè)置投影矩陣 2 /**//* 3 這部分雖然只有少數(shù)幾行,由于我的數(shù)學(xué)全丟給老師了,結(jié)果這里是我花時間最多的地方。 4 */ 5 void HGE_Impl::_SetProjectionMatrix(int width, int height) 6  { 7 D3DXMATRIX tmp; 8 /**//* 9 D3DXMatrixScaling產(chǎn)生的縮放矩陣是讓我不明白地方,實際上,它僅僅起到以X軸旋轉(zhuǎn)180度作用。 10 我將D3DXMatrixScaling換成D3DXMatrixRotationX(&matProj,D3DX_PI),結(jié)果不變。但這個小小的東西,造成了很大的誤解。 11 12 13 雖然選旋轉(zhuǎn)180度,再平移,再正交。但我們理解的順序,卻要完全反過來。 14 第一:重置坐標(biāo)系,也就是用正交投影函數(shù)。在這里將坐標(biāo)原點變成屏幕了左下角。這個Y軸向上,X軸向右 15 第二:平移,將原點向上平移屏幕的高度,這樣原點就變成左上角了。 16 第三:以X軸旋轉(zhuǎn)180度,這樣Y軸向下了。 17 經(jīng)過這樣的變換后,我們就可以用我們習(xí)慣的屏幕坐了。 18 19 公式如下: 20 D3D的坐標(biāo)矩陣 = 屏幕坐標(biāo)矩陣* (旋轉(zhuǎn)矩陣 * 平移矩陣 * 正交矩陣) 注:這里的順序是不能變的 21 22 D3D的坐標(biāo)矩陣是以屏幕中心為原點,x(-1,1),y(-1,1),z(0,1)的坐標(biāo)系。 23 24 我們可以通過這個坐標(biāo)系,可以坐標(biāo)還原屏幕矩陣 25 公式如下: 26 X1為D3D坐標(biāo)矩陣中的X,Y1為D3D坐標(biāo)矩陣中的Y 27 X2為還原的還原屏幕X,Y2為還原的還原屏幕Y 28 X2 = (X1 + 1) * (WINDOW_WIDTH/2); 29 Y2 = WINDOW_HEIGHT - (Y1 + 1) * (WINDOW_HEIGHT/2); 30 結(jié)果你會發(fā)現(xiàn),這個與你輸入的結(jié)果一樣。 31 32 另外,在平移過程中,HGE多平移了0.5個單位,這個應(yīng)該和紋理有關(guān),如果剛好全屏的紋理貼圖,可能邊緣會出現(xiàn)問題。 33 */ 34 D3DXMatrixScaling(&matProj, 1.0f, -1.0f, 1.0f); 35 D3DXMatrixTranslation(&tmp, -0.5f, height+0.5f, 0.0f); 36 D3DXMatrixMultiply(&matProj, &matProj, &tmp); 37 D3DXMatrixOrthoOffCenterLH(&tmp, 0, (float)width, 0, (float)height, 0.0f, 1.0f); 38 D3DXMatrixMultiply(&matProj, &matProj, &tmp); 39 } 40
為了證實我理解正確,我用我實現(xiàn)的矩陣模板類,進(jìn)行了驗證。矩陣的原代碼請參考我前面的隨筆 矩陣C++實現(xiàn)模板
1 int main(int argc,char * argv) 2  { 3 FloatMatrix v1(4,4),v2(4,4),v3(4,4),v(4,4); 4 FloatMatrix p(1,4),p2(1,4); 5 XMatrixRotationX(&v1,X_PI); 6 XMatrixTranslation(&v2, 0.0f, 600.0f, 0.0f); 7 XMatrixOrthoOffCenterLH(&v3, 0, 800.0f, 0, 600.0f, 0.0f, 1.0f); 8 v = v1*v2*v3; 9 p.Clear(0.0f); 10 p(1,4) = 1.0f; 11 for(int x = 0; x <= 800; x+= 100) 12 { 13 for(int y = 0; y <= 600; y+= 50) 14 { 15 p(1,1) = (float)(rand()%800); 16 p(1,2) = (float)(rand()%600); 17 p2 = p * v; 18 p2(1,1) = (p2(1,1) + 1) * 400.0f; 19 p2(1,2) = 600- (p2(1,2) + 1) * 300.0f; 20 cout<<"Src("<<p(1,1)<<","<<p(1,2)<<") Dest=("<<p2(1,1)<<","<<p2(1,2)<<")"<<endl; 21 } 22 } 23 system("pause"); 24 return 0; 25 }
|