| 1 | /* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield |
|---|
| 2 | * |
|---|
| 3 | * This library is open source and may be redistributed and/or modified under |
|---|
| 4 | * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or |
|---|
| 5 | * (at your option) any later version. The full license is in LICENSE file |
|---|
| 6 | * included with this distribution, and on the openscenegraph.org website. |
|---|
| 7 | * |
|---|
| 8 | * This library is distributed in the hope that it will be useful, |
|---|
| 9 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 10 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 11 | * OpenSceneGraph Public License for more details. |
|---|
| 12 | */ |
|---|
| 13 | |
|---|
| 14 | #ifndef OSGVIEWER_VIEWERBASE |
|---|
| 15 | #define OSGVIEWER_VIEWERBASE 1 |
|---|
| 16 | |
|---|
| 17 | #include <osg/Stats> |
|---|
| 18 | |
|---|
| 19 | #include <osgUtil/UpdateVisitor> |
|---|
| 20 | #include <osgUtil/GLObjectsVisitor> |
|---|
| 21 | |
|---|
| 22 | #include <osgGA/MatrixManipulator> |
|---|
| 23 | #include <osgGA/EventVisitor> |
|---|
| 24 | #include <osgGA/EventQueue> |
|---|
| 25 | |
|---|
| 26 | #include <osgViewer/Scene> |
|---|
| 27 | #include <osgViewer/GraphicsWindow> |
|---|
| 28 | |
|---|
| 29 | namespace osgViewer { |
|---|
| 30 | |
|---|
| 31 | #define USE_REFERENCE_TIME DBL_MAX |
|---|
| 32 | |
|---|
| 33 | class View; |
|---|
| 34 | |
|---|
| 35 | /** ViewerBase is the view base class that is inherited by both Viewer and CompositeViewer.*/ |
|---|
| 36 | class OSGVIEWER_EXPORT ViewerBase : public virtual osg::Object |
|---|
| 37 | { |
|---|
| 38 | public: |
|---|
| 39 | |
|---|
| 40 | ViewerBase(); |
|---|
| 41 | ViewerBase(const ViewerBase& vb); |
|---|
| 42 | |
|---|
| 43 | |
|---|
| 44 | /** Set the Stats object used for collect various frame related timing and scene graph stats.*/ |
|---|
| 45 | virtual void setViewerStats(osg::Stats* stats) = 0; |
|---|
| 46 | |
|---|
| 47 | /** Get the Viewers Stats object.*/ |
|---|
| 48 | virtual osg::Stats* getViewerStats() = 0; |
|---|
| 49 | |
|---|
| 50 | /** Get the Viewers Stats object.*/ |
|---|
| 51 | virtual const osg::Stats* getViewerStats() const = 0; |
|---|
| 52 | |
|---|
| 53 | |
|---|
| 54 | /** read the viewer configuration from a configuration file.*/ |
|---|
| 55 | virtual bool readConfiguration(const std::string& filename) = 0; |
|---|
| 56 | |
|---|
| 57 | /** Get whether at least of one of this viewers windows are realized.*/ |
|---|
| 58 | virtual bool isRealized() const = 0; |
|---|
| 59 | |
|---|
| 60 | /** set up windows and associated threads.*/ |
|---|
| 61 | virtual void realize() = 0; |
|---|
| 62 | |
|---|
| 63 | enum ThreadingModel |
|---|
| 64 | { |
|---|
| 65 | SingleThreaded, |
|---|
| 66 | CullDrawThreadPerContext, |
|---|
| 67 | ThreadPerContext = CullDrawThreadPerContext, |
|---|
| 68 | DrawThreadPerContext, |
|---|
| 69 | CullThreadPerCameraDrawThreadPerContext, |
|---|
| 70 | ThreadPerCamera = CullThreadPerCameraDrawThreadPerContext, |
|---|
| 71 | AutomaticSelection |
|---|
| 72 | }; |
|---|
| 73 | |
|---|
| 74 | /** Set the threading model the rendering traversals will use.*/ |
|---|
| 75 | virtual void setThreadingModel(ThreadingModel threadingModel); |
|---|
| 76 | |
|---|
| 77 | /** Get the threading model the rendering traversals will use.*/ |
|---|
| 78 | ThreadingModel getThreadingModel() const { return _threadingModel; } |
|---|
| 79 | |
|---|
| 80 | /** Let the viewer suggest the best threading model for the viewers camera/window setup and the hardware available.*/ |
|---|
| 81 | virtual ThreadingModel suggestBestThreadingModel(); |
|---|
| 82 | |
|---|
| 83 | /** Set up the threading and processor affinity as per the viewers threading model.*/ |
|---|
| 84 | virtual void setUpThreading(); |
|---|
| 85 | |
|---|
| 86 | /** Return true if viewer threads are running. */ |
|---|
| 87 | bool areThreadsRunning() const { return _threadsRunning; } |
|---|
| 88 | |
|---|
| 89 | /** Stop any threads begin run by viewer.*/ |
|---|
| 90 | virtual void stopThreading(); |
|---|
| 91 | |
|---|
| 92 | /** Start any threads required by the viewer.*/ |
|---|
| 93 | virtual void startThreading(); |
|---|
| 94 | |
|---|
| 95 | enum BarrierPosition |
|---|
| 96 | { |
|---|
| 97 | BeforeSwapBuffers, |
|---|
| 98 | AfterSwapBuffers |
|---|
| 99 | }; |
|---|
| 100 | |
|---|
| 101 | /** Set the position of the end barrier. |
|---|
| 102 | * AfterSwapBuffers may result in slightly higher framerates, but may |
|---|
| 103 | * lead to inconsistent swapping between different windows. |
|---|
| 104 | * BeforeSwapBuffers may lead to slightly lower framerate, but improve consistency in timing of swap buffers, |
|---|
| 105 | * especially important if you are likely to consistently break frame.*/ |
|---|
| 106 | void setEndBarrierPosition(BarrierPosition bp); |
|---|
| 107 | |
|---|
| 108 | /** Get the end barrier position.*/ |
|---|
| 109 | BarrierPosition getEndBarrierPosition() const { return _endBarrierPosition; } |
|---|
| 110 | |
|---|
| 111 | |
|---|
| 112 | |
|---|
| 113 | /** Set the done flag to signal the viewer's work is done and should exit the frame loop.*/ |
|---|
| 114 | void setDone(bool done) { _done = done; } |
|---|
| 115 | |
|---|
| 116 | /** Return true if viewer's work is done and should exit the frame loop.*/ |
|---|
| 117 | bool done() const { return _done; } |
|---|
| 118 | |
|---|
| 119 | /** Set the EventVisitor. */ |
|---|
| 120 | void setEventVisitor(osgGA::EventVisitor* eventVisitor) { _eventVisitor = eventVisitor; } |
|---|
| 121 | |
|---|
| 122 | /** Get the EventVisitor. */ |
|---|
| 123 | osgGA::EventVisitor* getEventVisitor() { return _eventVisitor.get(); } |
|---|
| 124 | |
|---|
| 125 | /** Get the const EventVisitor. */ |
|---|
| 126 | const osgGA::EventVisitor* getEventVisitor() const { return _eventVisitor.get(); } |
|---|
| 127 | |
|---|
| 128 | /** Set the key event that the viewer checks on each frame to see if the viewer's done flag should be set to |
|---|
| 129 | * signal end of viewers main loop. |
|---|
| 130 | * Default value is Escape (osgGA::GUIEVentAdapter::KEY_Escape). |
|---|
| 131 | * Setting to 0 switches off the feature.*/ |
|---|
| 132 | void setKeyEventSetsDone(int key) { _keyEventSetsDone = key; } |
|---|
| 133 | |
|---|
| 134 | /** get the key event that the viewer checks on each frame to see if the viewer's done flag.*/ |
|---|
| 135 | int getKeyEventSetsDone() const { return _keyEventSetsDone; } |
|---|
| 136 | |
|---|
| 137 | /** if the flag is true, the viewer set its done flag when a QUIT_APPLICATION is received, false disables this feature */ |
|---|
| 138 | void setQuitEventSetsDone(bool flag) { _quitEventSetsDone = flag; } |
|---|
| 139 | |
|---|
| 140 | /** @return true if the viewer respond to the QUIT_APPLICATION-event */ |
|---|
| 141 | bool getQuitEventSetsDone() const { return _quitEventSetsDone; } |
|---|
| 142 | |
|---|
| 143 | |
|---|
| 144 | /** Hint to tell the renderingTraversals() method whether to call relaseContext() on the last |
|---|
| 145 | * context that was made current by the thread calling renderingTraverals(). Note, when |
|---|
| 146 | * running multi-threaded viewer no threads will be made current or release current. |
|---|
| 147 | * Setting this hint to false can enable the frame loop to be lazy about calling makeCurrent |
|---|
| 148 | * and releaseContext on each new frame, helping performance. However, if you frame loop |
|---|
| 149 | * is managing multiple graphics context all from the main frame thread then this hint must |
|---|
| 150 | * be left on, otherwise the wrong context could be left active, introducing errors in rendering.*/ |
|---|
| 151 | void setReleaseContextAtEndOfFrameHint(bool hint) { _releaseContextAtEndOfFrameHint = hint; } |
|---|
| 152 | |
|---|
| 153 | /** Hint to tell the renderingTraversals() method whether to call relaseContext().*/ |
|---|
| 154 | bool getReleaseContextAtEndOfFrameHint() const { return _releaseContextAtEndOfFrameHint; } |
|---|
| 155 | |
|---|
| 156 | |
|---|
| 157 | /** Set the UpdateVisitor. */ |
|---|
| 158 | void setUpdateVisitor(osgUtil::UpdateVisitor* updateVisitor) { _updateVisitor = updateVisitor; } |
|---|
| 159 | |
|---|
| 160 | /** Get the UpdateVisitor. */ |
|---|
| 161 | osgUtil::UpdateVisitor* getUpdateVisitor() { return _updateVisitor.get(); } |
|---|
| 162 | |
|---|
| 163 | /** Get the const UpdateVisitor. */ |
|---|
| 164 | const osgUtil::UpdateVisitor* getUpdateVisitor() const { return _updateVisitor.get(); } |
|---|
| 165 | |
|---|
| 166 | |
|---|
| 167 | /** Set the Update OperationQueue. */ |
|---|
| 168 | void setUpdateOperations(osg::OperationQueue* operations) { _updateOperations = operations; } |
|---|
| 169 | |
|---|
| 170 | /** Get the Update OperationQueue. */ |
|---|
| 171 | osg::OperationQueue* getUpdateOperations() { return _updateOperations.get(); } |
|---|
| 172 | |
|---|
| 173 | /** Get the const Update OperationQueue. */ |
|---|
| 174 | const osg::OperationQueue* getUpdateOperations() const { return _updateOperations.get(); } |
|---|
| 175 | |
|---|
| 176 | /** Add an update operation.*/ |
|---|
| 177 | void addUpdateOperation(osg::Operation* operation); |
|---|
| 178 | |
|---|
| 179 | /** Remove an update operation.*/ |
|---|
| 180 | void removeUpdateOperation(osg::Operation* operation); |
|---|
| 181 | |
|---|
| 182 | |
|---|
| 183 | /** Set the graphics operation to call on realization of the viewers graphics windows.*/ |
|---|
| 184 | void setRealizeOperation(osg::Operation* op) { _realizeOperation = op; } |
|---|
| 185 | |
|---|
| 186 | /** Get the graphics operation to call on realization of the viewers graphics windows.*/ |
|---|
| 187 | osg::Operation* getRealizeOperation() { return _realizeOperation.get(); } |
|---|
| 188 | |
|---|
| 189 | |
|---|
| 190 | /** Set the incremental compile operation. |
|---|
| 191 | * Used to manage the OpenGL object compilation and merging of subgraphs in a way that avoids overloading |
|---|
| 192 | * the rendering of frame with too many new objects in one frame. */ |
|---|
| 193 | void setIncrementalCompileOperation(osgUtil::IncrementalCompileOperation* ico); |
|---|
| 194 | |
|---|
| 195 | /** Get the incremental compile operation. */ |
|---|
| 196 | osgUtil::IncrementalCompileOperation* getIncrementalCompileOperation() { return _incrementalCompileOperation.get(); } |
|---|
| 197 | |
|---|
| 198 | |
|---|
| 199 | /** Check to see if windows are still open, if not set viewer done to true. */ |
|---|
| 200 | void checkWindowStatus(); |
|---|
| 201 | |
|---|
| 202 | |
|---|
| 203 | |
|---|
| 204 | /** Execute a main frame loop. |
|---|
| 205 | * Equivalent to while (!viewer.done()) viewer.frame(); |
|---|
| 206 | * Also calls realize() if the viewer is not already realized, |
|---|
| 207 | * and installs trackball manipulator if one is not already assigned. |
|---|
| 208 | */ |
|---|
| 209 | virtual int run() = 0; |
|---|
| 210 | |
|---|
| 211 | /** Render a complete new frame. |
|---|
| 212 | * Calls advance(), eventTraversal(), updateTraversal(), renderingTraversals(). */ |
|---|
| 213 | virtual void frame(double simulationTime=USE_REFERENCE_TIME); |
|---|
| 214 | |
|---|
| 215 | virtual void advance(double simulationTime=USE_REFERENCE_TIME) = 0; |
|---|
| 216 | |
|---|
| 217 | virtual void eventTraversal() = 0; |
|---|
| 218 | |
|---|
| 219 | virtual void updateTraversal() = 0; |
|---|
| 220 | |
|---|
| 221 | virtual void renderingTraversals(); |
|---|
| 222 | |
|---|
| 223 | typedef std::vector<osg::Camera*> Cameras; |
|---|
| 224 | virtual void getCameras(Cameras& cameras, bool onlyActive=true) = 0; |
|---|
| 225 | |
|---|
| 226 | typedef std::vector<osg::GraphicsContext*> Contexts; |
|---|
| 227 | virtual void getContexts(Contexts& contexts, bool onlyValid=true) = 0; |
|---|
| 228 | |
|---|
| 229 | typedef std::vector<osgViewer::GraphicsWindow*> Windows; |
|---|
| 230 | virtual void getWindows(Windows& windows, bool onlyValid=true); |
|---|
| 231 | |
|---|
| 232 | typedef std::vector<OpenThreads::Thread*> Threads; |
|---|
| 233 | virtual void getAllThreads(Threads& threads, bool onlyActive=true) = 0; |
|---|
| 234 | |
|---|
| 235 | typedef std::vector<osg::OperationThread*> OperationThreads; |
|---|
| 236 | virtual void getOperationThreads(OperationThreads& threads, bool onlyActive=true) = 0; |
|---|
| 237 | |
|---|
| 238 | typedef std::vector<osgViewer::Scene*> Scenes; |
|---|
| 239 | virtual void getScenes(Scenes& scenes, bool onlyValid=true) = 0; |
|---|
| 240 | |
|---|
| 241 | typedef std::vector<osgViewer::View*> Views; |
|---|
| 242 | virtual void getViews(Views& views, bool onlyValid=true) = 0; |
|---|
| 243 | |
|---|
| 244 | virtual double elapsedTime() = 0; |
|---|
| 245 | |
|---|
| 246 | virtual osg::FrameStamp* getViewerFrameStamp() = 0; |
|---|
| 247 | |
|---|
| 248 | /** Get the keyboard and mouse usage of this viewer.*/ |
|---|
| 249 | virtual void getUsage(osg::ApplicationUsage& usage) const = 0; |
|---|
| 250 | |
|---|
| 251 | protected: |
|---|
| 252 | |
|---|
| 253 | inline void makeCurrent(osg::GraphicsContext* gc) |
|---|
| 254 | { |
|---|
| 255 | if (_currentContext==gc) return; |
|---|
| 256 | |
|---|
| 257 | releaseContext(); |
|---|
| 258 | |
|---|
| 259 | if (gc && gc->valid() && gc->makeCurrent()) _currentContext = gc; |
|---|
| 260 | } |
|---|
| 261 | |
|---|
| 262 | inline void releaseContext() |
|---|
| 263 | { |
|---|
| 264 | if (_currentContext.valid() && _currentContext->valid()) |
|---|
| 265 | { |
|---|
| 266 | _currentContext->releaseContext(); |
|---|
| 267 | } |
|---|
| 268 | _currentContext = 0; |
|---|
| 269 | } |
|---|
| 270 | |
|---|
| 271 | virtual void viewerInit() = 0; |
|---|
| 272 | |
|---|
| 273 | bool _firstFrame; |
|---|
| 274 | bool _done; |
|---|
| 275 | int _keyEventSetsDone; |
|---|
| 276 | bool _quitEventSetsDone; |
|---|
| 277 | bool _releaseContextAtEndOfFrameHint; |
|---|
| 278 | |
|---|
| 279 | ThreadingModel _threadingModel; |
|---|
| 280 | bool _threadsRunning; |
|---|
| 281 | |
|---|
| 282 | BarrierPosition _endBarrierPosition; |
|---|
| 283 | |
|---|
| 284 | osg::ref_ptr<osg::BarrierOperation> _startRenderingBarrier; |
|---|
| 285 | osg::ref_ptr<osg::BarrierOperation> _endRenderingDispatchBarrier; |
|---|
| 286 | osg::ref_ptr<osg::EndOfDynamicDrawBlock> _endDynamicDrawBlock; |
|---|
| 287 | |
|---|
| 288 | osg::ref_ptr<osgGA::EventVisitor> _eventVisitor; |
|---|
| 289 | |
|---|
| 290 | osg::ref_ptr<osg::OperationQueue> _updateOperations; |
|---|
| 291 | osg::ref_ptr<osgUtil::UpdateVisitor> _updateVisitor; |
|---|
| 292 | |
|---|
| 293 | osg::ref_ptr<osg::Operation> _realizeOperation; |
|---|
| 294 | osg::ref_ptr<osgUtil::IncrementalCompileOperation> _incrementalCompileOperation; |
|---|
| 295 | |
|---|
| 296 | osg::observer_ptr<osg::GraphicsContext> _currentContext; |
|---|
| 297 | }; |
|---|
| 298 | |
|---|
| 299 | } |
|---|
| 300 | |
|---|
| 301 | #endif |
|---|