【3D技术宅公社】XR数字艺术论坛  XR技术讨论 XR互动电影 定格动画

 找回密码
 立即注册

QQ登录

只需一步,快速开始

调查问卷
论坛即将给大家带来全新的技术服务,面向三围图形学、游戏、动画的全新服务论坛升级为UTF8版本后,中文用户名和用户密码中有中文的都无法登陆,请发邮件到324007255(at)QQ.com联系手动修改密码

3D技术论坛将以计算机图形学为核心,面向教育 推出国内的三维教育引擎该项目在持续研发当中,感谢大家的关注。

查看: 2100|回复: 2

动画技术-关键帧(keyFrame)

[复制链接]
发表于 2006-4-21 16:12:43 | 显示全部楼层 |阅读模式
关键帧是一种常用的动画技术,其基本原理是将动画序列中比较关键的帧提取出来,而其他帧根据时间用这些关键帧插值计算得到。

一个简单的关键帧结构:

typedef struct sKeyframe {
DWORD Time ;
D3DMATRIX matTransformation ;
}sKeyframe

这是一个非常简化的结构,只包含时间和矩阵。但从这个结构可以看出keyFrame技术最根本的含义。假设我们要创建一个正方形旋转并移动的动画。

如图,这个正方形在3个位置间旋转着移动。我们需要定义4个关键帧,每个关键帧都通过矩阵设定正方形相对于初始位置的偏转和偏移。
sKeyframe Keyframes[4] = {
{ 0, 1.00000f, 0.00000f, 0.00000f, 0.00000f,
0.00000f, 1.00000f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f; },

{ 400, 0.000796f, 1.00000f, 0.00000f, 0.00000f,
-1.00000f, 0.000796f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
50.00000f, 0.00000f, 0.00000f, 1.00000f; },

{ 800, -0.99999f, 0.001593f, 0.00000f, 0.00000f,
-0.001593f, -0.99999f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
25.00000f, 25.00000f, 0.00000f, 1.00000f; },

{ 1200, 1.00000f, 0.00000f, 0.00000f, 0.00000f,
0.00000f, 1.00000f, 0.00000f, 0.00000f,
0.00000f, 0.00000f, 1.00000f, 0.00000f,
0.00000f, 0.00000f, 0.00000f, 1.00000f; }
};

keyFrame4虽然与keyFrame1动画完全一样,但时间不同,所以要定义keyFrame4。
更新动画时首先要根据动画已经播放的时间计算出当前帧处于哪两个关键帧之间。
DWORD Keyframe = 0; // Start at 1st keyframe
for(DWORD i=0;i<4;i++) {
// If time is greater or equal to a
// key-frame's time then update the
// keyframe to use
if(Time >= Keyframes.Time)
Keyframe = i;
}
如果当前时间>=某个关键帧设定的时间,那么该关键帧就是当前帧的前一个关键帧。而下一帧就是后一个关键帧。如果前一个关键帧已经是最后一个关键帧,那么后一个关键帧也使用该帧。
DWORD keyframe2 = (Keyframe==LAST_KEYFRAME_ID)?Keyframe:Keyframe+1 ;
计算出两个关键帧后,根据当前时间和两个关键帧的时间进行插值计算,得到当前帧。
DWORD TimeDiff = Keyframes[Keyframe2].Time -
Keyframes[Keyframe].Time;
// Make sure there's a time difference to
// avoid divide-by-zero errors later on.
if(!TimeDiff)
TimeDiff=1;
float Scalar = (Time - Keyframes[Keyframe].Time)/TimeDiff;
// Calculate the difference in transformations
D3DXMATRIX matInt = \
D3DXMATRIX(Keyframes[Keyframe2].matTransformation) - \
D3DXMATRIX(Keyframes[Keyframe].matTransformation);
matInt *= Scalar; // Scale the difference
// Add scaled transformation matrix back to 1st keyframe matrix
matInt += D3DXMATRIX(Keyframes[Keyframe].matTransformation);

matInt就是计算出的当前帧的转换矩阵,用这个矩阵可以得到当前帧动画的位置。
这个例子是一个最简单的关键帧动画,因为这个动画的Frame只包含一个正方型而以,也就是说该动画每一帧的Mesh是一样的。在稍微复杂些的情况中,比如一个人走动的动画。可以选取几个动作作为关键帧,如果使用简单的动画,每个关键帧要记录一套mesh信息;如果使用骨骼动画,每个关键帧要记录骨骼的变换。这些情况中,需要插值计算的内容就复杂多了。不过根据时间,插值计算出当前帧仍是基础。

关键帧技术除了用于播放动画,还可以用于物体的运动。特别是固定路线的物体运动。

虽然我们谈到关键帧技术都是在3D动画中,不过2D游戏中也可以很好的使用。其实这个简单的例子就可以看成是一个2D动画关键帧的例子,只不过我们要使用2D转换矩阵。


参考资料: <Advanced Animation with DirectX> Chapter2 Trackback: http://tb.blog.csdn.net/TrackBack.aspx?PostId=613767

发表于 2006-5-6 21:55:30 | 显示全部楼层

专业

哈哈,有点不明白

发表于 2006-4-22 12:47:04 | 显示全部楼层

我在做的动画回放也是做插值的:)
http://ogl2dsdk.cosoft.org.cn/

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|3D数字艺术论坛 ( 沪ICP备14023054号 )

GMT+8, 2025-2-6 01:07

Powered by Discuz! X3.4

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表