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

6



7

8


9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

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
}

2



3

4

5

6

7

8

9

10

11

12



13

14



15

16

17

18

19

20

21

22

23

24

25
