本篇是创建游戏内核(4)【C风格版】的续篇,关于该内核的细节说明请参考创建游戏内核(5)。
接口:
typedef struct WORLD_POS
{
BOOL use_billboard; // flag indicates whether use billboard
float x_pos, y_pos, z_pos; // current position
float x_rot, y_rot, z_rot; // cuurent rotation
float x_scale, y_scale, z_scale; // current scale value
D3DXMATRIX mat_world; // world transform matrix
D3DXMATRIX mat_scale; // scale matrix
D3DXMATRIX mat_rotation; // rotation matrix
D3DXMATRIX mat_translation; // translation matrix
D3DXMATRIX* mat_combine_1; // pointer to combination matrix 1
D3DXMATRIX* mat_combine_2; // pointer to combination matrix 2
} *WORLD_POS_PTR;
WORLD_POS_PTR create_world_pos();
void destroy_world_pos(WORLD_POS_PTR world_pos);
void clone_world_pos(WORLD_POS_PTR dest, const WORLD_POS_PTR source);
void move_world_pos(WORLD_POS_PTR world_pos,
float x_pos, float y_pos, float z_pos);
void move_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add);
void rotate_world_pos(WORLD_POS_PTR world_pos,
float x_rot, float y_rot, float z_rot);
void rotate_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add);
void scale_world_pos(WORLD_POS_PTR world_pos,
float x_scale, float y_scale, float z_scale);
void scale_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add);
void update_world_pos(WORLD_POS_PTR world_pos);
实现:
//-------------------------------------------------------------------------
// create world position object.
//-------------------------------------------------------------------------
WORLD_POS_PTR create_world_pos()
{
WORLD_POS_PTR world_pos = (WORLD_POS_PTR) malloc(sizeof(WORLD_POS));
memset(world_pos, 0, sizeof(WORLD_POS));
world_pos->use_billboard = TRUE;
world_pos->x_scale = world_pos->y_scale = world_pos->z_scale = 1.0f;
update_world_pos(world_pos);
return world_pos;
}
//-------------------------------------------------------------------------
// destroy world position object.
//-------------------------------------------------------------------------
void destroy_world_pos(WORLD_POS_PTR world_pos)
{
free(world_pos);
}
//-------------------------------------------------------------------------
// clone world position information to another world position object.
//-------------------------------------------------------------------------
void clone_world_pos(WORLD_POS_PTR dest, const WORLD_POS_PTR source)
{
move_world_pos(dest, source->x_pos, source->y_pos, source->z_pos);
rotate_world_pos(dest, source->x_rot, source->y_rot, source->z_rot);
scale_world_pos(dest, source->x_scale, source->y_scale, source->z_scale);
dest->use_billboard = source->use_billboard;
}
//-------------------------------------------------------------------------
// move to new world position with specified relative value.
//-------------------------------------------------------------------------
void move_world_pos(WORLD_POS_PTR world_pos,
float x_pos, float y_pos, float z_pos)
{
world_pos->x_pos = x_pos;
world_pos->y_pos = y_pos;
world_pos->z_pos = z_pos;
D3DXMatrixTranslation(&world_pos->mat_translation, x_pos, y_pos, z_pos);
}
//-------------------------------------------------------------------------
// move to new world position which relative to current position.
//-------------------------------------------------------------------------
void move_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add)
{
move_world_pos(world_pos,
world_pos->x_pos + x_add, world_pos->y_pos + y_add, world_pos->z_pos + z_add);
}
//-------------------------------------------------------------------------
// rotate around x, y, z, axis with specified degree.
//-------------------------------------------------------------------------
void rotate_world_pos(WORLD_POS_PTR world_pos,
float x_rot, float y_rot, float z_rot)
{
world_pos->x_rot = x_rot;
world_pos->y_rot = y_rot;
world_pos->z_rot = z_rot;
// Builds a matrix with a specified yaw, pitch, and roll.
D3DXMatrixRotationYawPitchRoll(&world_pos->mat_rotation, y_rot, x_rot, z_rot);
}
//-------------------------------------------------------------------------
// rotate around x, y, z, axis which relative to cuurent x, y, z angle.
//-------------------------------------------------------------------------
void rotate_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add)
{
rotate_world_pos(world_pos,
world_pos->x_rot + x_add, world_pos->y_rot + y_add, world_pos->z_rot + z_add);
}
//-------------------------------------------------------------------------
// Scale world position.
//-------------------------------------------------------------------------
void scale_world_pos(WORLD_POS_PTR world_pos,
float x_scale, float y_scale, float z_scale)
{
world_pos->x_scale = x_scale;
world_pos->y_scale = y_scale;
world_pos->z_scale = z_scale;
D3DXMatrixScaling(&world_pos->mat_scale, x_scale, y_scale, z_scale);
}
//-------------------------------------------------------------------------
// Scale world position which relative to current scale value.
//-------------------------------------------------------------------------
void scale_world_pos_rel(WORLD_POS_PTR world_pos,
float x_add, float y_add, float z_add)
{
scale_world_pos(world_pos,
world_pos->x_pos + x_add, world_pos->y_pos + y_add, world_pos->z_pos + z_add);
}
//-------------------------------------------------------------------------
// Update world transformation matrix.
//-------------------------------------------------------------------------
void update_world_pos(WORLD_POS_PTR world_pos)
{
D3DXMATRIX mat_view, mat_transposed;
// setup billboarding matrix
if(world_pos->use_billboard)
{
g_d3d_device->GetTransform(D3DTS_VIEW, &mat_view);
D3DXMatrixTranspose(&mat_transposed, &mat_view);
mat_transposed._41 = mat_transposed._42 = mat_transposed._43 = 0.0;
mat_transposed._14 = mat_transposed._24 = mat_transposed._34 = 0.0;
}
// combine scaling and rotation matrices first
D3DXMatrixMultiply(&world_pos->mat_world, &world_pos->mat_scale, &world_pos->mat_rotation);
// apply billboard matrix
if(world_pos->use_billboard)
D3DXMatrixMultiply(&world_pos->mat_world, &world_pos->mat_world, &mat_transposed);
// combine with translation matrix
D3DXMatrixMultiply(&world_pos->mat_world, &world_pos->mat_world, &world_pos->mat_translation);
// combine with combined matrices (if any)
if(world_pos->mat_combine_1)
D3DXMatrixMultiply(&world_pos->mat_world, &world_pos->mat_world, world_pos->mat_combine_1);
if(world_pos->mat_combine_2)
D3DXMatrixMultiply(&world_pos->mat_world, &world_pos->mat_world, world_pos->mat_combine_2);
}