Open Scene Graph动画系统

OSG 提供了强大的动画功能,支持多种动画实现方式,从简单的变换动画到复杂的骨骼动画。以下是 OSG 动画系统的全面介绍:

1. 基本动画类型

1.1 变换动画 (Transform Animation)

// 创建动画路径
osg::AnimationPath* createAnimationPath(const osg::Vec3& center, float radius, double looptime)
{
    osg::ref_ptr<osg::AnimationPath> path = new osg::AnimationPath;
    path->setLoopMode(osg::AnimationPath::LOOP);
    
    unsigned int numSamples = 32;
    float delta_yaw = 2.0f * osg::PI / ((float)numSamples - 1.0f);
    
    for(unsigned int i=0; i<numSamples; ++i) {
        float yaw = delta_yaw * (float)i;
        osg::Vec3 position(center + osg::Vec3(sinf(yaw)*radius, cosf(yaw)*radius, 0.0f));
        osg::Quat rotation(osg::Quat(-yaw, osg::Z_AXIS));
        path->insert(looptime * (double)i / (double)(numSamples-1), 
                    osg::AnimationPath::ControlPoint(position, rotation));
    }
    return path.release();
}

// 应用到节点
osg::ref_ptr<osg::AnimationPathCallback> apcb = new osg::AnimationPathCallback(animationPath);
node->setUpdateCallback(apcb);

1.2 关键帧动画 (Keyframe Animation)

osg::ref_ptr<osg::PositionAttitudeTransform> pat = new osg::PositionAttitudeTransform;

// 创建关键帧动画
osg::ref_ptr<osg::Vec3Array> positions = new osg::Vec3Array;
positions->push_back(osg::Vec3(0,0,0));
positions->push_back(osg::Vec3(10,0,0));
positions->push_back(osg::Vec3(10,10,0));

osg::ref_ptr<osg::Vec3LinearInterpolator> interpolator = new osg::Vec3LinearInterpolator;
interpolator->setKeyFrameData(positions);

osg::ref_ptr<osg::AnimationPathCallback> animCallback = new osg::AnimationPathCallback;
animCallback->setInterpolator(interpolator);
animCallback->setDuration(5.0); // 5秒完成动画

pat->setUpdateCallback(animCallback);

2. 高级动画技术

2.1 骨骼动画 (Skeletal Animation)

// 加载带骨骼的模型
osg::ref_ptr<osg::Node> model = osgDB::readNodeFile("character.osgt");

// 获取动画管理器
osgAnimation::BasicAnimationManager* manager = 
    dynamic_cast<osgAnimation::BasicAnimationManager*>(model->getUpdateCallback());

if(manager) {
    // 播放特定动画
    manager->playAnimation("walk_cycle");
}

2.2 变形动画 (Morph Animation)

osg::ref_ptr<osg::Geode> geode = new osg::Geode;
osg::ref_ptr<osg::Geometry> geometry = createMorphGeometry(); // 创建可变形几何体

osg::ref_ptr<osgAnimation::MorphGeometry> morphGeom = new osgAnimation::MorphGeometry(*geometry);
morphGeom->addMorphTarget(createMorphTarget1(), 0.0f);
morphGeom->addMorphTarget(createMorphTarget2(), 1.0f);

osg::ref_ptr<osgAnimation::MorphCallback> morphCallback = new osgAnimation::MorphCallback;
morphCallback->setWeight(0, 0.5f); // 设置混合权重

morphGeom->setUpdateCallback(morphCallback);
geode->addDrawable(morphGeom);

2.3 顶点动画 (Vertex Animation)

osg::ref_ptr<osg::Geometry> geom = createGeometryWithVertexAnimation();

osg::ref_ptr<osgAnimation::VertexInfluence> vinf = new osgAnimation::VertexInfluence;
vinf->setName("vertexAnimation");
vinf->setWeight(0.5f); // 动画强度

osg::ref_ptr<osgAnimation::VertexInfluenceMap> vmap = new osgAnimation::VertexInfluenceMap;
vmap->insert(std::make_pair(vinf->getName(), vinf));

geom->setVertexInfluenceMap(vmap);

3. 动画控制

3.1 动画时间线控制

osg::ref_ptr<osgAnimation::Animation> animation = new osgAnimation::Animation;
animation->setPlayMode(osgAnimation::Animation::LOOP);
animation->setDuration(10.0); // 10秒动画

// 添加时间线通道
osg::ref_ptr<osgAnimation::Vec3LinearChannel> channel = new osgAnimation::Vec3LinearChannel;
channel->setName("position");
channel->setTargetName("MyNode");

// 添加关键帧
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(0.0, osg::Vec3(0,0,0)));
channel->getOrCreateSampler()->getOrCreateKeyframeContainer()->push_back(osgAnimation::Vec3Keyframe(10.0, osg::Vec3(10,0,0)));

animation->addChannel(channel);

3.2 动画混合

osgAnimation::AnimationManagerBase* manager = getAnimationManager();

// 设置动画混合
manager->blendAnimation("walk", 0.5, 0.2); // 动画名, 权重, 过渡时间
manager->blendAnimation("run", 0.5, 0.2);

4. 性能优化技巧

  1. 使用LOD(Level of Detail):根据距离切换不同精度的动画

  2. 动画裁剪:当动画不可见时暂停处理

  3. 硬件蒙皮:启用GPU加速骨骼动画

    osg::StateSet* stateset = model->getOrCreateStateSet();
    stateset->setAttributeAndModes(new osg::VertexProgram, osg::StateAttribute::ON);
  4. 实例化动画:对相同动画的多个对象使用实例化渲染

5. 调试工具

OSG动画查看器

bash

osgviewer --animation model.dae

动画信息输出

osgAnimation::Animation::print(animation.get());

6. 常见文件格式支持

  • DAE (Collada):支持骨骼动画

  • FBX:通过插件支持

  • BVH:运动捕捉数据

    扫描二维码关注公众号,回复: 17575337 查看本文章
  • OSGT/OSGB:OSG原生格式