osg示例程序解析2---osganimationeasemotion

本文参考文章http://blog.csdn.net/yungis/article/details/8463077

#include <osg/Geode>
#include <osg/MatrixTransform>
#include <osg/ShapeDrawable>
#include <osgGA/TrackballManipulator>
#include <osgViewer/Viewer>
#include <osgViewer/ViewerEventHandlers>
#include <osgAnimation/EaseMotion>
#include <osgWidget/WindowManager>
#include <osgWidget/Box>
#include <osgWidget/Table>
#include <osgWidget/Label>
#include <iostream>

class EaseMotionSampler;

const unsigned int WINDOW_WIDTH  = 800;
const unsigned int WINDOW_HEIGHT = 600;
const unsigned int MASK_2D       = 0xF0000000;
const unsigned int MASK_3D       = 0x0F000000;
const float        M_START       = 0.0f;
const float        M_DURATION    = 2.0f;
const float        M_CHANGE      = 1.0f;

EaseMotionSampler* EASE_MOTION_SAMPLER = 0;
osg::Geode*        EASE_MOTION_GEODE   = 0;


//根据传进来的Motion绘制了一条曲线----绘制的为物体的运动路程
osg::Geometry* createEaseMotionGeometry(osgAnimation::Motion* motion) {
    osg::Geometry*  geom = new osg::Geometry();
    osg::Vec4Array* cols = new osg::Vec4Array();
    osg::Vec3Array* v    = new osg::Vec3Array();
 int j=0;
    for(float i = 0.0f; i < M_DURATION; i += M_DURATION / 256.0f)
 {
  j++;
  std::cout<<(motion->getValueAt(i))<<" ";
  if (j%10==0)
  {
   std::cout<<std::endl;
  }
  
  v->push_back(osg::Vec3(i * 30.0f, motion->getValueAt(i) * 30.0f, 0.0f));
 }

    cols->push_back(osg::Vec4(1.0f, 1.0f, 1.0f, 1.0f));

    geom->setUseDisplayList(false);
    geom->setVertexArray(v);
    geom->setColorArray(cols);
    geom->setColorBinding(osg::Geometry::BIND_OVERALL);
    geom->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::LINE_STRIP, 0, v->size()));

    return geom;
}


//EaseMotionSampler继承了NodeCallback,重写了operator()函数,在这个函数中对Callback的节点进行了setMatrix操作,也就是根据motion进行运动
class EaseMotionSampler: public osg::NodeCallback
{
public:
    float     _previous;
    osg::Vec3 _pos;

    osg::ref_ptr<osgAnimation::Motion> _motion;

    EaseMotionSampler(const osg::Vec3& pos):
        _previous (0.0f),
        _pos      (pos) {
    }

    void operator()(osg::Node* node, osg::NodeVisitor* nv) {
        if(!_motion.valid()) return;

        osg::MatrixTransform* mt = dynamic_cast<osg::MatrixTransform*>(node);

        if(!mt) return;

        double t = nv->getFrameStamp()->getSimulationTime();

  //这避免了应用开始但是动画不能用的故障
        if(_previous == 0.0f) _previous = t;

        _motion->update(t - _previous);

        _previous = t;

        mt->setMatrix(osg::Matrix::translate(_pos * _motion->getValue()));
    }
 //osgAnimation::Motion来看看他是什么吧,在easeMotion(缓和的移动)类中,EaseMotion中定义了好多的移动方式,TimeBehaviour执行一次还是循环,Motion中三个重要的变量:开始值,改变值,持续时间。
 float _startValue;
 float _changeValue;
 float _duration;
 

 //MathMotionTemplate继承了Motion重写了getValueInNormalizedRange,MathMotionTemplate是一个模板类,通过不同的模板实现不同的效果,看看getValueInNormalizedRange中干了什么,没错,调用了模板
    //的getValueAt方法,这样不同的模板就产生了不同的效果,而EaseMotion中实现了很多的数学方法。各
    //种曲线函数,如果想实现自己的算法可以重写getValueAt方法,想参考不同的曲线算法都可以参考EaseMotion中的实现。
    template<typename T>
    void setMotion() {
        _motion = new T(M_START, M_DURATION, M_CHANGE, osgAnimation::Motion::LOOP);

        EASE_MOTION_GEODE->removeDrawables(0, EASE_MOTION_GEODE->getNumDrawables());
        EASE_MOTION_GEODE->addDrawable(createEaseMotionGeometry(_motion.get()));
    }
};


