OpenWalnut  1.4.0
WGraphicsEngine.cpp
1 //---------------------------------------------------------------------------
2 //
3 // Project: OpenWalnut ( http://www.openwalnut.org )
4 //
5 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
6 // For more information see http://www.openwalnut.org/copying
7 //
8 // This file is part of OpenWalnut.
9 //
10 // OpenWalnut is free software: you can redistribute it and/or modify
11 // it under the terms of the GNU Lesser General Public License as published by
12 // the Free Software Foundation, either version 3 of the License, or
13 // (at your option) any later version.
14 //
15 // OpenWalnut is distributed in the hope that it will be useful,
16 // but WITHOUT ANY WARRANTY; without even the implied warranty of
17 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 // GNU Lesser General Public License for more details.
19 //
20 // You should have received a copy of the GNU Lesser General Public License
21 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
22 //
23 //---------------------------------------------------------------------------
24 
25 #include <stdlib.h>
26 
27 #include <iostream>
28 #include <list>
29 #include <string>
30 #include <vector>
31 
32 #include <boost/shared_ptr.hpp>
33 #include <boost/thread/locks.hpp>
34 
35 #include <osg/Vec3>
36 #include <osg/Vec4>
37 #include <osg/ref_ptr>
38 #include <osgViewer/CompositeViewer>
39 #include <osgViewer/View>
40 #include <osgViewer/Viewer>
41 
42 #include "../common/WColor.h"
43 #include "../common/WLogger.h"
44 #include "../common/WPathHelper.h"
45 #include "WGEViewer.h"
46 #include "exceptions/WGEInitFailed.h"
47 #include "exceptions/WGESignalSubscriptionFailed.h"
48 #include "WGraphicsEngineMode.h"
49 #include "postprocessing/WGEPostprocessor.h"
50 
51 #include "WStaticOSGSetup.h"
52 
53 #include "WGraphicsEngine.h"
54 
55 // graphics engine instance as singleton
56 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::m_instance = boost::shared_ptr< WGraphicsEngine >();
57 
60 {
61  WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_INFO );
62 
63 #ifdef WGEMODE_MULTITHREADED
64  // initialize OSG render window
65  m_viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() );
66  m_viewer->setThreadingModel( osgViewer::ViewerBase::SingleThreaded );
67 #endif
68 
69  // initialize members
70  m_rootNode = new WGEScene();
71 
72  setThreadName( "WGE" );
73 }
74 
76 {
77  // cleanup
78  WLogger::getLogger()->addLogMessage( "Shutting down Graphics Engine", "GE", LL_INFO );
79 }
80 
82 {
83 #ifdef WGEMODE_SINGLETHREADED
84  if( enable )
85  {
86  WLogger::getLogger()->addLogMessage( "WGraphicsEngine::setMultiThreadedViews not implemented for single threaded mode", "GE", LL_INFO );
87  }
88 #else
89  // ThreadingModel: enum with the following possibilities
90  //
91  // SingleThreaded
92  // CullDrawThreadPerContext
93  // ThreadPerContext
94  // DrawThreadPerContext
95  // CullThreadPerCameraDrawThreadPerContext
96  // ThreadPerCamera
97  // AutomaticSelection
98  if( !enable )
99  {
100  m_viewer->setThreadingModel( osgViewer::Viewer::SingleThreaded );
101  }
102  else
103  {
104  m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
105  }
106 #endif
107 }
108 
110 {
111 #ifdef WGEMODE_MULTITHREADED
112  return ( osgViewer::Viewer::SingleThreaded != m_viewer->getThreadingModel() );
113 #endif
114  // on mac, this always is false currently
115  return false;
116 }
117 
118 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::getGraphicsEngine()
119 {
120  if( !m_instance )
121  {
122  m_instance = boost::shared_ptr< WGraphicsEngine >( new WGraphicsEngine() );
123  }
124 
125  return m_instance;
126 }
127 
128 osg::ref_ptr<WGEScene> WGraphicsEngine::getScene()
129 {
130  return m_rootNode;
131 }
132 
133 boost::shared_ptr<WGEViewer> WGraphicsEngine::createViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int x, int y,
134  int width, int height, WGECamera::ProjectionMode projectionMode,
135  WColor bgColor )
136 {
137  boost::shared_ptr<WGEViewer> viewer = boost::shared_ptr<WGEViewer>(
138  new WGEViewer( name, wdata, x, y, width, height, projectionMode ) );
139  viewer->setBgColor( bgColor );
140  viewer->setScene( getScene() );
141 
142 #ifdef WGEMODE_MULTITHREADED
143  // finally add view
144  m_viewer->addView( viewer->getView() );
145 #endif
146 
147  // store it in viewer list
148  boost::mutex::scoped_lock lock( m_viewersLock );
149  bool insertSucceeded = m_viewers.insert( make_pair( name, viewer ) ).second;
150  assert( insertSucceeded == true ); // if false, viewer with same name already exists
151 
152  return viewer;
153 }
154 
155 void WGraphicsEngine::closeViewer( const std::string name )
156 {
157  boost::mutex::scoped_lock lock( m_viewersLock );
158  if( m_viewers.count( name ) > 0 )
159  {
160  m_viewers[name]->close();
161 
162  m_viewers.erase( name );
163  }
164 }
165 
166 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewerByName( std::string name )
167 {
168  boost::mutex::scoped_lock lock( m_viewersLock );
169  boost::shared_ptr< WGEViewer > out = m_viewers.count( name ) > 0 ?
170  m_viewers[name] :
171  boost::shared_ptr< WGEViewer >();
172  return out;
173 }
174 
175 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewer()
176 {
177  boost::mutex::scoped_lock lock( m_viewersLock );
178  return m_viewers[ "Main View" ];
179 }
180 
182 {
183  if( !m_instance )
184  {
185  return false;
186  }
187 
188  return m_instance->m_running;
189 }
190 
192 {
193  if( !m_instance )
194  {
195  WLogger::getLogger()->addLogMessage( "Not Graphics Engine running", "GE", LL_INFO );
196  return false;
197  }
198 
199  WLogger::getLogger()->addLogMessage( "Blocking for graphics engine startup", "GE", LL_INFO );
200  // this ensures that the startup is completed if returning.
201  m_instance->m_startThreadingCondition.wait();
202 
203  WLogger::getLogger()->addLogMessage( "Done blocking for graphics engine startup, maybe running now", "GE", LL_INFO );
204  // did something went wrong? Ensure by checking if really running.
205  return isRunning();
206 }
207 
209 {
210  WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_INFO );
211 
212  // initialize all available postprocessors
214 
215 #ifdef WGEMODE_MULTITHREADED
216  // NOTE: this is needed here since the viewer might start without any widgets being initialized properly.
218  m_running = true;
219  m_viewer->startThreading();
220  m_viewer->run();
221  m_viewer->stopThreading();
222  m_running = false;
223 #else
224  //m_startThreadingCondition.wait();
225  m_running = true; // we have to make sure, that we are "running"
226 #endif
227 }
228 
230 {
231  // when stopping the system while the GE is still waiting.
233  WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_INFO );
234 #ifdef WGEMODE_MULTITHREADED
235  m_viewer->setDone( true );
236 #endif
237 }
238 
240 {
242 }
243 
245 {
247 }
248 
250 {
252 }
253 
254 boost::signals2::connection WGraphicsEngine::subscribeSignal( GE_SIGNAL signal, t_GEGenericSignalHandlerType notifier )
255 {
256  switch( signal )
257  {
258  case GE_RELOADSHADERS:
259  return m_reloadShadersSignal.connect( notifier );
260  case GE_STARTUPCOMPLETE:
261  return m_startThreadingCondition.subscribeSignal( notifier );
262  default:
263  std::ostringstream s;
264  s << "Could not subscribe to unknown signal.";
265  throw WGESignalSubscriptionFailed( s.str() );
266  break;
267  }
268 }