|
我结合pick和osganimationmakepath两个例子,想实现鼠标点击场景时,主相机的插值漫游到碰撞点处!但结果是相机一动不动。请大侠看看是怎么回事!
大致修改如下:
1在pickhandler中的pick函数加了
- osg::Vec3 start,end;
- view->getCamera()->getViewMatrixAsLookAt(position,center,up);
- start=position;//获取当前位置
- osgUtil::LineSegmentIntersector::Intersections::iterator hitr0 = intersections.begin();
- end=hitr0->getWorldIntersectPoint();//点击的交点即为目的地
- osg::ref_ptr<osg::Group>root=new osg::Group();
- osg::Camera* camera=new osg::Camera();
- camera=view->getCamera();
- setupAnimtkNode(camera,start,end);//调用该函数设置样条的关键帧,并在该函数中调用 AnimtkUpdateCallback
复制代码
2,在AnimtkUpdateCallback的operator()中
-
- _sampler->getValueAt(t, result);
- camera->setViewMatrixAsLookAt(result-osg::Vec3(0.0,1.0,0.0),result,osg::Vec3(0.0,0.0,1.0));
复制代码
全部代码:- #include <osgUtil/Optimizer>
- #include <osgDB/ReadFile>
- #include <osgViewer/Viewer>
- #include <osgViewer/CompositeViewer>
- #include <osgGA/TerrainManipulator>
- #include <osgGA/StateSetManipulator>
- #include <osgGA/AnimationPathManipulator>
- #include <osgGA/TrackballManipulator>
- #include <osgGA/FlightManipulator>
- #include <osgGA/DriveManipulator>
- #include <osgGA/KeySwitchMatrixManipulator>
- #include <osgGA/StateSetManipulator>
- #include <osgGA/AnimationPathManipulator>
- #include <osgGA/TerrainManipulator>
- #include <osg/Material>
- #include <osg/Geode>
- #include <osg/BlendFunc>
- #include <osg/Depth>
- #include <osg/Projection>
- #include <osg/MatrixTransform>
- #include <osg/Camera>
- #include <osg/io_utils>
- #include <osg/ShapeDrawable>
- #include <osgUtil/LineSegmentIntersector>
- #include <osgAnimation/Sampler>
- #include <osgText/Text>
- #include <sstream>
- class AnimtkUpdateCallback : public osg::NodeCallback
- {
- public:
- META_Object(osgAnimation, AnimtkUpdateCallback);
- AnimtkUpdateCallback()
- {
- _sampler = new osgAnimation::Vec3CubicBezierSampler;
- _playing = false;
- _lastUpdate = 0;
- }
- AnimtkUpdateCallback(const AnimtkUpdateCallback& val, const osg::CopyOp& copyop = osg::CopyOp::SHALLOW_COPY):
- osg::Object(val, copyop),
- osg::NodeCallback(val, copyop),
- _sampler(val._sampler),
- _startTime(val._startTime),
- _currentTime(val._currentTime),
- _playing(val._playing),
- _lastUpdate(val._lastUpdate)
- {
- }
- /** Callback method called by the NodeVisitor when visiting a node.*/
- virtual void operator()(osg::Node* node, osg::NodeVisitor* nv)
- {
- if (nv->getVisitorType() == osg::NodeVisitor::UPDATE_VISITOR &&
- nv->getFrameStamp() &&
- nv->getFrameStamp()->getFrameNumber() != _lastUpdate)
- {
- _lastUpdate = nv->getFrameStamp()->getFrameNumber();
- _currentTime = osg::Timer::instance()->tick();
- if (_playing && _sampler.get() && _sampler->getKeyframeContainer())
- {
- //osg::MatrixTransform* transform = dynamic_cast<osg::MatrixTransform*>(node);
- osg::Camera* camera = dynamic_cast<osg::Camera*>(node);
- if (camera) {
- osg::Vec3 result;
- float t = osg::Timer::instance()->delta_s(_startTime, _currentTime);
- float duration = _sampler->getEndTime() - _sampler->getStartTime();
- //t = fmod(t, duration);
- t += _sampler->getStartTime();
- _sampler->getValueAt(t, result);
- //transform->setMatrix(osg::Matrix::translate(result));
- camera->setViewMatrixAsLookAt(result-osg::Vec3(0.0,1.0,0.0),result,osg::Vec3(0.0,0.0,1.0));
- }
- }
- }
- // note, callback is responsible for scenegraph traversal so
- // they must call traverse(node,nv) to ensure that the
- // scene graph subtree (and associated callbacks) are traversed.
- traverse(node,nv);
- }
- void start() { _startTime = osg::Timer::instance()->tick(); _currentTime = _startTime; _playing = true;}
- void stop() { _currentTime = _startTime; _playing = false;}
- osg::ref_ptr<osgAnimation::Vec3CubicBezierSampler> _sampler;
- osg::Timer_t _startTime;
- osg::Timer_t _currentTime;
- bool _playing;
- int _lastUpdate;
- };
- osg::MatrixTransform* setupAnimtkNode(osg::Camera* camera,osg::Vec3 start,osg::Vec3 end)
- {
- osg::Vec3 v[2];
- osg::Vec3 startToend=end-start;
- /*startToend.x()*=0.5;
- startToend.y()*=0.5;
- startToend.z()*=0.5;*/
- v[0] = start;
- v[1] = v[0]+startToend;
- /*v[2] = v[1]+startToend;
- v[3] = v[2]+startToend;
- v[4] = v[3]+startToend;
- v[5] = v[4]+startToend;*/
- osg::MatrixTransform* node = new osg::MatrixTransform();
- //AnimtkUpdateCallback* callback = new MakePathDistanceCallback(staticGeode);
- AnimtkUpdateCallback* callback = new AnimtkUpdateCallback();
- osgAnimation::Vec3CubicBezierKeyframeContainer* keys = callback->_sampler->getOrCreateKeyframeContainer();
- keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(0, osgAnimation::Vec3CubicBezier(
- v[0],
- v[0] + (v[0] - v[1]),
- v[1] - (v[1] - v[0])
- )));
- keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(6, osgAnimation::Vec3CubicBezier(
- v[1],
- v[1] + (v[1] - v[0]),
- v[0] - (v[0] - v[1])
- )));
- /*keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(4, osgAnimation::Vec3CubicBezier(
- v[2],
- v[2] + (v[2] - v[1]),
- v[0] - (v[0] - v[2])
- )));
- keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(6, osgAnimation::Vec3CubicBezier(
- v[3],
- v[3] + (v[3] - v[2]),
- v[4] - (v[4] - v[3])
- )));
- keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(8, osgAnimation::Vec3CubicBezier(
- v[4],
- v[4] + (v[4] - v[3]),
- v[5] - (v[5] - v[4])
- )));
- keys->push_back(osgAnimation::Vec3CubicBezierKeyframe(12, osgAnimation::Vec3CubicBezier(
- v[5],
- v[5] + (v[5] - v[4]),
- v[0] - (v[0] - v[5])
- )));*/
- callback->start();
- camera->setUpdateCallback(callback);
- //osg::Geode* geode = new osg::Geode();
- //geode->setStateSet(setupStateSet());
- //geode->addDrawable(new osg::ShapeDrawable(new osg::Sphere(osg::Vec3(0.0f, 0.0f, 0.0f), 2)));
- //node->addChild(geode);
- return node;
- }
- //////////////////////////////////////////////////////////////////////////
- // class to handle events with a pick
- class PickHandler : public osgGA::GUIEventHandler {
- public:
- PickHandler(osgText::Text* updateText):
- _updateText(updateText) {}
- ~PickHandler() {}
- bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa);
- virtual void pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea);
- void setLabel(const std::string& name)
- {
- if (_updateText.get()) _updateText->setText(name);
- }
- protected:
- //得到当前视图矩阵
- osg::Vec3 position;
- osg::Vec3 center;
- osg::Vec3 up;
- osg::ref_ptr<osgText::Text> _updateText;
- };
- bool PickHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa)
- {
- switch(ea.getEventType())
- {
- /* case(osgGA::GUIEventAdapter::FRAME):
- {
- osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
- if (view) view->getCamera()->getViewMatrixAsLookAt(position,center,up);
- osg::Vec3 delta = center-position;
- position = position + delta/2.0;
- view->getCamera()->setViewMatrixAsLookAt(position, center, up);
- return false;
- }*/
- case(osgGA::GUIEventAdapter::PUSH):
- {
- osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
- if (view) pick(view,ea);
- return false;
- }
- case(osgGA::GUIEventAdapter::KEYDOWN):
- {
- if (ea.getKey()=='c')
- {
- osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
- osg::ref_ptr<osgGA::GUIEventAdapter> event = new osgGA::GUIEventAdapter(ea);
- event->setX((ea.getXmin()+ea.getXmax())*0.5);
- event->setY((ea.getYmin()+ea.getYmax())*0.5);
- view->requestWarpPointer((ea.getXmin()+ea.getXmax())/2.0f,(ea.getYmin()+ea.getYmax())/2.0f);
- if (view) pick(view,*event);
- }
- return false;
- }
- default:
- return false;
- }
- }
- void PickHandler::pick(osgViewer::View* view, const osgGA::GUIEventAdapter& ea)
- {
- osgUtil::LineSegmentIntersector::Intersections intersections;
- std::string gdlist="";
- float x = ea.getX();
- float y = ea.getY();
- #if 0
- osg::ref_ptr< osgUtil::LineSegmentIntersector > picker = new osgUtil::LineSegmentIntersector(osgUtil::Intersector::WINDOW, x, y);
- osgUtil::IntersectionVisitor iv(picker.get());
- view->getCamera()->accept(iv);
- if (picker->containsIntersections())
- {
- intersections = picker->getIntersections();
- #else
- if (view->computeIntersections(x,y,intersections))
- {
- #endif
- //////////////////////////////////////////////////////////////////////////
- osg::Vec3 start,end;
- view->getCamera()->getViewMatrixAsLookAt(position,center,up);
- start=position;
- osgUtil::LineSegmentIntersector::Intersections::iterator hitr0 = intersections.begin();
- end=hitr0->getWorldIntersectPoint();
- osg::ref_ptr<osg::Group>root=new osg::Group();
- osg::Camera* camera=new osg::Camera();
- camera=view->getCamera();
- setupAnimtkNode(camera,start,end);
- /*osg::Geode* geode = new osg::Geode();
- root=view->getSceneData()->asGroup();
- root->addChild(setupAnimtkNode(geode,start,end));
- root->addChild(geode);*/
- //////////////////////////////////////////////////////////////////////////
- for(osgUtil::LineSegmentIntersector::Intersections::iterator hitr = intersections.begin();
- hitr != intersections.end();
- ++hitr)
- {
- std::ostringstream os;
- if (!hitr->nodePath.empty() && !(hitr->nodePath.back()->getName().empty()))
- {
- // the geodes are identified by name.
- os<<"Object ""<<hitr->nodePath.back()->getName()<<"""<<std::endl;
- }
- else if (hitr->drawable.valid())
- {
- os<<"Object ""<<hitr->drawable->className()<<"""<<std::endl;
- }
- os<<" local coords vertex("<< hitr->getLocalIntersectPoint()<<")"<<" normal("<<hitr->getLocalIntersectNormal()<<")"<<std::endl;
- os<<" world coords vertex("<< hitr->getWorldIntersectPoint()<<")"<<" normal("<<hitr->getWorldIntersectNormal()<<")"<<std::endl;
- const osgUtil::LineSegmentIntersector::Intersection::IndexList& vil = hitr->indexList;
- for(unsigned int i=0;i<vil.size();++i)
- {
- os<<" vertex indices ["<<i<<"] = "<<vil[i]<<std::endl;
- }
- gdlist += os.str();
- }
- }
- setLabel(gdlist);
- }
- osg::Node* createHUD(osgText::Text* updateText)
- {
- osg::Camera* hudCamera = new osg::Camera;
- hudCamera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
- hudCamera->setProjectionMatrixAsOrtho2D(0,1280,0,1024);
- hudCamera->setViewMatrix(osg::Matrix::identity());
- hudCamera->setRenderOrder(osg::Camera::POST_RENDER);
- hudCamera->setClearMask(GL_DEPTH_BUFFER_BIT);
- std::string timesFont("fonts/times.ttf");
- // turn lighting off for the text and disable depth test to ensure its always ontop.
- osg::Vec3 position(150.0f,800.0f,0.0f);
- osg::Vec3 delta(0.0f,-60.0f,0.0f);
- {
- osg::Geode* geode = new osg::Geode();
- osg::StateSet* stateset = geode->getOrCreateStateSet();
- stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
- stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
- geode->setName("simple");
- hudCamera->addChild(geode);
- osgText::Text* text = new osgText::Text;
- geode->addDrawable( text );
- text->setFont(timesFont);
- text->setText("Picking in Head Up Displays is simple!");
- text->setPosition(position);
- position += delta;
- }
- for (int i=0; i<=5; i++) {
- osg::Vec3 dy(0.0f,-30.0f,0.0f);
- osg::Vec3 dx(120.0f,0.0f,0.0f);
- osg::Geode* geode = new osg::Geode();
- osg::StateSet* stateset = geode->getOrCreateStateSet();
- const char *opts[]={"One", "Two", "Three", "January", "Feb", "2003"};
- osg::Geometry *quad=new osg::Geometry;
- stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
- stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
- std::string name="subOption";
- name += " ";
- name += std::string(opts[i]);
- geode->setName(name);
- osg::Vec3Array* vertices = new osg::Vec3Array(4); // 1 quad
- osg::Vec4Array* colors = new osg::Vec4Array;
- colors = new osg::Vec4Array;
- colors->push_back(osg::Vec4(0.8-0.1*i,0.1*i,0.2*i, 1.0));
- quad->setColorArray(colors);
- quad->setColorBinding(osg::Geometry::BIND_PER_PRIMITIVE);
- (*vertices)[0]=position;
- (*vertices)[1]=position+dx;
- (*vertices)[2]=position+dx+dy;
- (*vertices)[3]=position+dy;
- quad->setVertexArray(vertices);
- quad->addPrimitiveSet(new osg::DrawArrays(osg::PrimitiveSet::QUADS,0,4));
- geode->addDrawable(quad);
- hudCamera->addChild(geode);
- position += delta;
- }
- { // this displays what has been selected
- osg::Geode* geode = new osg::Geode();
- osg::StateSet* stateset = geode->getOrCreateStateSet();
- stateset->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
- stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
- geode->setName("The text label");
- geode->addDrawable( updateText );
- hudCamera->addChild(geode);
- updateText->setCharacterSize(20.0f);
- updateText->setFont(timesFont);
- updateText->setColor(osg::Vec4(1.0f,1.0f,0.0f,1.0f));
- updateText->setText("");
- updateText->setPosition(position);
- updateText->setDataVariance(osg::Object::DYNAMIC);
- position += delta;
- }
- return hudCamera;
- }
- int main( int argc, char **argv )
- {
- // use an ArgumentParser object to manage the program arguments.
- osg::ArgumentParser arguments(&argc,argv);
- // read the scene from the list of file specified commandline args.
- osg::ref_ptr<osg::Node> scene = osgDB::readNodeFiles(arguments);
- if (!scene && arguments.read("--relative-camera-scene"))
- {
- // Create a test scene with a camera that has a relative reference frame.
- osg::Group* group = new osg::Group();
- osg::Geode* sphere = new osg::Geode();
- sphere->setName("Sphere");
- sphere->addDrawable(new osg::ShapeDrawable(new osg::Sphere()));
- osg::Geode* cube = new osg::Geode();
- cube->setName("Cube");
- cube->addDrawable(new osg::ShapeDrawable(new osg::Box()));
- osg::Camera* camera = new osg::Camera();
- camera->setRenderOrder(osg::Camera::POST_RENDER);
- camera->setClearMask(GL_DEPTH_BUFFER_BIT);
- camera->setReferenceFrame(osg::Transform::RELATIVE_RF);
- camera->setViewMatrix(osg::Matrix::translate(-2, 0, 0));
- osg::MatrixTransform* xform = new osg::MatrixTransform(osg::Matrix::translate(1, 1, 1));
- xform->addChild(camera);
- group->addChild(sphere);
- group->addChild(xform);
- camera->addChild(cube);
- scene = group;
- }
- // if not loaded assume no arguments passed in, try use default mode instead.
- if (!scene) scene = osgDB::readNodeFile("lz.osg");
- osg::ref_ptr<osg::Group> group = dynamic_cast<osg::Group*>(scene.get());
- if (!group)
- {
- group = new osg::Group;
- group->addChild(scene.get());
- }
- osg::ref_ptr<osgText::Text> updateText = new osgText::Text;
- // add the HUD subgraph.
- group->addChild(createHUD(updateText.get()));
- if (arguments.read("--CompositeViewer"))
- {
- osg::ref_ptr<osgViewer::View> view = new osgViewer::View;
- // add the handler for doing the picking
- view->addEventHandler(new PickHandler(updateText.get()));
- // set the scene to render
- view->setSceneData(group.get());
- view->setUpViewAcrossAllScreens();
- osgViewer::CompositeViewer viewer;
- viewer.addView(view.get());
- return viewer.run();
- }
- else
- {
- osgViewer::Viewer viewer;
- // add all the camera manipulators
- {
- osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
- keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
- keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
- keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
- unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
- keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
- std::string pathfile;
- char keyForAnimationPath = '5';
- while (arguments.read("-p",pathfile))
- {
- osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
- if (apm || !apm->valid())
- {
- num = keyswitchManipulator->getNumMatrixManipulators();
- keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
- ++keyForAnimationPath;
- }
- }
- keyswitchManipulator->selectMatrixManipulator(num);
- viewer.setCameraManipulator( keyswitchManipulator.get() );
- }
- // add the handler for doing the picking
- viewer.addEventHandler(new PickHandler(updateText.get()));
- // set the scene to render
- viewer.setSceneData(group.get());
- return viewer.run();
- }
- }
复制代码 |
|