//鼠标操作的一系列响应
struct ColorLabel: public osgWidget::Label {
    ColorLabel(const char* label):
        osgWidget::Label(label, "") {
        setFont("fonts/VeraMono.ttf");
        setFontSize(14);
        setFontColor(1.0f, 1.0f, 1.0f, 1.0f);
  
        setColor(0.3f, 0.3f, 0.3f, 1.0f);
        setPadding(2.0f);
        setCanFill(true);
  
        addSize(150.0f, 25.0f);

        setLabel(label);
        setEventMask(osgWidget::EVENT_MOUSE_PUSH | osgWidget::EVENT_MASK_MOUSE_MOVE);
    }

    bool mousePush(double, double, const osgWidget::WindowManager*) {
        osgWidget::Table* p = dynamic_cast<osgWidget::Table*>(_parent);
 
        if(!p) return false;
  
        p->hide();

        const std::string& name = getName();

        if(!name.compare("OutQuadMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutQuadMotion>()
                ;

        else if(!name.compare("InQuadMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InQuadMotion>()
                ;

        else if(!name.compare("InOutQuadMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutQuadMotion>()
                ;

        else if(!name.compare("OutCubicMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutCubicMotion>()
                ;

        else if(!name.compare("InCubicMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InCubicMotion>()
                ;

        else if(!name.compare("InOutCubicMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutCubicMotion>()
                ;

        else if(!name.compare("OutQuartMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutQuartMotion>()
                ;

        else if(!name.compare("InQuartMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InQuartMotion>()
                ;

        else if(!name.compare("InOutQuartMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutQuartMotion>()
                ;

        else if(!name.compare("OutBounceMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutBounceMotion>()
                ;

        else if(!name.compare("InBounceMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InBounceMotion>()
                ;

        else if(!name.compare("InOutBounceMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutBounceMotion>()
                ;

        else if(!name.compare("OutElasticMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutElasticMotion>()
                ;

        else if(!name.compare("InElasticMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InElasticMotion>()
                ;

        else if(!name.compare("InOutElasticMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutElasticMotion>()
                ;

        else if(!name.compare("OutSineMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutSineMotion>()
                ;

        else if(!name.compare("InSineMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InSineMotion>()
                ;

        else if(!name.compare("InOutSineMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutSineMotion>()
                ;

        else if(!name.compare("OutBackMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutBackMotion>()
                ;

        else if(!name.compare("InBackMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InBackMotion>()
                ;

        else if(!name.compare("InOutBackMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutBackMotion>()
                ;

        else if(!name.compare("OutCircMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutCircMotion>()
                ;

        else if(!name.compare("InCircMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InCircMotion>()
                ;

        else if(!name.compare("InOutCircMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutCircMotion>()
                ;

        else if(!name.compare("OutExpoMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::OutExpoMotion>()
                ;

        else if(!name.compare("InExpoMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InExpoMotion>()
                ;

        else if(!name.compare("InOutExpoMotion"))
            EASE_MOTION_SAMPLER->setMotion<osgAnimation::InOutExpoMotion>()
                ;
  
        else EASE_MOTION_SAMPLER->setMotion<osgAnimation::LinearMotion>();

        return true;
    }

    bool mouseEnter(double, double, const osgWidget::WindowManager*) {
        setColor(0.9f, 0.6f, 0.1f, 1.0f);
  
        return true;
    }

    bool mouseLeave(double, double, const osgWidget::WindowManager*) {
        setColor(0.3f, 0.3f, 0.3f, 1.0f);
  
        return true;
    }
};

//添加响应组件,ColorLabelMenu设计了简单的交互,显隐
class ColorLabelMenu: public ColorLabel {
    osg::ref_ptr<osgWidget::Table> _window;

public:
    ColorLabelMenu(const char* label):
        ColorLabel(label) {
        _window = new osgWidget::Table(std::string("Menu_") + label, 6, 5);

        _window->addWidget(new ColorLabel("OutQuadMotion"), 0, 0);
        _window->addWidget(new ColorLabel("InQuadMotion"), 1, 0);
        _window->addWidget(new ColorLabel("InOutQuadMotion"), 2, 0);
        _window->addWidget(new ColorLabel("OutCubicMotion"), 3, 0);
        _window->addWidget(new ColorLabel("InCubicMotion"), 4, 0);
        _window->addWidget(new ColorLabel("InOutCubicMotion"), 5, 0);

        _window->addWidget(new ColorLabel("OutQuartMotion"), 0, 1);
        _window->addWidget(new ColorLabel("InQuartMotion"), 1, 1);
        _window->addWidget(new ColorLabel("InOutQuartMotion"), 2, 1);
        _window->addWidget(new ColorLabel("OutBounceMotion"), 3, 1);
        _window->addWidget(new ColorLabel("InBounceMotion"), 4, 1);
        _window->addWidget(new ColorLabel("InOutBounceMotion"), 5, 1);

        _window->addWidget(new ColorLabel("OutElasticMotion"), 0, 2);
        _window->addWidget(new ColorLabel("InElasticMotion"), 1, 2);
        _window->addWidget(new ColorLabel("InOutElasticMotion"), 2, 2);
        _window->addWidget(new ColorLabel("OutSineMotion"), 3, 2);
        _window->addWidget(new ColorLabel("InSineMotion"), 4, 2);
        _window->addWidget(new ColorLabel("InOutSineMotion"), 5, 2);

        _window->addWidget(new ColorLabel("OutBackMotion"), 0, 3);
        _window->addWidget(new ColorLabel("InBackMotion"), 1, 3);
        _window->addWidget(new ColorLabel("InOutBackMotion"), 2, 3);
        _window->addWidget(new ColorLabel("OutCircMotion"), 3, 3);
        _window->addWidget(new ColorLabel("InCircMotion"), 4, 3);
        _window->addWidget(new ColorLabel("InOutCircMotion"), 5, 3);
  
        _window->addWidget(new ColorLabel("OutExpoMotion"), 0, 4);
        _window->addWidget(new ColorLabel("InExpoMotion"), 1, 4);
        _window->addWidget(new ColorLabel("InOutExpoMotion"), 2, 4);
        _window->addWidget(new ColorLabel("Linear"), 3, 4);

        _window->resize();
    }

    void managed(osgWidget::WindowManager* wm) {
        osgWidget::Label::managed(wm);

        wm->addChild(_window.get());

        _window->hide();
    }

    void positioned() {
        osgWidget::Label::positioned();

        _window->setOrigin(_parent->getX(), _parent->getY() +  _parent->getHeight());
    }

    bool mousePush(double, double, const osgWidget::WindowManager*) {
        if(!_window->isVisible()) _window->show();

        else _window->hide();

        return true;
    }
};

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

 //osgWidget是通过HUD来实现的一个嵌入OSG中的响应界面
 //WindowManager 是osgWidget管理类,继承自Switch,可以识别事件的响应,添加各种窗体
 //WindowManager还可以支持Lua、Python等脚本文件,通过ScriptEngine进行脚本解析。Event定义事件,EventInterface定义响应事件的接口。通过StyleManager来定义窗体的样式。
    osgWidget::WindowManager* wm = new osgWidget::WindowManager(
        &viewer,
        WINDOW_WIDTH,
        WINDOW_HEIGHT,
        MASK_2D
        );

 //Label,继承Widget,可以设置样式、位置、文字等,ColorLabel继承Label,主要为了重新mousePush mouseEnter mouseLeave事件。
 //ColorLabelMenu继承了ColorLabel添加了更多的ColorLabel,addWidget的几个参数就是加入的窗体在table中的位置。

 //创建窗口菜单,水平对齐
    osgWidget::Window* menu = new osgWidget::Box("menu", osgWidget::Box::HORIZONTAL);
    menu->addWidget(new ColorLabelMenu("Choose EaseMotion"));
    menu->getBackground()->setColor(1.0f, 1.0f, 1.0f, 1.0f);
    menu->setPosition(15.0f, 15.0f, 0.0f);

    wm->addChild(menu);

    osg::Group*           group = new osg::Group();
    osg::Geode*           geode = new osg::Geode();
    osg::MatrixTransform* mt    = new osg::MatrixTransform();


 //这几行代码,把一个球,一条曲线加入到mt中,mt设置了callback,每一帧都调用operator方法更新自身的位置,实现根据motion进行移动。
    geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(), 4.0f)));

    EASE_MOTION_SAMPLER = new EaseMotionSampler(osg::Vec3(50.0f, 0.0f, 0.0f));
    EASE_MOTION_GEODE   = new osg::Geode();

    mt->addChild(geode);
    mt->setUpdateCallback(EASE_MOTION_SAMPLER);
    mt->setNodeMask(MASK_3D);

 

    viewer.setCameraManipulator(new osgGA::TrackballManipulator());
    viewer.getCameraManipulator()->setHomePosition(
        osg::Vec3d(0.0f, 0.0f, 200.0f),
        osg::Vec3d(20.0f, 0.0f, 0.0f),
        osg::Vec3d(0.0f, 1.0f, 0.0f)
        );
    viewer.home();

    group->addChild(mt);
    group->addChild(EASE_MOTION_GEODE);

    return osgWidget::createExample(viewer, wm, group);
}

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值