一.帧/帧时刻
? ? ?在常见的FPS游戏中,人物的行走,物体的变形等等都是采用动画的方式实现.计算机2D屏幕采用扫描周期的方式定时刷新渲染管线,C++程序通过定义帧/帧时刻实现每一帧的渲染,不同的帧衔接起来便是一个完整的动画.
? ? Direct3D提供API实现2D屏幕的重绘:
D3DDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.0f, 0);//清理GPU渲染管线
d3dDevice->BeginScene();
D3DDevice->EndScene();
D3DDevice->Present(NULL, NULL, NULL, NULL); //写入GPU渲染管线
二.顶点动画
? ? ?通过在不同帧时刻加载不同的静态模型实现的动画既顶点动画,所以顶点动画是不同帧时刻的静态模型的组合.游戏引擎可选择性将帧与帧之间的顶点进行插值运算实现连续性效果.
? ? ?顶点动画 = obj1(time1) + obj2(time2) + obj3(time3)
? ? ?故不同的游戏引擎导出的顶点动画最终是obj静态模型的组合.如常见M3D顶点动画3D文件,数据结构就是不同frame的静态模型组合MD3FileData.h:
// -------------------------------------------------------------------------------
/** @brief Data structure for the MD3 main header
*/
struct Header
{
//! magic number
uint32_t IDENT;
//! file format version
uint32_t VERSION;
//! original name in .pak archive
char NAME[ AI_MD3_MAXQPATH ];
//! unknown
int32_t FLAGS;
//! number of frames in the file
uint32_t NUM_FRAMES;
//! number of tags in the file
uint32_t NUM_TAGS;
//! number of surfaces in the file
uint32_t NUM_SURFACES;
//! number of skins in the file
uint32_t NUM_SKINS;
//! offset of the first frame
uint32_t OFS_FRAMES;
//! offset of the first tag
uint32_t OFS_TAGS;
//! offset of the first surface
uint32_t OFS_SURFACES;
//! end of file
uint32_t OFS_EOF;
} PACK_STRUCT;
// -------------------------------------------------------------------------------
/** @brief Data structure for the frame header
*/
struct Frame
{
//! minimum bounds
aiVector3D min;
//! maximum bounds
aiVector3D max;
//! local origin for this frame
aiVector3D origin;
//! radius of bounding sphere
ai_real radius;
//! name of frame
char name[ AI_MD3_MAXFRAME ];
} /* PACK_STRUCT */;
// -------------------------------------------------------------------------------
/** @brief Data structure for the surface header
*/
struct Surface {
//! magic number
int32_t IDENT;
//! original name of the surface
char NAME[ AI_MD3_MAXQPATH ];
//! unknown
int32_t FLAGS;
//! number of frames in the surface
uint32_t NUM_FRAMES;
//! number of shaders in the surface
uint32_t NUM_SHADER;
//! number of vertices in the surface
uint32_t NUM_VERTICES;
//! number of triangles in the surface
uint32_t NUM_TRIANGLES;
//! offset to the triangle data
uint32_t OFS_TRIANGLES;
//! offset to the shader data
uint32_t OFS_SHADERS;
//! offset to the texture coordinate data
uint32_t OFS_ST;
//! offset to the vertex/normal data
uint32_t OFS_XYZNORMAL;
//! offset to the end of the Surface object
int32_t OFS_END;
} /*PACK_STRUCT*/;
三.骨骼动画
? ? 通过预先将静态模型拆分成若干顶点组(骨骼),每一帧通过每个骨骼的变换矩阵运算后得到新的obj静态模型既骨骼动画.所需内存相比顶点动画内存占用更小.适用连续性动作制作.
? ? 骨骼动画 = (bone1×变换矩阵1 + bone2×变换矩阵2)(time1) + (bone1×变换矩阵3?+ bone2×变换矩阵4)(time2).
? ? 如常见的FBX,DAE文件存储骨骼动画采用将每一帧的变换矩阵进行封装存储,FBXDocument.h:
namespace FBX {
class AnimationCurve;
class AnimationCurveNode; //顶点组节点
class AnimationLayer;
class AnimationStack;
}
/** DOM class for skin deformer clusters (aka sub-deformers) */
class Cluster : public Deformer {
private:
WeightArray weights; //权重
WeightIndexArray indices;
aiMatrix4x4 transform; //每一帧对应的旋转矩阵
aiMatrix4x4 transformLink; //每一帧对应的旋转矩阵
const Model* node;
};
? ??