HTML clipboard
HTML clipboard
世界坐標(biāo)系到攝影坐標(biāo)系的變換
攝影坐標(biāo)系的原點為世界坐標(biāo)系中的觀察位置eye點,z軸與觀察方向(從eye點出發(fā)到at點的向量)一致。
由于僅由一個坐標(biāo)原點的位置和一個z坐標(biāo)軸的方向不足以完全確定一個坐標(biāo)系,因此,還需要指定一個up向量來定位攝影坐標(biāo)系的y軸方向。這個在世界坐標(biāo)系中給出的up向量是不必與觀察方向垂直的,只是指明攝影坐標(biāo)系應(yīng)該以向上的方向還是以向下的方向作為y軸。
Builds a left-handed, look-at matrix.
D3DXMATRIX * D3DXMatrixLookAtLH(
D3DXMATRIX * pOut ,
CONST D3DXVECTOR3 * pEye ,
CONST D3DXVECTOR3 * pAt ,
CONST D3DXVECTOR3 * pUp
);
Parameters
- pOut
- [in, out] Pointer to the D3DXMATRIX structure that
is the result of the operation.
- pEye
- [in] Pointer to the D3DXVECTOR3 structure that
defines the eye point. This value is used in translation.
- pAt
- [in] Pointer to the D3DXVECTOR3 structure
that defines the camera look-at target.
- pUp
- [in] Pointer to the D3DXVECTOR3 structure
that defines the current world's up, usually [0, 1, 0].
Return Values
Pointer to a D3DXMATRIX structure that is a
left-handed, look-at matrix.
Remarks
The return value for this function is the same value
returned in the pOut parameter. In this way, the D3DXMatrixLookAtLH
function can be used as a parameter for another function.
This function uses the following formula to compute the
returned matrix.
zaxis = normal(At - Eye)
xaxis = normal(cross(Up, zaxis))
yaxis = cross(zaxis, xaxis)
xaxis.x yaxis.x zaxis.x 0
xaxis.y yaxis.y zaxis.y 0
xaxis.z yaxis.z zaxis.z 0
-dot(xaxis, eye) -dot(yaxis, eye) -dot(zaxis, eye) 1
要正確運行以下的示例程序,需要在工程中包含d3dx9.lib,或者在main函數(shù)前加入
#pragma comment(lib, "d3dx9.lib")
以指示編譯器鏈接d3dx9.lib。
代碼示例:
#include <d3dx9math.h>
#include <stdio.h>
#pragma warning(disable : 4305)
int main()
{
D3DXVECTOR3 p(3.0, 3.0, 3.0); // point with world coordinate
D3DXVECTOR3 eye(1.0, 0.0, 0.0); // camera position with world coordinate
D3DXVECTOR3 at(0.0, 0.0, 0.0); // look at target with world coordinate
D3DXVECTOR3 up(0.0, 1.0, 0.0); // define the current world's up
D3DXMATRIX m; // transform matrix from world coordinate to camera coordinate
// Builds a left-handed, look-at matrix.
D3DXMatrixLookAtLH(&m, &eye, &at, &up);
// print out matrix
printf(" |%f %f %f %f|\n", m._11, m._12, m._13, m._14);
printf(" |%f %f %f %f|\n", m._21, m._22, m._23, m._24);
printf("m =|%f %f %f %f|\n", m._31, m._32, m._33, m._34);
printf(" |%f %f %f %f|\n", m._41, m._42, m._43, m._44);
printf("\n\n\n");
D3DXVec3TransformCoord(&p, &p, &m);
printf("p(%f, %f, %f)", p.x, p.y, p.z);
printf("\n\n\n");
return 0;
}
輸出:
|0.000000 0.000000 -1.000000 0.000000|
|-0.000000 1.000000 0.000000 0.000000|
m = |1.000000 0.000000 0.000000 0.000000|
|-0.000000 -0.000000 1.000000 1.000000|
p(3.000000, 3.000000, -2.000000)
透視投影變換
為了顯示三維物體,必須將三維物體透視投影到平面上,以獲得一個二維的平面圖象,同時還要保存物體的深度信息(z軸上的位置信息)。
Builds a left-handed perspective projection matrix
based on a field of view.
D3DXMATRIX * D3DXMatrixPerspectiveFovLH(
D3DXMATRIX * pOut ,
FLOAT fovy ,
FLOAT Aspect ,
FLOAT zn ,
FLOAT zf
);
Parameters
- pOut
- [in, out] Pointer to the D3DXMATRIX structure that
is the result of the operation.
- fovy
- [in] Field of view in the y direction, in radians.
- Aspect
- [in] Aspect ratio, defined as view space width
divided by height.
- zn
- [in] Z-value of the near view-plane.
- zf
- [in] Z-value of the far view-plane.
Return Values
Pointer to a D3DXMATRIX structure that is a
left-handed perspective projection matrix.
Remarks
The return value for this function is the same value
returned in the pOut parameter. In this way, the D3DXMatrixPerspectiveFovLH
function can be used as a parameter for another function.
This function computes the returned matrix as shown:
xScale 0 0 0
0 yScale 0 0
0 0 zf/(zf-zn) 1
0 0 -zn*zf/(zf-zn) 0
where:
yScale = cot(fovY/2)
xScale = yScale / aspect ratio
視截體的平面計算
在世界坐標(biāo)系中選擇觀察者位置,并確定視角的方向和視線的遠(yuǎn)近距離,視截體的6個側(cè)面也就決定下來,由于三維物體一開始是在世界坐標(biāo)系中給出的,因此視截體在世界坐標(biāo)系中的6個平面的計算就顯得相當(dāng)重要,因為可由這6個視截體的平面法向量計算出世界空間中的哪些三維物體應(yīng)該顯示出來。
完全可以根據(jù)觀察者的坐標(biāo)位置、觀察視角的大小和遠(yuǎn)近平面的方位,直接計算出6個視截體平面在世界坐標(biāo)系中的方程。不過,DirectX并沒有直接提供一個函數(shù)來計算這些平面的方程,但可以根據(jù)攝影變換和透視投影變換矩陣,反向計算出視截體的各個平面在世界坐標(biāo)系中的方程。
世界空間中的視截體在攝影變換和透視投影變換后,變成攝影空間中的立方體[-1, 1] x [-1, 1] x [0,
1],即6個視截體平面的方程分別為x=-1,x=1,y=-1,y=1,z=0和z=1。
代碼示例:
#include <d3dx9math.h>
#include <stdio.h>
#pragma warning(disable : 4305)
int main()
{
// build camera reference frame
D3DXVECTOR3 eye(0.0, 0.0, 3.0); // camera position with world coordinate
D3DXVECTOR3 at(0.0, 0.0, 30.0); // look at target with world coordinate
D3DXVECTOR3 up(0.0, 1.0, 3.0); // define the current world's up
D3DXMATRIX view_matrix; // transform matrix from world coordinate to camera coordinate
// Builds a left-handed, look-at matrix.
D3DXMatrixLookAtLH(&view_matrix, &eye, &at, &up);
D3DXMATRIX proj_matrix;
// Builds a left-handed perspective projection matrix based on a field of view.
D3DXMatrixPerspectiveFovLH(&proj_matrix, D3DX_PI/3, 2.0, 2.0, 8.0);
printf("calculate frustum plane equation in world reference frame:\n\n");
D3DXMATRIX M = view_matrix * proj_matrix;
D3DXPLANE plane[6];
plane[0].a = M._11 + M._14;
plane[0].b = M._21 + M._24;
plane[0].c = M._31 + M._34;
plane[0].d = M._41 + M._44;
D3DXPlaneNormalize(&plane[0], &plane[0]);
printf("left plane equation: a=%f, b=%f, c=%f, d=%f\n\n", plane[0].a, plane[0].b, plane[0].c, plane[0].d);
plane[1].a = M._14 - M._11;
plane[1].b = M._24 - M._21;
plane[1].c = M._34 - M._31;
plane[1].d = M._44 - M._41;
D3DXPlaneNormalize(&plane[1], &plane[1]);
printf("right plane equation: a=%f, b=%f, c=%f, d=%f\n\n", plane[1].a, plane[1].b, plane[1].c, plane[1].d);
plane[2].a = M._14 - M._12;
plane[2].b = M._24 - M._22;
plane[2].c = M._34 - M._32;
plane[2].d = M._44 - M._42;
D3DXPlaneNormalize(&plane[2], &plane[2]);
printf("top plane equation: a=%f, b=%f, c=%f, d=%f\n\n", plane[2].a, plane[2].b, plane[2].c, plane[2].d);
plane[3].a = M._12 + M._14;
plane[3].b = M._22 + M._24;
plane[3].c = M._32 + M._34;
plane[3].d = M._42 + M._44;
D3DXPlaneNormalize(&plane[3], &plane[3]);
printf("bottom plane equation: a=%f, b=%f, c=%f, d=%f\n\n", plane[3].a, plane[3].b, plane[3].c, plane[3].d);
plane[4].a = M._13;
plane[4].b = M._23;
plane[4].c = M._33;
plane[4].d = M._43;
D3DXPlaneNormalize(&plane[4], &plane[4]);
printf("near plane equation: a=%f, b=%f, c=%f, d=%f\n\n", plane[4].a, plane[4].b, plane[4].c, plane[4].d);
plane[5].a = M._14 - M._13;
plane[5].b = M._24 - M._23;
plane[5].c = M._34 - M._33;
plane[5].d = M._44 - M._43;
D3DXPlaneNormalize(&plane[5], &plane[5]);
printf("far plane equation: a=%f, b=%f, c=%f, d=%f\n\n\n\n", plane[5].a, plane[5].b, plane[5].c, plane[5].d);
return 0;
}
輸出:
calculate frustum plane equation in world reference frame:
left plane equation: a=0.654654, b=0.000000, c=0.755929, d=-2.267787
right plane equation: a=-0.654654, b=0.000000, c=0.755929, d=-2.267787
top plane equation: a=0.000000, b=-0.866025, c=0.500000, d=-1.500000
bottom plane equation: a=0.000000, b=0.866025, c=0.500000, d=-1.500000
near plane equation: a=0.000000, b=0.000000, c=1.000000, d=-5.000000
far plane equation: a=0.000000, b=0.000000, c=-1.000000, d=11.000000
透視投影空間到屏幕視口的變換
視截體透視投影到[-1, -1] x [-1, 1] x [0, 1]立方體后,就需要將xy平面中的二維圖像變換到計算機(jī)的屏幕視口中進(jìn)行顯示,同時還將z軸[0,
1]變換為[min_z, max_z],這就是透視投影空間到視口的坐標(biāo)變換。對于DirectX來說,通常取min_z = 0和max_z =
1,即維持z軸的坐標(biāo)值不變。
在三維游戲開發(fā)中,一般使用D3DVIEWPORT9結(jié)構(gòu)體和 IDirect3DDevice9::SetViewport Method設(shè)置視口的區(qū)域。