1
//設置投影矩陣
2
/**//*
3
這部分雖然只有少數幾行,由于我的數學全丟給老師了,結果這里是我花時間最多的地方。
4
*/
5
void HGE_Impl::_SetProjectionMatrix(int width, int height)
6

{
7
D3DXMATRIX tmp;
8
/**//*
9
D3DXMatrixScaling產生的縮放矩陣是讓我不明白地方,實際上,它僅僅起到以X軸旋轉180度作用。
10
我將D3DXMatrixScaling換成D3DXMatrixRotationX(&matProj,D3DX_PI),結果不變。但這個小小的東西,造成了很大的誤解。
11
12
13
雖然選旋轉180度,再平移,再正交。但我們理解的順序,卻要完全反過來。
14
第一:重置坐標系,也就是用正交投影函數。在這里將坐標原點變成屏幕了左下角。這個Y軸向上,X軸向右
15
第二:平移,將原點向上平移屏幕的高度,這樣原點就變成左上角了。
16
第三:以X軸旋轉180度,這樣Y軸向下了。
17
經過這樣的變換后,我們就可以用我們習慣的屏幕坐了。
18
19
公式如下:
20
D3D的坐標矩陣 = 屏幕坐標矩陣* (旋轉矩陣 * 平移矩陣 * 正交矩陣) 注:這里的順序是不能變的
21
22
D3D的坐標矩陣是以屏幕中心為原點,x(-1,1),y(-1,1),z(0,1)的坐標系。
23
24
我們可以通過這個坐標系,可以坐標還原屏幕矩陣
25
公式如下:
26
X1為D3D坐標矩陣中的X,Y1為D3D坐標矩陣中的Y
27
X2為還原的還原屏幕X,Y2為還原的還原屏幕Y
28
X2 = (X1 + 1) * (WINDOW_WIDTH/2);
29
Y2 = WINDOW_HEIGHT - (Y1 + 1) * (WINDOW_HEIGHT/2);
30
結果你會發現,這個與你輸入的結果一樣。
31
32
另外,在平移過程中,HGE多平移了0.5個單位,這個應該和紋理有關,如果剛好全屏的紋理貼圖,可能邊緣會出現問題。
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
為了證實我理解正確,我用我實現的矩陣模板類,進行了驗證。矩陣的原代碼請參考我前面的隨筆矩陣C++實現模板
//設置投影矩陣2

/**//*3
這部分雖然只有少數幾行,由于我的數學全丟給老師了,結果這里是我花時間最多的地方。4
*/5
void HGE_Impl::_SetProjectionMatrix(int width, int height)6


{7
D3DXMATRIX tmp;8

/**//*9
D3DXMatrixScaling產生的縮放矩陣是讓我不明白地方,實際上,它僅僅起到以X軸旋轉180度作用。10
我將D3DXMatrixScaling換成D3DXMatrixRotationX(&matProj,D3DX_PI),結果不變。但這個小小的東西,造成了很大的誤解。11

12
13
雖然選旋轉180度,再平移,再正交。但我們理解的順序,卻要完全反過來。14
第一:重置坐標系,也就是用正交投影函數。在這里將坐標原點變成屏幕了左下角。這個Y軸向上,X軸向右15
第二:平移,將原點向上平移屏幕的高度,這樣原點就變成左上角了。16
第三:以X軸旋轉180度,這樣Y軸向下了。17
經過這樣的變換后,我們就可以用我們習慣的屏幕坐了。18

19
公式如下:20
D3D的坐標矩陣 = 屏幕坐標矩陣* (旋轉矩陣 * 平移矩陣 * 正交矩陣) 注:這里的順序是不能變的21
22
D3D的坐標矩陣是以屏幕中心為原點,x(-1,1),y(-1,1),z(0,1)的坐標系。23

24
我們可以通過這個坐標系,可以坐標還原屏幕矩陣25
公式如下:26
X1為D3D坐標矩陣中的X,Y1為D3D坐標矩陣中的Y27
X2為還原的還原屏幕X,Y2為還原的還原屏幕Y28
X2 = (X1 + 1) * (WINDOW_WIDTH/2);29
Y2 = WINDOW_HEIGHT - (Y1 + 1) * (WINDOW_HEIGHT/2);30
結果你會發現,這個與你輸入的結果一樣。31

32
另外,在平移過程中,HGE多平移了0.5個單位,這個應該和紋理有關,如果剛好全屏的紋理貼圖,可能邊緣會出現問題。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

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
}
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
}

