本篇是
創(chuàng)建游戲內(nèi)核(5)的續(xù)篇,其中涉及到矩陣以及坐標(biāo)系統(tǒng)變換的知識(shí)請(qǐng)參閱
DirectX
9的一些數(shù)學(xué)計(jì)算函數(shù):矩陣,坐標(biāo)變換。以及
DirectX
9的坐標(biāo)系統(tǒng)變換。
視口變換和CAMERA
CAMERA類和 WORLD_POSITION類非常類似,但CAMERA類處理的是視口變換矩陣。
來(lái)看看CAMERA類的定義:
//================================================================================
// Defines for class CAMERA.
//================================================================================
class CAMERA
{
protected:
float _x_pos, _y_pos, _z_pos; // camera current position
float _x_rot, _y_rot, _z_rot; // camera current rotation
float _start_x_pos, _start_y_pos, _start_z_pos; // start tracking position
float _start_x_rot, _start_y_rot, _start_z_rot; // start tracking rotation
float _end_x_pos, _end_y_pos, _end_z_pos; // end tracking position
float _end_x_rot, _end_y_rot, _end_z_rot; // end tracking rotation
D3DXMATRIX _mat_world; // world transform matrix
D3DXMATRIX _mat_translation; // translation matrix
D3DXMATRIX _mat_rotation; // rotation matrix
public:
CAMERA();
D3DXMATRIX* Get_Matrix();
void Update();
void Move(float x_pos, float y_pos, float z_pos);
void Move_Rel(float x_add, float y_add, float z_add);
void Rotate(float x_rot, float y_rot, float z_rot);
void Rotate_Rel(float x_add, float y_add, float z_add);
void Point(float x_eye, float y_eye, float z_eye, float x_at, float y_at, float z_at);
void Set_Start_Track();
void Set_End_Track();
void Track(float time_ratio, float time_length);
float Get_X_Pos();
float Get_Y_Pos();
float Get_Z_Pos();
float Get_X_Rotation();
float Get_Y_Rotation();
float Get_Z_Rotation();
};
接著是CAMERA類的實(shí)現(xiàn):
//-------------------------------------------------------------------
// Constructor, initialize camera's current position and rotation.
//-------------------------------------------------------------------
CAMERA::CAMERA()
{
Move(0.0, 0.0, 0.0);
Rotate(0.0, 0.0, 0.0);
Update();
}
//-------------------------------------------------------------------
// Move camera to new position.
//-------------------------------------------------------------------
void CAMERA::Move(float x_pos, float y_pos, float z_pos)
{
_x_pos = x_pos; _y_pos = y_pos; _z_pos = z_pos;
D3DXMatrixTranslation(&_mat_translation, -x_pos, -y_pos, -z_pos);
}
//-------------------------------------------------------------------
// Move camera to new positoin which is summed by current position and
// added position.
//-------------------------------------------------------------------
void CAMERA::Move_Rel(float x_add, float y_add, float z_add)
{
Move(_x_pos + x_add, _y_pos + y_add, _z_pos + z_add);
}
//-------------------------------------------------------------------
// Build rotation matrix.
//-------------------------------------------------------------------
void CAMERA::Rotate(float x_rot, float y_rot, float z_rot)
{
D3DXMATRIX mat_x_rot, mat_y_rot, mat_z_rot;
_x_rot = x_rot; _y_rot = y_rot; _z_rot = z_rot;
D3DXMatrixRotationX(&mat_x_rot, -x_rot);
D3DXMatrixRotationX(&mat_y_rot, -y_rot);
D3DXMatrixRotationX(&mat_z_rot, -z_rot);
_mat_rotation = mat_z_rot;
D3DXMatrixMultiply(&_mat_rotation, &_mat_rotation, &mat_y_rot);
D3DXMatrixMultiply(&_mat_rotation, &_mat_rotation, &mat_x_rot);
}
//-------------------------------------------------------------------
// Build rotation matrix which is summed by current rotation value
// and added rotation value.
//-------------------------------------------------------------------
void CAMERA::Rotate_Rel(float x_add, float y_add, float z_add)
{
Rotate(_x_rot + x_add, _y_rot + y_add, _z_rot + z_add);
}
//-------------------------------------------------------------------
// Move camera to new position and look at new target position.
//-------------------------------------------------------------------
void CAMERA::Point(float x_eye, float y_eye, float z_eye, float x_at, float y_at, float z_at)
{
// Calculate angles between points
float x_diff = x_at - x_eye;
float y_diff = y_at - y_eye;
float z_diff = z_at - z_eye;
float x_rot = (float) atan2(-y_diff, sqrt(x_diff * x_diff + z_diff * z_diff));
float y_rot = (float) atan2(x_diff, z_diff);
// Move camera to new position and look at new target
Move(x_eye, y_eye, z_eye);
Rotate(x_rot, y_rot, 0.0);
}
//-------------------------------------------------------------------
// Set camera's start tracking position and rotation.
//-------------------------------------------------------------------
void CAMERA::Set_Start_Track()
{
_start_x_pos = _x_pos; _start_y_pos = _y_pos; _start_z_pos = _z_pos;
_start_x_rot = _x_rot; _start_y_rot = _y_rot; _start_z_rot = _z_rot;
}
//-------------------------------------------------------------------
// Set camera's end tracking position and rotation.
//-------------------------------------------------------------------
void CAMERA::Set_End_Track()
{
_end_x_pos = _x_pos; _end_y_pos = _y_pos; _end_z_pos = _z_pos;
_end_x_rot = _x_rot; _end_y_rot = _y_rot; _end_z_rot = _z_rot;
}
//-------------------------------------------------------------------
// Move camera to new position and ratation by giving time,
// 0 <= time_ratio <= 1.
//-------------------------------------------------------------------
void CAMERA::Track(float time_ratio, float time_length)
{
float time_offset = time_length * time_ratio;
float x = (_end_x_pos - _start_x_pos) / time_length * time_offset;
float y = (_end_y_pos - _start_y_pos) / time_length * time_offset;
float z = (_end_z_pos - _start_z_pos) / time_length * time_offset;
Move(_start_x_pos + x, _start_y_pos + y, _start_z_pos + z);
x = (_end_x_rot - _start_x_rot) / time_length * time_offset;
y = (_end_y_rot - _start_y_rot) / time_length * time_offset;
z = (_end_z_rot - _start_z_rot) / time_length * time_offset;
Rotate(_start_x_rot + x, _start_y_rot + y, _start_z_rot + z);
}
//-------------------------------------------------------------------
// Update new camera world transform matrix.
//-------------------------------------------------------------------
void CAMERA::Update()
{
D3DXMatrixMultiply(&_mat_world, &_mat_translation, &_mat_rotation);
}
//-------------------------------------------------------------------
// Get camera world transform matrix.
//-------------------------------------------------------------------
D3DXMATRIX* CAMERA::Get_Matrix()
{
Update();
return &_mat_world;
}
//-------------------------------------------------------------------
// Get camera current position (x coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_X_Pos()
{
return _x_pos;
}
//-------------------------------------------------------------------
// Get camera current position (y coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_Y_Pos()
{
return _y_pos;
}
//-------------------------------------------------------------------
// Get camera current position (z coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_Z_Pos()
{
return _z_pos;
}
//-------------------------------------------------------------------
// Get camera current rotation (x coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_X_Rotation()
{
return _x_rot;
}
//-------------------------------------------------------------------
// Get camera current rotation (y coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_Y_Rotation()
{
return _y_rot;
}
//-------------------------------------------------------------------
// Get camera current rotation (z coordinate).
//-------------------------------------------------------------------
float CAMERA::Get_Z_Rotation()
{
return _z_rot;
}
CAMERA類和WORLD_POSITION類惟一的不同就是加上了Point、Set_Start_Track、
Set_End_Track以及Track函數(shù)。Point函數(shù)用來(lái)確定觀察點(diǎn)的方位并在瞬間將它指向一個(gè)特定的方向。
三個(gè)同追蹤有關(guān)的函數(shù)隨著時(shí)間追蹤攝像機(jī)的移動(dòng)路徑。要使用攝像機(jī)追蹤方位,將攝像機(jī)放到預(yù)想的起始位置并調(diào)用CAMERA::
Set_Start_Track,然后再將攝像機(jī)移動(dòng)到預(yù)想的結(jié)束方位并調(diào)用CAMERA::Set_End_Track即可。
接下來(lái)需要調(diào)用CAMERA::Track函數(shù)(要在調(diào)用CAMERA::Update之前調(diào)用它)沿著創(chuàng)建的軌跡來(lái)定位攝像機(jī)。
Track函數(shù)的time_ratio參數(shù)的范圍從0.0(起始方位)-1.0(結(jié)束方位),任何介于此范圍內(nèi)的值都會(huì)將攝像機(jī)沿著軌跡進(jìn)行移動(dòng),
time_length可以是任意起作用的值(舉例來(lái)說(shuō),毫秒)。
攝像機(jī)追蹤創(chuàng)建了一些很棒的效果,下面的示例說(shuō)明了這一點(diǎn):
CAMERA camera;
// 移到位置(0.0, 100.0, -100.0)處并朝向原點(diǎn)
camera.Point(0.0, 100.0, -100.0, 0.0, 0.0, 0.0);
camera.Set_Start_Track();
// 移到結(jié)束方位
camera.Point(-100.0, 0.0, 0.0, 0.0, 100.0, 0.0);
camera.Set_End_Track();
// 每過(guò)10000毫秒將攝像機(jī)放置到起始方位和結(jié)束方位的一半處
camera.Track(0.5, 10000);
camera.Update();