本篇是创建游戏内核(5)【C风格版】的续篇,关于该内核的细节说明请参考创建游戏内核(6)。
接口:
typedef struct CAMERA
{
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_view; // world transform matrix
D3DXMATRIX mat_translation; // translation matrix
D3DXMATRIX mat_rotation; // rotation matrix
} *CAMERA_PTR;
CAMERA_PTR create_camera();
void destroy_camera(CAMERA_PTR camera);
void move_camera(CAMERA_PTR camera,
float x_pos, float y_pos, float z_pos);
void move_camera_rel(CAMERA_PTR camera,
float x_add, float y_add, float z_add);
void rotate_camera(CAMERA_PTR camera,
float x_rot, float y_rot, float z_rot);
void point_camera(CAMERA_PTR camera,
float x_eye, float y_eye, float z_eye,
float x_at, float y_at, float z_at);
void start_track_camera(CAMERA_PTR camera);
void end_track_camera(CAMERA_PTR camera);
void track_camera(CAMERA_PTR camera, float time_ratio);
void update_camera_pos(CAMERA_PTR camera);
实现:
//----------------------------------------------------------------------------------------
// Create camera.
//----------------------------------------------------------------------------------------
CAMERA_PTR create_camera()
{
CAMERA_PTR camera = (CAMERA_PTR) malloc(sizeof(CAMERA));
memset(camera, 0, sizeof(CAMERA));
return camera;
}
//----------------------------------------------------------------------------------------
// Destroy camera.
//----------------------------------------------------------------------------------------
void destroy_camera(CAMERA_PTR camera)
{
free(camera);
}
//----------------------------------------------------------------------------------------
// move camera to new position.
//----------------------------------------------------------------------------------------
void move_camera(CAMERA_PTR camera,
float x_pos, float y_pos, float z_pos)
{
camera->x_pos = x_pos;
camera->y_pos = y_pos;
camera->z_pos = z_pos;
D3DXMatrixTranslation(&camera->mat_translation, -x_pos, -y_pos, -z_pos);
}
//----------------------------------------------------------------------------------------
// Move camera to new position relative to current position.
//----------------------------------------------------------------------------------------
void move_camera_rel(CAMERA_PTR camera,
float x_add, float y_add, float z_add)
{
move_camera(camera,
camera->x_pos + x_add, camera->y_pos + y_add, camera->z_pos + z_add);
}
//-------------------------------------------------------------------------
// rotate camera.
//-------------------------------------------------------------------------
void rotate_camera(CAMERA_PTR camera,
float x_rot, float y_rot, float z_rot)
{
D3DXMATRIX mat_x_rot, mat_y_rot, mat_z_rot;
camera->x_rot = x_rot;
camera->y_rot = y_rot;
camera->z_rot = z_rot;
D3DXMatrixRotationX(&mat_x_rot, -x_rot);
D3DXMatrixRotationY(&mat_y_rot, -y_rot);
D3DXMatrixRotationZ(&mat_z_rot, -z_rot);
camera->mat_rotation = mat_z_rot;
D3DXMatrixMultiply(&camera->mat_rotation, &camera->mat_rotation, &mat_y_rot);
D3DXMatrixMultiply(&camera->mat_rotation, &camera->mat_rotation, &mat_x_rot);
}
//-------------------------------------------------------------------------
// rotate camera.
//-------------------------------------------------------------------------
void rotate_camera_rel(CAMERA_PTR camera,
float x_add, float y_add, float z_add)
{
rotate_camera(camera,
camera->x_pos + x_add, camera->y_pos + y_add, camera->z_pos + z_add);
}
//-------------------------------------------------------------------------
// move camera to new position and look at new target position.
//-------------------------------------------------------------------------
void point_camera(CAMERA_PTR camera,
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_camera(camera, x_eye, y_eye, z_eye);
rotate_camera(camera, x_rot, y_rot, 0.0);
}
//-------------------------------------------------------------------------
// set camera's start tracking position and rotation.
//-------------------------------------------------------------------------
void start_track_camera(CAMERA_PTR camera)
{
camera->start_x_pos = camera->x_pos;
camera->start_y_pos = camera->y_pos;
camera->start_z_pos = camera->z_pos;
camera->start_x_rot = camera->x_rot;
camera->start_y_rot = camera->y_rot;
camera->start_z_rot = camera->z_rot;
}
//-------------------------------------------------------------------------
// set camera's end tracking position and rotation.
//-------------------------------------------------------------------------
void end_track_camera(CAMERA_PTR camera)
{
camera->end_x_pos = camera->x_pos;
camera->end_y_pos = camera->y_pos;
camera->end_z_pos = camera->z_pos;
camera->end_x_rot = camera->x_rot;
camera->end_y_rot = camera->y_rot;
camera->end_z_rot = camera->z_rot;
}
//-------------------------------------------------------------------------
// move camera to new position and ratation by giving time,
// 0 <= time_ratio <= 1.
//-------------------------------------------------------------------------
void track_camera(CAMERA_PTR camera, float time_ratio)
{
float x_move = (camera->end_x_pos - camera->start_x_pos) * time_ratio;
float y_move = (camera->end_y_pos - camera->start_y_pos) * time_ratio;
float z_move = (camera->end_z_pos - camera->start_z_pos) * time_ratio;
move_camera(camera,
camera->start_x_pos + x_move, camera->start_y_pos + y_move, camera->start_z_pos + z_move);
float x_rotate = (camera->end_x_rot - camera->start_x_rot) * time_ratio;
float y_rotate = (camera->end_y_rot - camera->start_y_rot) * time_ratio;
float z_rotate = (camera->end_z_rot - camera->start_z_rot) * time_ratio;
rotate_camera(camera,
camera->start_x_rot + x_rotate, camera->start_y_rot + y_rotate, camera->start_z_rot + z_rotate);
}
//-------------------------------------------------------------------------
// update new camera world transform matrix.
//-------------------------------------------------------------------------
void update_camera_pos(CAMERA_PTR camera)
{
D3DXMatrixMultiply(&camera->mat_view, &camera->mat_translation, &camera->mat_rotation);
}