OpenWalnut 1.2.5
WGraphicsEngine.cpp
00001 //---------------------------------------------------------------------------
00002 //
00003 // Project: OpenWalnut ( http://www.openwalnut.org )
00004 //
00005 // Copyright 2009 OpenWalnut Community, BSV@Uni-Leipzig and CNCF@MPI-CBS
00006 // For more information see http://www.openwalnut.org/copying
00007 //
00008 // This file is part of OpenWalnut.
00009 //
00010 // OpenWalnut is free software: you can redistribute it and/or modify
00011 // it under the terms of the GNU Lesser General Public License as published by
00012 // the Free Software Foundation, either version 3 of the License, or
00013 // (at your option) any later version.
00014 //
00015 // OpenWalnut is distributed in the hope that it will be useful,
00016 // but WITHOUT ANY WARRANTY; without even the implied warranty of
00017 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00018 // GNU Lesser General Public License for more details.
00019 //
00020 // You should have received a copy of the GNU Lesser General Public License
00021 // along with OpenWalnut. If not, see <http://www.gnu.org/licenses/>.
00022 //
00023 //---------------------------------------------------------------------------
00024 
00025 #include <stdlib.h>
00026 
00027 #include <iostream>
00028 #include <list>
00029 #include <string>
00030 #include <vector>
00031 
00032 #include <boost/shared_ptr.hpp>
00033 #include <boost/thread/locks.hpp>
00034 
00035 #include <osg/Vec3>
00036 #include <osg/Vec4>
00037 #include <osg/ref_ptr>
00038 #include <osgViewer/CompositeViewer>
00039 #include <osgViewer/View>
00040 #include <osgViewer/Viewer>
00041 
00042 #include "../common/WColor.h"
00043 #include "../common/WLogger.h"
00044 #include "../common/WPathHelper.h"
00045 #include "../common/math/linearAlgebra/WLinearAlgebra.h"
00046 #include "WGEViewer.h"
00047 #include "exceptions/WGEInitFailed.h"
00048 #include "exceptions/WGESignalSubscriptionFailed.h"
00049 #include "WGraphicsEngine.h"
00050 
00051 // graphics engine instance as singleton
00052 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::m_instance = boost::shared_ptr< WGraphicsEngine >();
00053 
00054 WGraphicsEngine::WGraphicsEngine():
00055     WThreadedRunner()
00056 {
00057     WLogger::getLogger()->addLogMessage( "Initializing Graphics Engine", "GE", LL_INFO );
00058 
00059     // NOTE: the osgViewer::StatsHandler uses a hard coded font filename. :-(. Fortunately OSG allows us to modify the search path using
00060     // environment variables:
00061 #ifndef _WIN32
00062     setenv( "OSGFILEPATH", WPathHelper::getFontPath().file_string().c_str(), 1 );
00063 #else
00064     std::string envStr = std::string( "OSGFILEPATH=" ) + WPathHelper::getFontPath().file_string();
00065     putenv( envStr.c_str() );
00066 #endif
00067 
00068 #ifndef __APPLE__
00069     // initialize OSG render window
00070     m_viewer = osg::ref_ptr<osgViewer::CompositeViewer>( new osgViewer::CompositeViewer() );
00071 #endif
00072 
00073     // initialize members
00074     m_rootNode = new WGEScene();
00075 }
00076 
00077 WGraphicsEngine::~WGraphicsEngine()
00078 {
00079     // cleanup
00080     WLogger::getLogger()->addLogMessage( "Shutting down Graphics Engine", "GE", LL_INFO );
00081 }
00082 
00083 void WGraphicsEngine::setMultiThreadedViews( bool enable )
00084 {
00085 #ifndef __APPLE__
00086     // ThreadingModel: enum with the following possibilities
00087     //
00088     //  SingleThreaded
00089     //  CullDrawThreadPerContext
00090     //  ThreadPerContext
00091     //  DrawThreadPerContext
00092     //  CullThreadPerCameraDrawThreadPerContext
00093     //  ThreadPerCamera
00094     //  AutomaticSelection
00095     if( !enable )
00096     {
00097         m_viewer->setThreadingModel( osgViewer::Viewer::SingleThreaded );
00098     }
00099     else
00100     {
00101         m_viewer->setThreadingModel( osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext );
00102     }
00103 #endif
00104 }
00105 
00106 bool WGraphicsEngine::isMultiThreadedViews() const
00107 {
00108 #ifndef __APPLE__
00109     return ( osgViewer::Viewer::SingleThreaded != m_viewer->getThreadingModel() );
00110 #endif
00111     // on mac, this always is false currently
00112     return false;
00113 }
00114 
00115 boost::shared_ptr< WGraphicsEngine > WGraphicsEngine::getGraphicsEngine()
00116 {
00117     if( !m_instance )
00118     {
00119         m_instance = boost::shared_ptr< WGraphicsEngine >( new WGraphicsEngine() );
00120     }
00121 
00122     return m_instance;
00123 }
00124 
00125 osg::ref_ptr<WGEScene> WGraphicsEngine::getScene()
00126 {
00127     return m_rootNode;
00128 }
00129 
00130 boost::shared_ptr<WGEViewer> WGraphicsEngine::createViewer( std::string name, osg::ref_ptr<osg::Referenced> wdata, int x, int y,
00131                                                             int width, int height, WGECamera::ProjectionMode projectionMode,
00132                                                             WColor bgColor )
00133 {
00134     boost::shared_ptr<WGEViewer> viewer = boost::shared_ptr<WGEViewer>(
00135         new WGEViewer( name, wdata, x, y, width, height, projectionMode ) );
00136     viewer->setBgColor( bgColor );
00137     viewer->setScene( getScene() );
00138 
00139 #ifndef __APPLE__
00140     // finally add view
00141     m_viewer->addView( viewer->getView() );
00142 #endif
00143 
00144     // store it in viewer list
00145     boost::mutex::scoped_lock lock( m_viewersLock );
00146     bool insertSucceeded = m_viewers.insert( make_pair( name, viewer ) ).second;
00147     assert( insertSucceeded == true );
00148 
00149     return viewer;
00150 }
00151 
00152 void WGraphicsEngine::closeViewer( const std::string name )
00153 {
00154     boost::mutex::scoped_lock lock( m_viewersLock );
00155     if( m_viewers.count( name ) > 0 )
00156     {
00157         m_viewers[name]->close();
00158 
00159         m_viewers.erase( name );
00160     }
00161 }
00162 
00163 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewerByName( std::string name )
00164 {
00165     boost::mutex::scoped_lock lock( m_viewersLock );
00166     boost::shared_ptr< WGEViewer > out = m_viewers.count( name ) > 0 ?
00167         m_viewers[name] :
00168         boost::shared_ptr< WGEViewer >();
00169     return out;
00170 }
00171 
00172 boost::shared_ptr< WGEViewer > WGraphicsEngine::getViewer()
00173 {
00174     boost::mutex::scoped_lock lock( m_viewersLock );
00175     return m_viewers[ "main" ];
00176 }
00177 
00178 bool WGraphicsEngine::isRunning()
00179 {
00180     if( !m_instance )
00181     {
00182         return false;
00183     }
00184 
00185     return m_instance->m_running;
00186 }
00187 
00188 bool WGraphicsEngine::waitForStartupComplete()
00189 {
00190     if( !m_instance )
00191     {
00192         return false;
00193     }
00194 
00195     // this ensures that the startup is completed if returning.
00196     m_instance->m_startThreadingCondition.wait();
00197 
00198     // did something went wrong? Ensure by checking if really running.
00199     return isRunning();
00200 }
00201 
00202 void WGraphicsEngine::threadMain()
00203 {
00204     WLogger::getLogger()->addLogMessage( "Starting Graphics Engine", "GE", LL_INFO );
00205 
00206 #ifndef __APPLE__
00207     // NOTE: this is needed here since the viewer might start without any widgets being initialized properly.
00208     m_startThreadingCondition.wait();
00209     m_running = true;
00210     m_viewer->startThreading();
00211     m_viewer->run();
00212     m_viewer->stopThreading();
00213     m_running = false;
00214 #endif
00215 }
00216 
00217 void WGraphicsEngine::notifyStop()
00218 {
00219     WLogger::getLogger()->addLogMessage( "Stopping Graphics Engine", "GE", LL_INFO );
00220 #ifndef __APPLE__
00221     m_viewer->setDone( true );
00222 #endif
00223 }
00224 
00225 void WGraphicsEngine::finalizeStartup()
00226 {
00227     m_startThreadingCondition.notify();
00228 }
00229 
00230 void WGraphicsEngine::requestShaderReload()
00231 {
00232     m_reloadShadersSignal();
00233 }
00234 
00235 boost::signals2::connection WGraphicsEngine::subscribeSignal( GE_SIGNAL signal, t_GEGenericSignalHandlerType notifier )
00236 {
00237     switch ( signal )
00238     {
00239         case GE_RELOADSHADERS:
00240             return m_reloadShadersSignal.connect( notifier );
00241         default:
00242             std::ostringstream s;
00243             s << "Could not subscribe to unknown signal.";
00244             throw WGESignalSubscriptionFailed( s.str() );
00245             break;
00246     }
00247 }
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator Friends