/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield * * This library is open source and may be redistributed and/or modified under * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or * (at your option) any later version. The full license is in LICENSE file * included with this distribution, and on the openscenegraph.org website. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * OpenSceneGraph Public License for more details. */ #ifndef OSGPRODUCER_VIEWER #define OSGPRODUCER_VIEWER 1 #include #include #include #include #include #include #include #include #include #include #include #include #include namespace osgProducer { /** A Producer-based viewer. Just like OpenGL, the core of OSG is independent of * windowing system. The integration between OSG and some windowing system is * delegated to other, non-core parts of OSG (users are also allowed to * integrate OSG with any exotic windowing system they happen to use). * \c Viewer implements the integration between OSG and Producer, AKA Open * Producer (http://www.andesengineering.com/Producer), thus offering an * out-of-the-box, scalable and multi-platform abstraction of the windowing * system. */ class OSGPRODUCER_EXPORT Viewer : public OsgCameraGroup, public osgGA::GUIActionAdapter { public : Viewer(); Viewer(Producer::CameraConfig *cfg); Viewer(const std::string& configFile); Viewer(osg::ArgumentParser& arguments); virtual ~Viewer(); /** Specifies options to control some aspects of the * \c Viewer behavior (using the \c setUpViewer() member * function). */ enum ViewerOptions { /** Do not activate any standard event handlers. * If no event handlers are selected then the users would typically * register their own custom event handlers to add user interaction via * getEventHandlerList().push_back(myEventHandler) or addCameraManipulator(myCameraManipualtor).*/ NO_EVENT_HANDLERS = 0, /** Add an \c osgGA::TrackballManipulator to manipulate the camera * interactively. */ TRACKBALL_MANIPULATOR = 1, /** Add an \c osgGA::DriveManipulator to manipulate the camera * interactively. */ DRIVE_MANIPULATOR = 2, /** Add an \c osgGA::FlightManipulator to manipulate the camera * interactively. */ FLIGHT_MANIPULATOR = 4, /** Add an \c osgGA::TerrainManipulator to manipulate the camera * interactively. */ TERRAIN_MANIPULATOR = 8, /** Add an \c osgGA::UFOManipulator to manipulate the camera * interactively. */ UFO_MANIPULATOR = 0x10, /** Add an \c osgGA::StateSetManipulator to interactively toggle * some bits of the renderer state (texturing, lightning...) */ STATE_MANIPULATOR = 32, /** Add a light source some point near the camera. */ HEAD_LIGHT_SOURCE = 64, /** Add a light source above the scene; does nothing if * \c HEAD_LIGHT_SOURCE is also used. */ SKY_LIGHT_SOURCE = 128, /** Add peformance statistics reporting, currently implemented via VIEWER_MANPULATOR. */ STATS_MANIPULATOR = 256, /** Add an \c osgProducer::ViewerEventHandler that enables lots of * tricks like performance statistics and writing the scene to a * file. */ VIEWER_MANIPULATOR = 512, /** Finish the viewer execution when the ESC key is pressed. */ ESCAPE_SETS_DONE = 1024, /** Enable a set of standard settings (\c TRACKBALL_MANIPULATOR, * \c DRIVE_MANIPULATOR, \c FLIGHT_MANIPULATOR, * \c TERRAIN_MANIPULATOR, \c STATE_MANIPULATOR, * \c HEAD_LIGHT_SOURCE, \c STATS_MANIPULATOR, * \c VIEWER_MANIPULATOR, \c ESCAPE_SETS_DONE). */ STANDARD_SETTINGS = TRACKBALL_MANIPULATOR| DRIVE_MANIPULATOR | FLIGHT_MANIPULATOR | TERRAIN_MANIPULATOR | UFO_MANIPULATOR | STATE_MANIPULATOR | HEAD_LIGHT_SOURCE | STATS_MANIPULATOR | VIEWER_MANIPULATOR | ESCAPE_SETS_DONE }; /** Set up the viewer, allowing to control some aspects of its behavior. * @param options One or more of the options defined by the * \c ViewerOptions enumeration, combined using the bitwise OR * operator (``|''). */ void setUpViewer(unsigned int options=STANDARD_SETTINGS); /** Set the viewer so it sets done to true once the refrence time equals or exceeds specified elapsed time. * Automatically does a setDoneAtElapsedTimeEnabled(true). */ void setDoneAtElapsedTime(double elapsedTime) { _setDoneAtElapsedTimeEnabled = true; _setDoneAtElapsedTime = elapsedTime; } /** Get the elapsed time that will cause done to be set to be true.*/ double getDoneAtElapsedTime() const { return _setDoneAtElapsedTime; } /** Set whether to use a elapsed time to limit the run of the viewer.*/ void setDoneAtElapsedTimeEnabled(bool enabled) { _setDoneAtElapsedTimeEnabled = enabled; } /** Get whether to use a elapsed time to limit the run of the viewer.*/ bool getDoneAtElapsedTimeEnabled() const { return _setDoneAtElapsedTimeEnabled; } /** Set the viewer so it sets done to true once the frame number equals or exceeds specified frame number. * Automatically does a setDoneAtFrameNumberEnabled(true). */ void setDoneAtFrameNumber(unsigned int frameNumber) { _setDoneAtFrameNumberEnabled = true; _setDoneAtFrameNumber = frameNumber; } /** Get the frame number that will cause done to be set to be true.*/ unsigned int getDoneAtFrameNumber() const { return _setDoneAtFrameNumber; } /** Set whether to use a frame number to limit the run of the viewer.*/ void setDoneAtFrameNumberEnabled(bool enabled) { _setDoneAtFrameNumberEnabled = enabled; } /** Get whether to use a frame number to limit the run of the viewer.*/ bool getDoneAtFrameNumberEnabled() const { return _setDoneAtFrameNumberEnabled; } /** Set the done flag signalling that the viewer exit.*/ void setDone(bool done) { _done = done; } /** Get the done flag which signals that the viewer exit.*/ bool getDone() const { return _done; } /** Return true if the application is done and should exit.*/ virtual bool done() const; /** Set the viewer to take an image snapshot on the last frame() when done is enabled.*/ void setWriteImageWhenDone(bool enabled) { _writeImageWhenDone = enabled; } /** Set the viewer to take an image snapshot on the last frame() when done is enabled.*/ bool getWriteImageWhenDone() const { return _writeImageWhenDone; } /** Set the filename to write to when the viewer takes an image snapshot on the last frame() when done is enabled.*/ void setWriteImageFileName(const std::string& filename); /** Get the filename to write to when the viewer takes an image snapshot on the last frame() when done is enabled.*/ const std::string& getWriteImageFileName() const; /** Get the default filename for writing an image snapshot */ static const char* getDefaultImageFileName(); /** Override the Producer::CameraGroup::setViewByMatrix to catch all changes to view.*/ virtual void setViewByMatrix( const Producer::Matrix & pm); /** Set the threading model and then call realize().*/ virtual bool realize(ThreadingModel thread_model); virtual bool realize(); /** Updated the scene. Handle any queued up events, do an update traversal and set the CameraGroup's setViewByMatrix if any camera manipulators are active.*/ virtual void update(); /** Set the update visitor which does the update traversal of the scene graph. Automatically called by the update() method.*/ void setUpdateVisitor(osg::NodeVisitor* nv) { _updateVisitor = nv; } /** Get the update visitor.*/ osg::NodeVisitor* getUpdateVisitor() { return _updateVisitor.get(); } /** Get the const update visitor.*/ const osg::NodeVisitor* getUpdateVisitor() const { return _updateVisitor.get(); } /** Set the update visitor which does the event traversal of the scene graph. Automatically called by the update() method.*/ void setEventVisitor(osgGA::EventVisitor* nv) { _eventVisitor = nv; } /** Get the update visitor.*/ osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); } /** Get the const update visitor.*/ const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); } void computeActiveCoordinateSystemNodePath(); void setCoordinateSystemNodePath(const osg::NodePath& nodePath); osg::NodePath getCoordinateSystemNodePath() const; /** Dispatch the cull and draw for each of the Camera's for this frame.*/ virtual void frame(); virtual void requestRedraw(); virtual void requestContinuousUpdate(bool); virtual void requestWarpPointer(float x,float y); /** Compute, from normalized mouse coords, for sepecified Camera, the pixel coords relative to that Camera's RenderSurface.*/ bool computePixelCoords(float x,float y,unsigned int cameraNum,float& pixel_x,float& pixel_y); /** Compute, from normalized mouse coords, for sepecified Camera, the near and far points in worlds coords.*/ bool computeNearFarPoints(float x,float y,unsigned int cameraNum,osg::Vec3& near, osg::Vec3& far); /** Compute, from normalized mouse coords, for all Cameras, intersections with the specified subgraph.*/ bool computeIntersections(float x,float y,unsigned int cameraNum,osg::Node *node,osgUtil::IntersectVisitor::HitList& hits,osg::Node::NodeMask traversalMask = 0xffffffff); /** Compute, from normalized mouse coords, for sepecified Camera, intersections with the scene.*/ bool computeIntersections(float x,float y,unsigned int cameraNum,osgUtil::IntersectVisitor::HitList& hits,osg::Node::NodeMask traversalMask = 0xffffffff); /** Compute, from normalized mouse coords, for all Cameras, intersections with specified subgraph.*/ bool computeIntersections(float x,float y,osg::Node *node,osgUtil::IntersectVisitor::HitList& hits,osg::Node::NodeMask traversalMask = 0xffffffff); /** Compute, from normalized mouse coords, for all Cameras, intersections with the scene.*/ bool computeIntersections(float x,float y,osgUtil::IntersectVisitor::HitList& hits,osg::Node::NodeMask traversalMask = 0xffffffff); /** Set the EventQueue - a thread safe queue for registering events.*/ void setEventQueue(osgGA::EventQueue* eventQueue) { _eventQueue = eventQueue; } /** Get the EventQueue.*/ osgGA::EventQueue* getEventQueue() { return _eventQueue.get(); } void setKeyboardMouse(Producer::KeyboardMouse* kbm); Producer::KeyboardMouse* getKeyboardMouse() { return _kbm.get(); } const Producer::KeyboardMouse* getKeyboardMouse() const { return _kbm.get(); } void setKeyboardMouseCallback(osgProducer::KeyboardMouseCallback* kbmcb); osgProducer::KeyboardMouseCallback* getKeyboardMouseCallback() { return _kbmcb.get(); } const osgProducer::KeyboardMouseCallback* getKeyboardMouseCallback() const { return _kbmcb.get(); } typedef std::list< osg::ref_ptr > EventHandlerList; EventHandlerList& getEventHandlerList() { return _eventHandlerList; } const EventHandlerList& getEventHandlerList() const { return _eventHandlerList; } osgGA::KeySwitchMatrixManipulator* getKeySwitchMatrixManipulator() { return _keyswitchManipulator.get(); } const osgGA::KeySwitchMatrixManipulator* getKeySwitchMatrixManipulator() const { return _keyswitchManipulator.get(); } unsigned int addCameraManipulator(osgGA::MatrixManipulator* cm); void selectCameraManipulator(unsigned int no); void getCameraManipulatorNameList( std::list &nameList ); bool selectCameraManipulatorByName( const std::string &name ); osgGA::MatrixManipulator *getCameraManipulatorByName( const std::string &name ); void setRecordingAnimationPath(bool on) { _recordingAnimationPath = on; } bool getRecordingAnimationPath() const { return _recordingAnimationPath; } void setAnimationPath(osg::AnimationPath* path) { _animationPath = path; } osg::AnimationPath* getAnimationPath() { return _animationPath.get(); } const osg::AnimationPath* getAnimationPath() const { return _animationPath.get(); } const double* getPosition() const { return _position; } double getSpeed() const { return _speed; } osg::Quat getOrientation() const { return _orientation; } /** Get the keyboard and mouse usage of this viewer.*/ virtual void getUsage(osg::ApplicationUsage& usage) const; /** Update internal structures w.r.t updated scene data.*/ virtual void updatedSceneData(); /** Dispatch a clean up frame that should be called before closing a OsgCameraGroup, i.e. on exit from an app. * The clean up frame first release all GL objects associated with all the graphics context associated with * the camera group, then runs a special frame that does the actual OpenGL deletion of GL objects for each * graphics context. */ virtual void cleanup_frame(); protected : bool _setDoneAtElapsedTimeEnabled; double _setDoneAtElapsedTime; bool _setDoneAtFrameNumberEnabled; unsigned int _setDoneAtFrameNumber; bool _done; bool _writeImageWhenDone; std::string _writeImageFileName; osg::ref_ptr _eventQueue; osg::ref_ptr _kbm; osg::ref_ptr _kbmcb; EventHandlerList _eventHandlerList; osg::ref_ptr _keyswitchManipulator; osg::ref_ptr _updateVisitor; osg::ref_ptr _eventVisitor; typedef std::vector< osg::observer_ptr > ObserveredNodePath; ObserveredNodePath _coordinateSystemNodePath; bool _recordingAnimationPath; double _recordingStartTime; osg::ref_ptr _animationPath; // record the current position and orientation of the view. double _position[3]; osg::Quat _orientation; double _speed; }; } #endif