作者:CYM
最近因为想研究骨骼动画,就想看看HavokAnimation上面的例子,HavokAnimation很强大,听说上古时代5就是用HavokAnimation做的,虽然不开源,但至少免费,现在市面上开源免费的动画库几乎快灭绝了,很多开源动画库不是过期了就是停止更新了..
HavokAnimation其实学起来挺简单的,就是把它整合到自己的游戏引擎中去就难了.
以下讲解的是Havok自带的AnimatedSkeletonDemo例子.
Animated Skeleton 这个词翻译过来是骨骼框架,在程序中用hkaAnimatedSkeleton类来代表一个Animated Skeleton.对于这个类官方给出的解释是:管理运行时每个骨骼的实例..
以下是代码:
h文件--------------------------------------------------------------------------------------------------------
#ifndef ANIMATED_SKELETON_DEMO_H
#define ANIMATED_SKELETON_DEMO_H
#include
class AnimatedSkeletonDemo : public hkDefaultAnimationDemo
{
public:
HK_DECLARE_CLASS_ALLOCATOR( HK_MEMORY_CLASS_DEMO );
AnimatedSkeletonDemo( hkDemoEnvironment* env );
~AnimatedSkeletonDemo();
Result stepDemo();
private:
class hkLoader* m_loader;//资源加载器
class hkaSkeleton* m_skeleton;//存储骨骼信息
class hkaAnimation* m_animation;//存储动画信息
class hkaAnimationBinding* m_binding;//描述一个动画是如何被绑定在骨骼上的
hkArray
};
#endif //ANIMATED_SKELETON_DEMO_H
cpp文件-------------------------------------------------------------------------------------------------------
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define NUM_SKELETONS 8
AnimatedSkeletonDemo::AnimatedSkeletonDemo( hkDemoEnvironment* env )
:hkDefaultAnimationDemo(env)
{
//
// Setup the camera
//
{
hkVector4 from( -1.0f, -7.0f, 1.0f);
hkVector4 to ( 0.0f, 0.0f, 0.0f);
hkVector4 up ( 0.0f, 0.0f, 1.0f);
setupDefaultCameras( env, from, to, up );
}
m_loader = new hkLoader();
// Get the rig获取骨骼
{
hkStringBuf assetFile("Resources/Animation/HavokGirl/hkRig.hkx");//设置资源路径
hkAssetManagementUtil::getFilePath(assetFile);//将通用资源路径指定为当前平台路径
//载入资源,获取根级容器
hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
//获取顶级动画容器
hkaAnimationContainer* ac = reinterpret_cast
m_skeleton = ac->m_skeletons[0];
}
// Get the animation and the binding获取动画以及绑定
{
hkStringBuf assetFile("Resources/Animation/HavokGirl/hkJumpLandLoop.hkx"); hkAssetManagementUtil::getFilePath(assetFile);
hkRootLevelContainer* container = m_loader->load( assetFile.cString() );
hkaAnimationContainer* ac = reinterpret_cast
m_animation = ac->m_animations[0];
m_binding = ac->m_bindings[0];
}
for ( int i = 0; i < NUM_SKELETONS; ++i )
{
// Create an animation control 创建动画控制器
hkaDefaultAnimationControl* ac = new hkaDefaultAnimationControl(m_binding);
ac->setLocalTime( i * 0.2f );
// Create a new animated skeleton 创建骨骼框架
hkaAnimatedSkeleton* skeleton = new hkaAnimatedSkeleton( m_skeleton );
m_activeSkeletons.pushBack( skeleton );
// Bind the control to the skeleton 绑定控制器到骨骼
skeleton->addAnimationControl( ac );
// The animated skeleton now owns the control
ac->removeReference();
}
setupGraphics( );
}
AnimatedSkeletonDemo::~AnimatedSkeletonDemo()
{
delete m_loader;
// Delete the active skeletons
for (int s=0; s< m_activeSkeletons.getSize(); s++)
{
m_activeSkeletons[s]->removeReference();
}
}
hkDemo::Result AnimatedSkeletonDemo::stepDemo()
{
for (int i = 0; i < m_activeSkeletons.getSize(); ++i )
{
hkaAnimatedSkeleton* inst = m_activeSkeletons[i];
// Advance the animation 播放动画
inst->stepDeltaTime( m_timestep );
hkaPose pose (inst->getSkeleton());
inst->sampleAndCombineAnimations( pose.accessUnsyncedPoseLocalSpace().begin(), pose.getFloatSlotValues().begin() );
// Draw
hkQsTransform worldFromModel (hkQsTransform::IDENTITY);
worldFromModel.m_translation.set( hkReal(i - 1 - (NUM_SKELETONS>>2)), 0, 0);
AnimationUtils::drawPose( pose, worldFromModel,2147413847,0.25f,true,true);
}
return DEMO_OK;
}
static const char helpString[] = \
"A single animation and rig is loaded. This is instanced 5 times. Each instance has a different initial local time." ;
HK_DECLARE_DEMO(AnimatedSkeletonDemo, HK_DEMO_TYPE_ANIMATION | HK_DEMO_TYPE_SERIALIZE | HK_DEMO_TYPE_CRITICAL, "Shows 5 instances of the same skeletal animation", helpString);