天天看點

osg 路徑 動畫 效果

#include <osg/Group>
#include <osg/ShapeDrawable>

#include <osgViewer/ViewerEventHandlers>
#include <osgViewer/Viewer>

#include <osgDB/ReadFile>
#include <osgUtil/LineSegmentIntersector>
#include <osgGA/GUIEventHandler>
#include <osgGA/AnimationPathManipulator>

#include <iostream>
using namespace std;


class PickEventHandle :public osgGA::GUIEventHandler
{
public:
  PickEventHandle(){
    _points=new osg::Vec3Array;
  }
  virtual ~PickEventHandle(){
  }
  osg::Geode*createBox(osg::Vec3 center){
    osg::ref_ptr<osg::Geode>geode=new osg::Geode;
    geode->getOrCreateStateSet()->setMode(GL_BLEND, osg::StateAttribute::ON);
    osg::ref_ptr<osg::ShapeDrawable>sd=new osg::ShapeDrawable(new osg::Box(center,5,5,5));
    sd->setColor(osg::Vec4(1,0,0,1));
    geode->addDrawable(sd);
    return geode.release();
  }
  float getRunTime(osg::Vec3 res,osg::Vec3 des){
    float xx=(res.x()-des.x())*(res.x()-des.x());
    float yy=(res.y()-des.y())*(res.y()-des.y());
    float zz=(res.z()-des.z())*(res.z()-des.z());
    float distant=sqrt(xx+yy+zz);
    return distant*0.1;
  }

  osg::AnimationPath*createPath(){
    osg::ref_ptr<osg::AnimationPath>anim=new osg::AnimationPath;
    anim->setLoopMode(osg::AnimationPath::LOOP);

    float time=0.0;
    float angle=0.0;
    float roll=1.57;//osg::inDegrees(90);

    if(_points.valid()){
      osg::Vec3Array::iterator iter=_points->begin();
      for(;;){
        osg::Vec3 pos(*iter);
        iter++;
        if(iter!=_points->end()) {
          if(iter->x() > pos.x())
          {
            angle=1.57-atan((iter->y()-pos.y())/(iter->x()-pos.x()));
            if(angle<0)
              angle+=1.57;
          }
          else {
            angle=-(1.57+atan((iter->y()-pos.y())/(iter->x()-pos.x())));
            if(angle>0){
              angle=-(1.57-angle);
            }

          }

          osg::Quat rotate (osg::Quat(roll,osg::Vec3(1.0,0,0))*osg::Quat(-angle,osg::Vec3(0,0,1)));

          anim->insert(time,osg::AnimationPath::ControlPoint(pos,rotate));
          time+=getRunTime(pos, *iter);
        }
        else {
          break;
        }
      }      
    }


    ofstream out("/root/a.path");//把資訊儲存
    anim->write(out);
    out.close();
    return anim.release();
  }


   bool handle(const osgGA::GUIEventAdapter &ea   ,osgGA::GUIActionAdapter &aa)
    {

      osgViewer::Viewer *viewer=dynamic_cast<osgViewer::Viewer*>(&aa);
      if(!viewer)
        return false;
      switch (ea.getEventType()){
        case osgGA::GUIEventAdapter::PUSH://尋找關鍵點
        {
          osgUtil::LineSegmentIntersector::Intersections inters;
          if(viewer->computeIntersections(ea.getX(),ea.getY(),inters)){
            osgUtil::LineSegmentIntersector::Intersections::iterator iter=inters.begin();
            osg::Vec3d pos=iter->getWorldIntersectPoint();
            cout<<pos.x()<<" "<<pos.y()<<" "<<pos.z()<<endl;
            _points->push_back(osg::Vec3(pos.x(),pos.y(),3));
            viewer->getSceneData()->asGroup()->addChild(createBox(pos));
          }
        }
        case osgGA::GUIEventAdapter::KEYDOWN:{
          if(ea.getKey()=='f' || ea.getKey()=='F'){//啟動漫遊(可以在這儲存下操縱器,漫遊完畢可以傳回原來狀态
            if(viewer)
            {
              osg::ref_ptr<osgGA::AnimationPathManipulator>apm=new osgGA::AnimationPathManipulator;
              apm->setAnimationPath(createPath());
              viewer->setCameraManipulator(apm);
            }
          }
          if(ea.getKey()=='g' || ea.getKey()=='G'){//用已經儲存的檔案裡的資訊
            osg::ref_ptr<osgGA::AnimationPathManipulator>apm=new osgGA::AnimationPathManipulator("/root/a.path");
            viewer->setCameraManipulator(apm); 
          }
        }
          break;
      }    
    return false;

  }

private:
  osg::ref_ptr<osg::Vec3Array> _points;
};

int main(int argc, char *argv[])
{

  osg::ref_ptr<osgViewer::Viewer>viewer=new osgViewer::Viewer;
  viewer->setSceneData(osgDB::readNodeFile("ceep.ive"));
  viewer->addEventHandler(new PickEventHandle());
  viewer->addEventHandler(new osgViewer::ScreenCaptureHandler);
  viewer->run();
}

           
osg 路徑 動畫 效果
osg