#include #include #include #include #include #include #include #include #include #include #include using namespace Producer; using namespace osgProducer; ////////////////////////////////////////////////////////////////////////////// // // Picking intersection visitor. // class PickIntersectVisitor : public osgUtil::IntersectVisitor { public: PickIntersectVisitor() { setNodeMaskOverride(0xffffffff); // need to make the visitor override the nodemask to visit invisible actions } virtual ~PickIntersectVisitor() {} HitList& getIntersections(osg::Node *scene, osg::Vec3 nr, osg::Vec3 fr) { // option for non-sceneView users: you need to get the screen perp line and call getIntersections // if you are using Projection nodes you should also call setxy to define the xp,yp positions for use with // the ray transformed by Projection _lineSegment = new osg::LineSegment; _lineSegment->set(nr,fr); // make a line segment //std::cout<<"near "<accept(*this); return getHitList(_lineSegment.get()); } private: osg::ref_ptr _lineSegment; friend class osgUtil::IntersectVisitor; }; // PickVisitor traverses whole scene and checks below all Projection nodes class PickVisitor : public osg::NodeVisitor { public: PickVisitor() { xp=yp=0; setNodeMaskOverride(0xffffffff); // need to make the visitor override the nodemask to visit invisible actions setTraversalMode(osg::NodeVisitor::TRAVERSE_ALL_CHILDREN); } ~PickVisitor() {} virtual void apply(osg::Projection& pr) { // stack the intersect rays, transform to new projection, traverse // Assumes that the Projection is an absolute projection osg::Matrix mt; mt.invert(pr.getMatrix()); osg::Vec3 npt=osg::Vec3(xp,yp,-1.0f) * mt, farpt=osg::Vec3(xp,yp,1.0f) * mt; // traversing the nodes children, using the projection direction for (unsigned int i=0; i0;} private: PickIntersectVisitor _piv; float xp, yp; // start point in viewport fraction coordiantes osgUtil::IntersectVisitor::HitList _PIVsegHitList; }; ////////////////////////////////////////////////////////////////////////////// // // osgProducer::Viewer implemention // Viewer::Viewer(): _done(0), _kbmcb(0), _recordingAnimationPath(false) { } Viewer::Viewer(Producer::CameraConfig *cfg): OsgCameraGroup(cfg), _done(false), _kbmcb(0), _recordingAnimationPath(false) { } Viewer::Viewer(const std::string& configFile): OsgCameraGroup(configFile), _done(false), _kbmcb(0), _recordingAnimationPath(false) { } Viewer::Viewer(osg::ArgumentParser& arguments): OsgCameraGroup(arguments), _done(false), _kbmcb(0), _recordingAnimationPath(false) { // report the usage options. if (arguments.getApplicationUsage()) { arguments.getApplicationUsage()->addCommandLineOption("-p ","Specify camera path file to animate the camera through the loaded scene"); } osg::DisplaySettings::instance()->readCommandLine(arguments); osgDB::readCommandLine(arguments); std::string pathfile; while (arguments.read("-p",pathfile)) { osg::ref_ptr apm = new osgGA::AnimationPathManipulator(pathfile); if( apm.valid() && apm->valid() ) { unsigned int num = addCameraManipulator(apm.get()); selectCameraManipulator(num); } } } void Viewer::setUpViewer(unsigned int options) { // set up the keyboard and mouse handling. Producer::InputArea *ia = getCameraConfig()->getInputArea(); Producer::KeyboardMouse *kbm = ia ? (new Producer::KeyboardMouse(ia)) : (new Producer::KeyboardMouse(getCamera(0)->getRenderSurface())); // set the keyboard mouse callback to catch the events from the windows. if (!_kbmcb) _kbmcb = new osgProducer::KeyboardMouseCallback( kbm, _done, (options & ESCAPE_SETS_DONE)!=0 ); _kbmcb->setStartTick(_start_tick); // register the callback with the keyboard mouse manger. kbm->setCallback( _kbmcb ); //kbm->allowContinuousMouseMotionUpdate(true); kbm->startThread(); // set the globa state osg::ref_ptr globalStateSet = new osg::StateSet; setGlobalStateSet(globalStateSet.get()); { globalStateSet->setGlobalDefaults(); // enable depth testing by default. globalStateSet->setMode(GL_DEPTH_TEST, osg::StateAttribute::ON); // enable lighting by default globalStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON); // set up an alphafunc by default to speed up blending operations. osg::AlphaFunc* alphafunc = new osg::AlphaFunc; alphafunc->setFunction(osg::AlphaFunc::GREATER,0.0f); globalStateSet->setAttributeAndModes(alphafunc, osg::StateAttribute::ON); } // add either a headlight or sun light to the scene. osg::LightSource* lightsource = new osg::LightSource; setSceneDecorator(lightsource); { osg::Light* light = new osg::Light; lightsource->setLight(light); lightsource->setReferenceFrame(osg::LightSource::RELATIVE_TO_ABSOLUTE); // headlight. lightsource->setLocalStateSetModes(osg::StateAttribute::ON); } _updateVisitor = new osgUtil::UpdateVisitor; _updateVisitor->setFrameStamp(_frameStamp.get()); if (options&TRACKBALL_MANIPULATOR) addCameraManipulator(new osgGA::TrackballManipulator); if (options&FLIGHT_MANIPULATOR) addCameraManipulator(new osgGA::FlightManipulator); if (options&DRIVE_MANIPULATOR) addCameraManipulator(new osgGA::DriveManipulator); if (options&STATE_MANIPULATOR) { osg::ref_ptr statesetManipulator = new osgGA::StateSetManipulator; statesetManipulator->setStateSet(getGlobalStateSet()); _eventHandlerList.push_back(statesetManipulator.get()); } if (options&VIEWER_MANIPULATOR) { getEventHandlerList().push_back(new ViewerEventHandler(this)); } } unsigned int Viewer::addCameraManipulator(osgGA::MatrixManipulator* cm) { if (!cm) return 0xfffff; // create a key switch manipulator if one doesn't already exist. if (!_keyswitchManipulator) { _keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator; _eventHandlerList.push_back(_keyswitchManipulator.get()); } unsigned int num = _keyswitchManipulator->getNumMatrixManipualtors(); _keyswitchManipulator->addNumberedMatrixManipulator(cm); return num; } bool Viewer::done() const { return _done || !validForRendering(); } void Viewer::setViewByMatrix( const Producer::Matrix & pm) { CameraGroup::setViewByMatrix(pm); if (_keyswitchManipulator.valid()) { // now convert Producer matrix to an osg::Matrix so we can update // the internal camera... osg::Matrix matrix(pm.ptr()); _keyswitchManipulator->setByInverseMatrix(matrix); } } bool Viewer::realize( ThreadingModel thread_model ) { if( _realized ) return _realized; _thread_model = thread_model; return realize(); } bool Viewer::realize() { if (_realized) return _realized; OsgCameraGroup::realize(); // force a sync before we intialize the keyswitch manipulator to home // so that Producer has a chance to set up the windows before we do // any work on them. OsgCameraGroup::sync(); if (_keyswitchManipulator.valid() && _keyswitchManipulator->getCurrentMatrixManipulator()) { osg::ref_ptr init_event = _kbmcb->createEventAdapter(); init_event->adaptFrame(0.0); _keyswitchManipulator->setNode(getSceneDecorator()); _keyswitchManipulator->home(*init_event,*this); } // set up osg::State objects with the _done prt to allow early termination of // draw traversal. for(SceneHandlerList::iterator p=_shvec.begin(); p!=_shvec.end(); p++ ) { (*p)->getState()->setAbortRenderingPtr(&_done); } return _realized; } void Viewer::update() { // get the event since the last frame. osgProducer::KeyboardMouseCallback::EventQueue queue; if (_kbmcb) _kbmcb->getEventQueue(queue); // create an event to signal the new frame. osg::ref_ptr frame_event = new osgProducer::EventAdapter; frame_event->adaptFrame(_frameStamp->getReferenceTime()); queue.push_back(frame_event); // dispatch the events in order of arrival. for(osgProducer::KeyboardMouseCallback::EventQueue::iterator event_itr=queue.begin(); event_itr!=queue.end(); ++event_itr) { bool handled = false; for(EventHandlerList::iterator handler_itr=_eventHandlerList.begin(); handler_itr!=_eventHandlerList.end() && !handled; ++handler_itr) { handled = (*handler_itr)->handle(*(*event_itr),*this); } } if (_updateVisitor.valid()) { _updateVisitor->setTraversalNumber(_frameStamp->getFrameNumber()); // update the scene by traversing it with the the update visitor which will // call all node update callbacks and animations. getSceneData()->accept(*_updateVisitor); } // update the main producer camera if (_keyswitchManipulator.valid() && _keyswitchManipulator->getCurrentMatrixManipulator()) { osgGA::MatrixManipulator* mm = _keyswitchManipulator->getCurrentMatrixManipulator(); osg::Matrix matrix = mm->getInverseMatrix(); CameraGroup::setViewByMatrix(Producer::Matrix(matrix.ptr())); setFusionDistance(mm->getFusionDistanceMode(),mm->getFusionDistanceValue()); } } void Viewer::frame() { if (getRecordingAnimationPath() && getAnimationPath()) { osg::Matrix matrix; matrix.invert(getViewMatrix()); osg::Quat quat; quat.set(matrix); getAnimationPath()->insert(_frameStamp->getReferenceTime(),osg::AnimationPath::ControlPoint(matrix.getTrans(),quat)); } OsgCameraGroup::frame(); } bool Viewer::computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y) { Producer::KeyboardMouse* km = getKeyboardMouse(); if (!km) return false; if (cameraNum>=getNumberOfCameras()) return false; Producer::Camera* camera=getCamera(cameraNum); Producer::RenderSurface* rs = camera->getRenderSurface(); //std::cout << "checking camara "<computePixelCoords(x,y,rs,pixel_x,pixel_y)) { //std::cout << " compute pixel coords "<getProjectionRectangle( pr_wx, pr_wy, pr_width, pr_height ); int rs_wx, rs_wy; unsigned int rs_width, rs_height; rs->getWindowRectangle( rs_wx, rs_wy, rs_width, rs_height ); pixel_x -= (float)rs_wx; pixel_y -= (float)rs_wy; //std::cout << " wx = "<(camera->getSceneHandler()); osg::Matrix vum; if (sh!=0 && sh->getModelViewMatrix()!=0 && sh->getProjectionMatrix()!=0) { vum.set((*(sh->getModelViewMatrix())) * (*(sh->getProjectionMatrix()))); } else { vum.set(osg::Matrix(camera->getViewMatrix()) * osg::Matrix(camera->getProjectionMatrix())); } PickVisitor iv; osgUtil::IntersectVisitor::HitList localHits; localHits = iv.getHits(getSceneData(), vum, rx,ry); if (localHits.empty()) return false; hits.insert(hits.begin(),localHits.begin(),localHits.end()); return true; } return false; } bool Viewer::computeIntersections(float x,float y,osgUtil::IntersectVisitor::HitList& hits) { bool hitFound = false; osgUtil::IntersectVisitor::HitList hlist; for(unsigned int i=0;iselectMatrixManipulator(no); } void Viewer::requestWarpPointer(float x,float y) { if (_kbmcb) { osg::notify(osg::INFO) << "requestWarpPointer x= "<getUsage(usage); } }