OSG使用AnimationPathManipulator实现摄像机环绕物体旋转动画,并解决Viewer再次设置不能执行动画的问题

文章讲述了在使用osgGA的AnimationPathManipulator时调整摄像机初始位置的问题,介绍了如何绕物体旋转并设置动画路径。同时,作者分享了解决场景运行过程中动画卡顿的修复方法,即自定义AnimationPathManipulator_Repaired类以处理帧时间问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一开始弄了好久没整明白这个Manipulator的初始摄像机位置,始终看不到物体不知道怎么调整(因为默认在(0, 0, 0)物体被剔除了),后来清楚了在此做个记录。

//动画完成回调
struct CompletedCallback : public osgGA::AnimationPathManipulator::AnimationCompletedCallback 
{
    CompletedCallback(osgViewer::Viewer* viewer)
    {
        _viewer = viewer;
    }
    void completed(const osgGA::AnimationPathManipulator* apm) override
    {
        _viewer->setCameraManipulator(new osgGA::TerrainManipulator);
    }
    osgViewer::Viewer* _viewer = nullptr;
};

int main(int argc, char *argv[])
{
    osgViewer::Viewer viewer;

    osg::ref_ptr<osg::Group> root = new osg::Group;
    root->addChild(osgDB::readNodeFile("./cow.osg"));
    viewer.setSceneData(root);

    osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator;
    osg::AnimationPath* path = new osg::AnimationPath;
    for (int i = 0; i <= 36; i++) 
    {
        float pi = 3.14159265;
        float pi2 = 2 * pi;
        float precision = 36.0;
        float delta = pi2 / precision;
        osg::Quat quat(-delta * i, osg::Vec3d(0.0, 0.0, 1.0));
        //AnimationPathManipulator默认情况下,摄像机是在(0, 0, 0)并且视角朝下(z-),这里先绕x轴旋转45°
        osg::Quat base(pi / 4.0, osg::Vec3d(1.0, 0.0, 0.0));
        float radius = root->getBound().radius() * 3;//使摄像机离视角中心三倍包围盒半径的距离
        float z = radius * cos(pi / 4.0);
        float xy_radius = radius * sin(pi / 4.0);
        osg::Matrixd m = osg::Matrixd::rotate(base * quat) * osg::Matrixd::translate(-xy_radius * sin(delta * i), -xy_radius * cos(delta * i), z);
        osg::Vec3f pos = m.getTrans();
        osg::Quat rot = m.getRotate();
        path->insert(i / 3.6, osg::AnimationPath::ControlPoint(pos, rot));
    }
    path->setLoopMode(osg::AnimationPath::NO_LOOPING);
    apm->setAnimationPath(path);
    //添加动画完成后的回调,如果为LOOP或SWING就不要添加了
    apm->setAnimationCompletedCallback(new CompletedCallback(&viewer));
    viewer.setCameraManipulator(apm);

    return viewer.run();
}

运行效果:摄像机俯角45°环绕物体一圈

在这里插入图片描述

注意:
如果在场景运行的过程中设置AnimationPathManipulator,会发现视角卡住,没有动画效果,这是因为AnimationPathManipulator是以场景frameTime为基准(另一个动画组件AnimationPathCallback则是会记录动画开始时的frameTime,然后以差值为基准),则如果动画设置的0-10s,然后当前frameTime为5s,那么只会执行其中5-10s的效果,如果当前frameTime超过了10s,那么什么效果都没有,解决方案是这里继承AnimationPathManipulator后做一点小修改。

class AnimationPathManipulator_Repaired :public osgGA::AnimationPathManipulator
{
public:
	bool handle(const osgGA::GUIEventAdapter& ea, osgGA::GUIActionAdapter& us) override
	{
		if (!valid())return false;

		switch (ea.getEventType())
		{
		case osgGA::GUIEventAdapter::FRAME:
		{
			if (_firstTime < 0.0)
			{
				_firstTime = ea.getTime();
			}
			handleFrame(ea.getTime() - _firstTime);
			return false;
		}
		default:
			break;
		}
		return false;
	}
	float _firstTime = -1.0;
};
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值