天行健 君子当自强而不息

创建游戏内核(6)


本篇是 创建游戏内核(5)的续篇,其中涉及到矩阵以及坐标系统变换的知识请参阅DirectX 9的一些数学计算函数:矩阵,坐标变换。以及DirectX 9的坐标系统变换。

视口变换和CAMERA

CAMERA类和 WORLD_POSITION类非常类似,但CAMERA类处理的是视口变换矩阵。

来看看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类的实现:
 
//-------------------------------------------------------------------
// 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函数。Point函数用来确定观察点的方位并在瞬间将它指向一个特定的方向。

三个同追踪有关的函数随着时间追踪摄像机的移动路径。要使用摄像机追踪方位,将摄像机放到预想的起始位置并调用CAMERA:: Set_Start_Track,然后再将摄像机移动到预想的结束方位并调用CAMERA::Set_End_Track即可。

接下来需要调用CAMERA::Track函数(要在调用CAMERA::Update之前调用它)沿着创建的轨迹来定位摄像机。 Track函数的time_ratio参数的范围从0.0(起始方位)-1.0(结束方位),任何介于此范围内的值都会将摄像机沿着轨迹进行移动, time_length可以是任意起作用的值(举例来说,毫秒)。

摄像机追踪创建了一些很棒的效果,下面的示例说明了这一点:
 
    CAMERA camera;

    
// 移到位置(0.0, 100.0, -100.0)处并朝向原点
    camera.Point(0.0, 100.0, -100.0, 0.0, 0.0, 0.0);
    camera.Set_Start_Track();

    
// 移到结束方位
    camera.Point(-100.0, 0.0, 0.0, 0.0, 100.0, 0.0);
    camera.Set_End_Track();

    
// 每过10000毫秒将摄像机放置到起始方位和结束方位的一半处
    camera.Track(0.5, 10000);
    camera.Update();

posted on 2007-08-29 18:14 lovedday 阅读(333) 评论(0)  编辑 收藏 引用


只有注册用户登录后才能发表评论。
网站导航: 博客园   IT新闻   BlogJava   博问   Chat2DB   管理


公告

导航

统计

常用链接

随笔分类(178)

3D游戏编程相关链接

搜索

最新评论