2006-11-27 22:52:07 +08:00
/* -*-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 ,
2006-11-29 19:00:02 +08:00
* but WITHOUT ANY WARRANTY
{
}
without even the implied warranty of
2006-11-27 22:52:07 +08:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* OpenSceneGraph Public License for more details .
*/
2006-12-23 01:46:21 +08:00
# include <osg/GLExtensions>
2007-01-05 18:59:23 +08:00
# include <osgUtil/GLObjectsVisitor>
# include <osgGA/TrackballManipulator>
# include <osgViewer/Viewer>
2006-11-27 22:52:07 +08:00
2007-01-02 02:20:10 +08:00
# include <osg/io_utils>
2006-12-21 05:13:29 +08:00
2007-01-02 02:20:10 +08:00
using namespace osgViewer ;
2006-12-21 05:13:29 +08:00
Viewer : : Viewer ( ) :
2006-12-22 00:56:20 +08:00
_firstFrame ( true ) ,
2007-01-03 01:39:31 +08:00
_done ( false ) ,
2007-01-05 05:28:16 +08:00
_keySetsDone ( osgGA : : GUIEventAdapter : : KEY_Escape ) ,
2007-01-09 18:06:20 +08:00
_quitEventSetsDone ( true ) ,
2007-01-04 19:49:15 +08:00
_threadingModel ( ThreadPerContext ) ,
_numThreadsOnBarrier ( 0 )
2006-11-27 22:52:07 +08:00
{
}
Viewer : : ~ Viewer ( )
{
2007-01-04 00:06:12 +08:00
//osg::notify(osg::NOTICE)<<"Viewer::~Viewer()"<<std::endl;
2007-01-04 19:49:15 +08:00
stopThreading ( ) ;
2006-12-23 01:46:21 +08:00
if ( _scene . valid ( ) & & _scene - > getDatabasePager ( ) )
{
_scene - > getDatabasePager ( ) - > cancel ( ) ;
_scene - > setDatabasePager ( 0 ) ;
}
2007-01-04 00:06:12 +08:00
2007-01-09 00:20:10 +08:00
Contexts contexts ;
getContexts ( contexts ) ;
// clear out all the previously assigned operations
for ( Contexts : : iterator citr = contexts . begin ( ) ;
citr ! = contexts . end ( ) ;
+ + citr )
{
( * citr ) - > close ( ) ;
}
2007-01-04 00:06:12 +08:00
//osg::notify(osg::NOTICE)<<"finish Viewer::~Viewer()"<<std::endl;
2007-01-09 00:20:10 +08:00
2006-11-27 22:52:07 +08:00
}
2006-11-29 19:00:02 +08:00
2007-01-05 18:59:23 +08:00
bool Viewer : : isRealized ( ) const
{
Contexts contexts ;
const_cast < Viewer * > ( this ) - > getContexts ( contexts ) ;
unsigned int numRealizedWindows = 0 ;
// clear out all the previously assigned operations
for ( Contexts : : iterator citr = contexts . begin ( ) ;
citr ! = contexts . end ( ) ;
+ + citr )
{
if ( ( * citr ) - > isRealized ( ) ) + + numRealizedWindows ;
}
return numRealizedWindows > 0 ;
}
2007-01-05 21:16:24 +08:00
int Viewer : : run ( )
2007-01-05 18:59:23 +08:00
{
// if we don't have any scene graph assigned then just return
if ( ! getSceneData ( ) )
{
osg : : notify ( osg : : NOTICE ) < < " Warning: Viewer::run() called without a scene graph being assigned to the viewer, cannot run. " < < std : : endl ;
2007-01-05 21:16:24 +08:00
return 1 ;
2007-01-05 18:59:23 +08:00
}
if ( ! getCameraManipulator ( ) )
{
setCameraManipulator ( new osgGA : : TrackballManipulator ( ) ) ;
}
if ( ! isRealized ( ) )
{
realize ( ) ;
}
while ( ! done ( ) )
{
frame ( ) ;
}
2007-01-05 21:16:24 +08:00
return 0 ;
2007-01-05 18:59:23 +08:00
}
2007-01-06 05:19:01 +08:00
osg : : FrameStamp * Viewer : : getFrameStamp ( )
{
return _scene . valid ( ) ? _scene - > getFrameStamp ( ) : 0 ;
}
const osg : : FrameStamp * Viewer : : getFrameStamp ( ) const
{
return _scene . valid ( ) ? _scene - > getFrameStamp ( ) : 0 ;
}
2007-01-03 01:39:31 +08:00
void Viewer : : setThreadingModel ( ThreadingModel threadingModel )
{
2007-01-04 19:49:15 +08:00
if ( _threadingModel = = threadingModel ) return ;
2006-12-21 05:13:29 +08:00
2007-01-04 19:49:15 +08:00
if ( _threadingModel ! = SingleThreaded ) stopThreading ( ) ;
2006-12-21 05:13:29 +08:00
2007-01-04 19:49:15 +08:00
_threadingModel = threadingModel ;
2006-12-23 01:46:21 +08:00
2007-01-04 19:49:15 +08:00
if ( _threadingModel ! = SingleThreaded ) startThreading ( ) ;
2006-12-23 01:46:21 +08:00
}
2007-01-04 19:49:15 +08:00
void Viewer : : stopThreading ( )
2007-01-02 20:50:57 +08:00
{
2007-01-04 19:49:15 +08:00
if ( _numThreadsOnBarrier = = 0 ) return ;
2007-01-02 20:50:57 +08:00
2007-01-04 19:49:15 +08:00
osg : : notify ( osg : : INFO ) < < " Viewer::stopThreading() - stopping threading " < < std : : endl ;
2007-01-02 20:50:57 +08:00
2007-01-04 19:49:15 +08:00
Contexts contexts ;
getContexts ( contexts ) ;
2007-01-02 20:50:57 +08:00
2007-01-04 19:49:15 +08:00
// delete all the graphics threads.
for ( Contexts : : iterator itr = contexts . begin ( ) ;
itr ! = contexts . end ( ) ;
2007-01-02 20:50:57 +08:00
+ + itr )
{
2007-01-04 19:49:15 +08:00
( * itr ) - > setGraphicsThread ( 0 ) ;
2007-01-02 20:50:57 +08:00
}
2007-01-04 19:49:15 +08:00
_startRenderingBarrier = 0 ;
_endRenderingDispatchBarrier = 0 ;
_numThreadsOnBarrier = 0 ;
}
2006-12-23 01:46:21 +08:00
// Compile operation, that compile OpenGL objects.
2006-12-25 00:40:19 +08:00
struct CompileOperation : public osg : : GraphicsOperation
2006-12-23 01:46:21 +08:00
{
CompileOperation ( osg : : Node * scene ) :
2006-12-25 00:40:19 +08:00
osg : : GraphicsOperation ( " Compile " , false ) ,
2006-12-23 01:46:21 +08:00
_scene ( scene )
{
}
virtual void operator ( ) ( osg : : GraphicsContext * context )
{
// OpenThreads::ScopedLock<OpenThreads::Mutex> lock(mutex);
// osg::notify(osg::NOTICE)<<"Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
// context->makeCurrentImplementation();
osgUtil : : GLObjectsVisitor compileVisitor ;
compileVisitor . setState ( context - > getState ( ) ) ;
// do the compile traversal
_scene - > accept ( compileVisitor ) ;
// osg::notify(osg::NOTICE)<<"Done Compile "<<context<<" "<<OpenThreads::Thread::CurrentThread()<<std::endl;
}
osg : : ref_ptr < osg : : Node > _scene ;
} ;
// Draw operation, that does a draw on the scene graph.
2006-12-25 00:40:19 +08:00
struct RunOperations : public osg : : GraphicsOperation
2006-12-23 01:46:21 +08:00
{
RunOperations ( osg : : GraphicsContext * gc ) :
2006-12-25 00:40:19 +08:00
osg : : GraphicsOperation ( " RunOperation " , true ) ,
2006-12-23 01:46:21 +08:00
_originalContext ( gc )
{
}
virtual void operator ( ) ( osg : : GraphicsContext * gc )
{
gc - > runOperations ( ) ;
}
osg : : GraphicsContext * _originalContext ;
} ;
2007-01-04 19:49:15 +08:00
unsigned int Viewer : : computeNumberOfThreadsIncludingMainRequired ( )
{
Contexts contexts ;
getContexts ( contexts ) ;
2006-12-23 01:46:21 +08:00
2007-01-04 19:49:15 +08:00
if ( contexts . empty ( ) ) return 0 ;
if ( contexts . size ( ) = = 1 | | _threadingModel = = SingleThreaded )
{
return 1 ;
}
bool firstContextAsMainThread = _threadingModel = = ThreadPerContext ;
return firstContextAsMainThread ? contexts . size ( ) : contexts . size ( ) + 1 ;
}
void Viewer : : startThreading ( )
2006-12-23 01:46:21 +08:00
{
2007-01-04 19:49:15 +08:00
unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired ( ) ;
2006-12-23 01:46:21 +08:00
2007-01-04 19:49:15 +08:00
// return if we don't need multiple threads.
if ( numThreadsIncludingMainThread < = 1 ) return ;
// return if threading is already up and running
if ( numThreadsIncludingMainThread = = _numThreadsOnBarrier ) return ;
if ( _numThreadsOnBarrier ! = 0 )
{
// we already have threads running but not the right number, so stop them and then create new threads.
stopThreading ( ) ;
}
2007-01-02 02:20:10 +08:00
2007-01-05 05:18:03 +08:00
osg : : notify ( osg : : INFO ) < < " Viewer::startThreading() - starting threading " < < std : : endl ;
2007-01-05 00:49:58 +08:00
// using multi-threading so make sure that new objects are allocated with thread safe ref/unref
osg : : Referenced : : setThreadSafeReferenceCounting ( true ) ;
if ( getSceneData ( ) )
{
2007-01-05 05:18:03 +08:00
osg : : notify ( osg : : INFO ) < < " Making scene thread safe " < < std : : endl ;
2007-01-05 00:49:58 +08:00
// make sure that existing scene graph objects are allocated with thread safe ref/unref
getSceneData ( ) - > setThreadSafeRefUnref ( true ) ;
// update the scene graph so that it has enough GL object buffer memory for the graphics contexts that will be using it.
getSceneData ( ) - > resizeGLObjectBuffers ( osg : : DisplaySettings : : instance ( ) - > getMaxNumberOfGraphicsContexts ( ) ) ;
}
2006-12-23 01:46:21 +08:00
Contexts contexts ;
getContexts ( contexts ) ;
2007-01-04 00:06:12 +08:00
int numProcessors = OpenThreads : : GetNumberOfProcessors ( ) ;
bool affinity = true ;
2006-12-27 01:38:47 +08:00
2007-01-04 19:49:15 +08:00
bool firstContextAsMainThread = numThreadsIncludingMainThread = = contexts . size ( ) ;
// osg::notify(osg::NOTICE)<<"numThreadsIncludingMainThread=="<<numThreadsIncludingMainThread<<std::endl;
_numThreadsOnBarrier = numThreadsIncludingMainThread ;
_startRenderingBarrier = new osg : : BarrierOperation ( _numThreadsOnBarrier , osg : : BarrierOperation : : NO_OPERATION ) ;
_endRenderingDispatchBarrier = new osg : : BarrierOperation ( _numThreadsOnBarrier , osg : : BarrierOperation : : NO_OPERATION ) ;
osg : : ref_ptr < osg : : SwapBuffersOperation > swapOp = new osg : : SwapBuffersOperation ( ) ;
Contexts : : iterator citr = contexts . begin ( ) ;
unsigned int processNum = 0 ;
if ( firstContextAsMainThread )
2006-12-23 01:46:21 +08:00
{
2007-01-04 19:49:15 +08:00
if ( affinity ) OpenThreads : : SetProcessorAffinityOfCurrentThread ( processNum % numProcessors ) ;
+ + processNum ;
+ + citr ;
}
for ( ;
citr ! = contexts . end ( ) ;
+ + citr ,
+ + processNum )
{
osg : : GraphicsContext * gc = ( * citr ) ;
// create the a graphics thread for this context
gc - > createGraphicsThread ( ) ;
if ( affinity ) gc - > getGraphicsThread ( ) - > setProcessorAffinity ( processNum % numProcessors ) ;
gc - > getGraphicsThread ( ) - > add ( new CompileOperation ( getSceneData ( ) ) ) ;
// add the startRenderingBarrier
gc - > getGraphicsThread ( ) - > add ( _startRenderingBarrier . get ( ) ) ;
// add the rendering operation itself.
gc - > getGraphicsThread ( ) - > add ( new RunOperations ( gc ) ) ;
2006-12-23 01:46:21 +08:00
2007-01-04 19:49:15 +08:00
// add the endRenderingDispatchBarrier
gc - > getGraphicsThread ( ) - > add ( _endRenderingDispatchBarrier . get ( ) ) ;
2007-01-03 01:39:31 +08:00
2007-01-04 19:49:15 +08:00
// add the swap buffers
gc - > getGraphicsThread ( ) - > add ( swapOp . get ( ) ) ;
}
for ( citr = contexts . begin ( ) ;
citr ! = contexts . end ( ) ;
+ + citr )
{
osg : : GraphicsContext * gc = ( * citr ) ;
if ( gc - > getGraphicsThread ( ) & & ! gc - > getGraphicsThread ( ) - > isRunning ( ) )
2007-01-04 00:06:12 +08:00
{
2007-01-04 19:49:15 +08:00
//osg::notify(osg::NOTICE)<<" gc->getGraphicsThread()->startThread() "<<gc->getGraphicsThread()<<std::endl;
gc - > getGraphicsThread ( ) - > startThread ( ) ;
// OpenThreads::Thread::YieldCurrentThread();
2007-01-04 00:06:12 +08:00
}
2007-01-04 19:49:15 +08:00
}
}
void Viewer : : checkWindowStatus ( )
{
unsigned int numThreadsIncludingMainThread = computeNumberOfThreadsIncludingMainRequired ( ) ;
if ( numThreadsIncludingMainThread ! = _numThreadsOnBarrier )
{
stopThreading ( ) ;
2007-01-04 00:06:12 +08:00
2007-01-04 19:49:15 +08:00
if ( numThreadsIncludingMainThread > 1 ) startThreading ( ) ;
}
if ( numThreadsIncludingMainThread = = 0 ) _done = true ;
}
2006-12-23 01:46:21 +08:00
2007-01-04 19:49:15 +08:00
void Viewer : : init ( )
{
osg : : notify ( osg : : INFO ) < < " Viewer::init() " < < std : : endl ;
osg : : ref_ptr < osgGA : : GUIEventAdapter > initEvent = _eventQueue - > createEvent ( ) ;
initEvent - > setEventType ( osgGA : : GUIEventAdapter : : FRAME ) ;
if ( _cameraManipulator . valid ( ) )
{
_cameraManipulator - > init ( * initEvent , * this ) ;
}
}
void Viewer : : getContexts ( Contexts & contexts , bool onlyValid )
{
typedef std : : set < osg : : GraphicsContext * > ContextSet ;
ContextSet contextSet ;
if ( _camera . valid ( ) & &
_camera - > getGraphicsContext ( ) & &
( _camera - > getGraphicsContext ( ) - > valid ( ) | | ! onlyValid ) )
{
contextSet . insert ( _camera - > getGraphicsContext ( ) ) ;
}
for ( unsigned int i = 0 ; i < getNumSlaves ( ) ; + + i )
{
Slave & slave = getSlave ( i ) ;
if ( slave . _camera . valid ( ) & &
slave . _camera - > getGraphicsContext ( ) & &
( slave . _camera - > getGraphicsContext ( ) - > valid ( ) | | ! onlyValid ) )
{
contextSet . insert ( slave . _camera - > getGraphicsContext ( ) ) ;
2006-12-23 01:46:21 +08:00
}
}
2007-01-04 19:49:15 +08:00
contexts . clear ( ) ;
contexts . reserve ( contextSet . size ( ) ) ;
for ( ContextSet : : iterator itr = contextSet . begin ( ) ;
itr ! = contextSet . end ( ) ;
+ + itr )
{
contexts . push_back ( const_cast < osg : : GraphicsContext * > ( * itr ) ) ;
}
}
void Viewer : : getWindows ( Windows & windows , bool onlyValid )
{
windows . clear ( ) ;
Contexts contexts ;
getContexts ( contexts , onlyValid ) ;
for ( Contexts : : iterator itr = contexts . begin ( ) ;
itr ! = contexts . end ( ) ;
+ + itr )
{
osgViewer : : GraphicsWindow * gw = dynamic_cast < osgViewer : : GraphicsWindow * > ( * itr ) ;
if ( gw ) windows . push_back ( gw ) ;
}
}
2007-01-05 05:49:02 +08:00
// Draw operation, that does a draw on the scene graph.
struct RenderingOperation : public osg : : GraphicsOperation
{
RenderingOperation ( osgUtil : : SceneView * sceneView , osgDB : : DatabasePager * databasePager ) :
osg : : GraphicsOperation ( " Render " , true ) ,
_sceneView ( sceneView ) ,
_databasePager ( databasePager )
{
_sceneView - > getCullVisitor ( ) - > setDatabaseRequestHandler ( _databasePager . get ( ) ) ;
}
virtual void operator ( ) ( osg : : GraphicsContext * )
{
if ( ! _sceneView ) return ;
// osg::notify(osg::NOTICE)<<"RenderingOperation"<<std::endl;
_sceneView - > cull ( ) ;
_sceneView - > draw ( ) ;
if ( _databasePager . valid ( ) )
{
double availableTime = 0.004 ; // 4 ms
_databasePager - > compileGLObjects ( * ( _sceneView - > getState ( ) ) , availableTime ) ;
_sceneView - > flushDeletedGLObjects ( availableTime ) ;
}
}
osg : : observer_ptr < osgUtil : : SceneView > _sceneView ;
osg : : observer_ptr < osgDB : : DatabasePager > _databasePager ;
} ;
void Viewer : : setUpRenderingSupport ( )
{
if ( ! _scene ) return ;
osg : : FrameStamp * frameStamp = _scene - > getFrameStamp ( ) ;
// what should we do with the old sceneViews?
_cameraSceneViewMap . clear ( ) ;
Contexts contexts ;
getContexts ( contexts ) ;
// clear out all the previously assigned operations
for ( Contexts : : iterator citr = contexts . begin ( ) ;
citr ! = contexts . end ( ) ;
+ + citr )
{
( * citr ) - > removeAllOperations ( ) ;
}
if ( _camera . valid ( ) & & _camera - > getGraphicsContext ( ) )
{
osgUtil : : SceneView * sceneView = new osgUtil : : SceneView ;
_cameraSceneViewMap [ _camera ] = sceneView ;
sceneView - > setDefaults ( ) ;
sceneView - > setCamera ( _camera . get ( ) ) ;
sceneView - > setState ( _camera - > getGraphicsContext ( ) - > getState ( ) ) ;
sceneView - > setSceneData ( getSceneData ( ) ) ;
sceneView - > setFrameStamp ( frameStamp ) ;
_camera - > getGraphicsContext ( ) - > add ( new RenderingOperation ( sceneView , _scene - > getDatabasePager ( ) ) ) ;
}
for ( unsigned i = 0 ; i < getNumSlaves ( ) ; + + i )
{
Slave & slave = getSlave ( i ) ;
if ( slave . _camera . valid ( ) & & slave . _camera - > getGraphicsContext ( ) )
{
osgUtil : : SceneView * sceneView = new osgUtil : : SceneView ;
_cameraSceneViewMap [ slave . _camera ] = sceneView ;
sceneView - > setDefaults ( ) ;
sceneView - > setCamera ( slave . _camera . get ( ) ) ;
sceneView - > setState ( slave . _camera - > getGraphicsContext ( ) - > getState ( ) ) ;
sceneView - > setSceneData ( getSceneData ( ) ) ;
sceneView - > setFrameStamp ( frameStamp ) ;
slave . _camera - > getGraphicsContext ( ) - > add ( new RenderingOperation ( sceneView , _scene - > getDatabasePager ( ) ) ) ;
}
}
}
2007-01-04 19:49:15 +08:00
void Viewer : : realize ( )
{
//osg::notify(osg::INFO)<<"Viewer::realize()"<<std::endl;
2007-01-05 05:35:11 +08:00
2007-01-04 19:49:15 +08:00
setCameraWithFocus ( 0 ) ;
Contexts contexts ;
getContexts ( contexts ) ;
2007-01-05 05:35:11 +08:00
if ( contexts . empty ( ) )
{
2007-01-10 01:35:46 +08:00
osg : : notify ( osg : : INFO ) < < " Viewer::realize() - No valid contexts found, setting up view across all screens. " < < std : : endl ;
2007-01-05 05:35:11 +08:00
// no windows are already set up so set up a default view
setUpViewAcrossAllScreens ( ) ;
getContexts ( contexts ) ;
}
2007-01-04 19:49:15 +08:00
2007-01-05 05:35:11 +08:00
if ( contexts . empty ( ) )
{
osg : : notify ( osg : : NOTICE ) < < " Viewer::realize() - failed to set up any windows " < < std : : endl ;
_done = true ;
return ;
}
2007-01-05 05:49:02 +08:00
setUpRenderingSupport ( ) ;
2007-01-04 19:49:15 +08:00
for ( Contexts : : iterator citr = contexts . begin ( ) ;
2006-12-23 01:46:21 +08:00
citr ! = contexts . end ( ) ;
+ + citr )
{
( * citr ) - > realize ( ) ;
}
2006-12-21 19:20:42 +08:00
bool grabFocus = true ;
if ( grabFocus )
{
2007-01-04 19:49:15 +08:00
for ( Contexts : : iterator citr = contexts . begin ( ) ;
2006-12-23 01:46:21 +08:00
citr ! = contexts . end ( ) ;
+ + citr )
2006-12-21 19:20:42 +08:00
{
2006-12-23 01:46:21 +08:00
osgViewer : : GraphicsWindow * gw = dynamic_cast < osgViewer : : GraphicsWindow * > ( * citr ) ;
if ( gw )
{
gw - > grabFocusIfPointerInWindow ( ) ;
}
2006-12-21 19:20:42 +08:00
}
2007-01-05 00:49:58 +08:00
}
2007-01-04 19:49:15 +08:00
startThreading ( ) ;
2006-12-27 01:38:47 +08:00
// initialize the global timer to be relative to the current time.
osg : : Timer : : instance ( ) - > setStartTick ( ) ;
2006-12-20 00:00:51 +08:00
}
2006-11-29 19:00:02 +08:00
void Viewer : : frame ( )
{
2006-12-22 00:56:20 +08:00
if ( _done ) return ;
2006-12-27 23:04:04 +08:00
// osg::notify(osg::NOTICE)<<std::endl<<"Viewer::frame()"<<std::endl<<std::endl;
2006-12-21 05:13:29 +08:00
if ( _firstFrame )
{
init ( ) ;
2007-01-05 18:59:23 +08:00
if ( ! isRealized ( ) )
{
realize ( ) ;
}
2006-12-21 05:13:29 +08:00
_firstFrame = false ;
}
2007-01-06 00:48:04 +08:00
advance ( ) ;
2006-12-21 05:13:29 +08:00
2007-01-06 00:48:04 +08:00
eventTraversal ( ) ;
updateTraversal ( ) ;
renderingTraversals ( ) ;
2006-11-29 19:00:02 +08:00
}
2007-01-06 00:48:04 +08:00
void Viewer : : advance ( )
2006-11-29 19:00:02 +08:00
{
2006-12-22 00:56:20 +08:00
if ( _done ) return ;
2006-12-21 05:13:29 +08:00
// osg::notify(osg::NOTICE)<<"Viewer::frameAdvance()."<<std::endl;
_scene - > frameAdvance ( ) ;
2006-11-29 19:00:02 +08:00
}
2007-01-06 00:48:04 +08:00
void Viewer : : eventTraversal ( )
2006-11-29 19:00:02 +08:00
{
2006-12-22 00:56:20 +08:00
if ( _done ) return ;
2006-12-21 05:13:29 +08:00
// osg::notify(osg::NOTICE)<<"Viewer::frameEventTraversal()."<<std::endl;
// need to copy events from the GraphicsWindow's into local EventQueue;
osgGA : : EventQueue : : Events events ;
2006-12-23 01:46:21 +08:00
Contexts contexts ;
getContexts ( contexts ) ;
2007-01-02 02:20:10 +08:00
osgGA : : GUIEventAdapter * eventState = getEventQueue ( ) - > getCurrentEventState ( ) ;
osg : : Matrix masterCameraVPW = getCamera ( ) - > getViewMatrix ( ) * getCamera ( ) - > getProjectionMatrix ( ) ;
if ( getCamera ( ) - > getViewport ( ) )
{
osg : : Viewport * viewport = getCamera ( ) - > getViewport ( ) ;
masterCameraVPW * = viewport - > computeWindowMatrix ( ) ;
eventState - > setInputRange ( viewport - > x ( ) , viewport - > y ( ) , viewport - > x ( ) + viewport - > width ( ) , viewport - > y ( ) + viewport - > height ( ) ) ;
}
else
{
eventState - > setInputRange ( - 1.0 , - 1.0 , 1.0 , 1.0 ) ;
}
2006-12-23 01:46:21 +08:00
for ( Contexts : : iterator citr = contexts . begin ( ) ;
citr ! = contexts . end ( ) ;
+ + citr )
2006-12-21 05:13:29 +08:00
{
2006-12-23 01:46:21 +08:00
osgViewer : : GraphicsWindow * gw = dynamic_cast < osgViewer : : GraphicsWindow * > ( * citr ) ;
2006-12-21 05:13:29 +08:00
if ( gw )
{
gw - > checkEvents ( ) ;
2007-01-02 02:20:10 +08:00
osgGA : : EventQueue : : Events gw_events ;
gw - > getEventQueue ( ) - > takeEvents ( gw_events ) ;
2007-01-09 03:29:59 +08:00
osgGA : : EventQueue : : Events : : iterator itr ;
for ( itr = gw_events . begin ( ) ;
2007-01-02 02:20:10 +08:00
itr ! = gw_events . end ( ) ;
+ + itr )
{
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
bool pointerEvent = false ;
float x = event - > getX ( ) ;
float y = event - > getY ( ) ;
bool invert_y = event - > getMouseYOrientation ( ) = = osgGA : : GUIEventAdapter : : Y_INCREASING_DOWNWARDS ;
if ( invert_y ) y = gw - > getTraits ( ) - > height - y ;
switch ( event - > getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : PUSH ) :
case ( osgGA : : GUIEventAdapter : : RELEASE ) :
case ( osgGA : : GUIEventAdapter : : DRAG ) :
case ( osgGA : : GUIEventAdapter : : MOVE ) :
{
pointerEvent = true ;
if ( event - > getEventType ( ) ! = osgGA : : GUIEventAdapter : : DRAG | | ! getCameraWithFocus ( ) )
{
osg : : GraphicsContext : : Cameras & cameras = gw - > getCameras ( ) ;
for ( osg : : GraphicsContext : : Cameras : : iterator citr = cameras . begin ( ) ;
citr ! = cameras . end ( ) ;
+ + citr )
{
osg : : Camera * camera = * citr ;
osg : : Viewport * viewport = camera ? camera - > getViewport ( ) : 0 ;
if ( viewport & &
x > = viewport - > x ( ) & & y > = viewport - > y ( ) & &
x < = ( viewport - > x ( ) + viewport - > width ( ) ) & & y < = ( viewport - > y ( ) + viewport - > height ( ) ) )
{
setCameraWithFocus ( camera ) ;
}
}
}
break ;
}
default :
break ;
}
if ( pointerEvent )
{
if ( getCameraWithFocus ( ) )
{
osg : : Viewport * viewport = getCameraWithFocus ( ) - > getViewport ( ) ;
osg : : Matrix localCameraVPW = getCameraWithFocus ( ) - > getViewMatrix ( ) * getCameraWithFocus ( ) - > getProjectionMatrix ( ) ;
if ( viewport ) localCameraVPW * = viewport - > computeWindowMatrix ( ) ;
osg : : Matrix matrix ( osg : : Matrix : : inverse ( localCameraVPW ) * masterCameraVPW ) ;
osg : : Vec3d new_coord = osg : : Vec3d ( x , y , 0.0 ) * matrix ;
x = new_coord . x ( ) ;
y = new_coord . y ( ) ;
event - > setInputRange ( eventState - > getXmin ( ) , eventState - > getYmin ( ) , eventState - > getXmax ( ) , eventState - > getYmax ( ) ) ;
event - > setX ( x ) ;
event - > setY ( y ) ;
event - > setMouseYOrientation ( osgGA : : GUIEventAdapter : : Y_INCREASING_UPWARDS ) ;
}
// pass along the new pointer events details to the eventState of the viewer
eventState - > setX ( x ) ;
eventState - > setY ( y ) ;
eventState - > setButtonMask ( event - > getButtonMask ( ) ) ;
eventState - > setMouseYOrientation ( osgGA : : GUIEventAdapter : : Y_INCREASING_UPWARDS ) ;
}
else
{
event - > setInputRange ( eventState - > getXmin ( ) , eventState - > getYmin ( ) , eventState - > getXmax ( ) , eventState - > getYmax ( ) ) ;
event - > setX ( eventState - > getX ( ) ) ;
event - > setY ( eventState - > getY ( ) ) ;
event - > setButtonMask ( eventState - > getButtonMask ( ) ) ;
event - > setMouseYOrientation ( eventState - > getMouseYOrientation ( ) ) ;
}
//osg::notify(osg::NOTICE)<<" mouse x = "<<event->getX()<<" y="<<event->getY()<<std::endl;
// osg::notify(osg::NOTICE)<<" mouse Xmin = "<<event->getXmin()<<" Ymin="<<event->getYmin()<<" xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
}
2007-01-09 03:29:59 +08:00
for ( itr = gw_events . begin ( ) ;
itr ! = gw_events . end ( ) ;
+ + itr )
{
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
switch ( event - > getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : CLOSE_WINDOW ) :
{
2007-01-09 05:29:49 +08:00
// stopThreading();
2007-01-09 03:29:59 +08:00
gw - > close ( ) ;
2007-01-09 05:29:49 +08:00
// startThreading();
2007-01-09 03:29:59 +08:00
break ;
}
default :
break ;
}
}
2007-01-02 02:20:10 +08:00
events . insert ( events . end ( ) , gw_events . begin ( ) , gw_events . end ( ) ) ;
2006-12-21 05:13:29 +08:00
}
}
2007-01-09 18:06:20 +08:00
#if 0
2007-01-02 02:20:10 +08:00
// pointer coordinate transform
2006-12-21 05:13:29 +08:00
for ( osgGA : : EventQueue : : Events : : iterator itr = events . begin ( ) ;
itr ! = events . end ( ) ;
+ + itr )
{
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
2006-12-28 04:23:34 +08:00
if ( getEventQueue ( ) - > getUseFixedMouseInputRange ( ) )
{
event - > setInputRange ( eventState - > getXmin ( ) , eventState - > getYmin ( ) , eventState - > getXmax ( ) , eventState - > getYmax ( ) ) ;
}
2006-12-27 01:38:47 +08:00
switch ( event - > getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : PUSH ) :
case ( osgGA : : GUIEventAdapter : : RELEASE ) :
case ( osgGA : : GUIEventAdapter : : DRAG ) :
case ( osgGA : : GUIEventAdapter : : MOVE ) :
eventState - > setX ( event - > getX ( ) ) ;
eventState - > setY ( event - > getY ( ) ) ;
eventState - > setButtonMask ( event - > getButtonMask ( ) ) ;
2006-12-28 04:23:34 +08:00
// osg::notify(osg::NOTICE)<<" mouse x = "<<event->getX()<<" y="<<event->getY()<<std::endl;
// osg::notify(osg::NOTICE)<<" mouse Xmin = "<<event->getXmin()<<" Ymin="<<event->getYmin()<<" xMax="<<event->getXmax()<<" Ymax="<<event->getYmax()<<std::endl;
2006-12-27 01:38:47 +08:00
break ;
default :
break ;
}
2006-12-21 05:13:29 +08:00
}
2007-01-02 02:20:10 +08:00
# else
# endif
2006-12-21 05:13:29 +08:00
2006-12-28 04:23:34 +08:00
// osg::notify(osg::NOTICE)<<"mouseEventState Xmin = "<<eventState->getXmin()<<" Ymin="<<eventState->getYmin()<<" xMax="<<eventState->getXmax()<<" Ymax="<<eventState->getYmax()<<std::endl;
2006-12-27 01:38:47 +08:00
_eventQueue - > frame ( _scene - > getFrameStamp ( ) - > getReferenceTime ( ) ) ;
_eventQueue - > takeEvents ( events ) ;
2006-12-21 05:13:29 +08:00
#if 0
// osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
for ( osgGA : : EventQueue : : Events : : iterator itr = events . begin ( ) ;
itr ! = events . end ( ) ;
+ + itr )
{
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
switch ( event - > getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : PUSH ) :
osg : : notify ( osg : : NOTICE ) < < " PUSH " < < event - > getButton ( ) < < " x= " < < event - > getX ( ) < < " y= " < < event - > getY ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : RELEASE ) :
osg : : notify ( osg : : NOTICE ) < < " RELEASE " < < event - > getButton ( ) < < " x= " < < event - > getX ( ) < < " y= " < < event - > getY ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : DRAG ) :
osg : : notify ( osg : : NOTICE ) < < " DRAG " < < event - > getButtonMask ( ) < < " x= " < < event - > getX ( ) < < " y= " < < event - > getY ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : MOVE ) :
osg : : notify ( osg : : NOTICE ) < < " MOVE " < < event - > getButtonMask ( ) < < " x= " < < event - > getX ( ) < < " y= " < < event - > getY ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : SCROLL ) :
osg : : notify ( osg : : NOTICE ) < < " SCROLL " < < event - > getScrollingMotion ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : KEYDOWN ) :
osg : : notify ( osg : : NOTICE ) < < " KEYDOWN ' " < < ( char ) event - > getKey ( ) < < " ' " < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : KEYUP ) :
osg : : notify ( osg : : NOTICE ) < < " KEYUP ' " < < ( char ) event - > getKey ( ) < < " ' " < < std : : endl ;
break ;
2007-01-09 18:06:20 +08:00
*/ case ( osgGA : : GUIEventAdapter : : RESIZE ) :
osg : : notify ( osg : : NOTICE ) < < " RESIZE " < < event - > getWindowX ( ) < < " / " < < event - > getWindowY ( ) < < " x " < < event - > getWindowWidth ( ) < < " / " < < event - > getWindowHeight ( ) < < std : : endl ;
break ;
case ( osgGA : : GUIEventAdapter : : QUIT_APPLICATION ) :
osg : : notify ( osg : : NOTICE ) < < " QUIT_APPLICATION " < < std : : endl ;
2007-01-02 02:20:10 +08:00
case ( osgGA : : GUIEventAdapter : : RESIZE ) :
osg : : notify ( osg : : NOTICE ) < < " RESIZE " < < std : : endl ;
break ;
2006-12-21 05:13:29 +08:00
case ( osgGA : : GUIEventAdapter : : FRAME ) :
// osg::notify(osg::NOTICE)<<" FRAME "<<std::endl;
break ;
default :
// osg::notify(osg::NOTICE)<<" Event not handled"<<std::endl;
break ;
}
}
# endif
2006-12-22 00:56:20 +08:00
// osg::notify(osg::NOTICE)<<"Events "<<events.size()<<std::endl;
2007-01-05 05:28:16 +08:00
2007-01-09 18:06:20 +08:00
if ( ( _keySetsDone ! = 0 ) | | ( _quitEventSetsDone ) )
2006-12-22 00:56:20 +08:00
{
2007-01-05 05:28:16 +08:00
for ( osgGA : : EventQueue : : Events : : iterator itr = events . begin ( ) ;
itr ! = events . end ( ) ;
+ + itr )
2006-12-22 00:56:20 +08:00
{
2007-01-05 05:28:16 +08:00
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
switch ( event - > getEventType ( ) )
{
case ( osgGA : : GUIEventAdapter : : KEYUP ) :
if ( event - > getKey ( ) = = _keySetsDone ) _done = true ;
2007-01-09 03:29:59 +08:00
else if ( event - > getKey ( ) = = ' s ' ) { setThreadingModel ( SingleThreaded ) ; }
else if ( event - > getKey ( ) = = ' c ' ) { setThreadingModel ( ThreadPerCamera ) ; }
else if ( event - > getKey ( ) = = ' w ' ) { setThreadingModel ( ThreadPerContext ) ; }
2007-01-05 05:28:16 +08:00
break ;
2007-01-09 18:06:20 +08:00
case ( osgGA : : GUIEventAdapter : : QUIT_APPLICATION ) :
_done = true ;
break ;
2007-01-05 05:28:16 +08:00
default :
break ;
}
2006-12-22 00:56:20 +08:00
}
}
2007-01-05 05:28:16 +08:00
2006-12-22 00:56:20 +08:00
if ( _done ) return ;
2006-12-21 05:13:29 +08:00
for ( osgGA : : EventQueue : : Events : : iterator itr = events . begin ( ) ;
itr ! = events . end ( ) ;
+ + itr )
{
osgGA : : GUIEventAdapter * event = itr - > get ( ) ;
bool handled = false ;
if ( _cameraManipulator . valid ( ) )
{
2007-01-02 02:20:10 +08:00
_cameraManipulator - > handle ( * event , * this ) ;
2006-12-21 05:13:29 +08:00
}
for ( EventHandlers : : iterator hitr = _eventHandlers . begin ( ) ;
hitr ! = _eventHandlers . end ( ) & & ! handled ;
+ + hitr )
{
2007-01-02 02:20:10 +08:00
handled = ( * hitr ) - > handle ( * event , * this , 0 , 0 ) ;
2006-12-21 05:13:29 +08:00
}
}
2007-01-02 02:20:10 +08:00
2006-11-29 19:00:02 +08:00
}
2007-01-06 00:48:04 +08:00
void Viewer : : updateTraversal ( )
2006-11-29 19:00:02 +08:00
{
2006-12-22 00:56:20 +08:00
if ( _done ) return ;
if ( _scene . valid ( ) ) _scene - > frameUpdateTraversal ( ) ;
2006-12-21 05:13:29 +08:00
if ( _cameraManipulator . valid ( ) )
{
_camera - > setViewMatrix ( _cameraManipulator - > getInverseMatrix ( ) ) ;
}
updateSlaves ( ) ;
2006-11-29 19:00:02 +08:00
}
2007-01-06 00:48:04 +08:00
void Viewer : : renderingTraversals ( )
2006-11-29 19:00:02 +08:00
{
2007-01-04 19:49:15 +08:00
// check to see if windows are still valid
checkWindowStatus ( ) ;
2006-12-22 01:23:07 +08:00
if ( _done ) return ;
osgDB : : DatabasePager * dp = _scene - > getDatabasePager ( ) ;
if ( dp )
{
dp - > signalBeginFrame ( _scene - > getFrameStamp ( ) ) ;
}
2007-01-03 01:39:31 +08:00
// osg::notify(osg::NOTICE)<<std::endl<<"Joing _startRenderingBarrier block"<<std::endl;
2007-01-04 19:49:15 +08:00
2006-11-29 19:00:02 +08:00
2007-01-03 01:39:31 +08:00
Contexts contexts ;
getContexts ( contexts ) ;
2006-12-23 01:46:21 +08:00
2007-01-03 01:39:31 +08:00
// dispatch the the rendering threads
if ( _startRenderingBarrier . valid ( ) ) _startRenderingBarrier - > block ( ) ;
2006-12-22 00:56:20 +08:00
2007-01-03 01:39:31 +08:00
Contexts : : iterator itr ;
for ( itr = contexts . begin ( ) ;
itr ! = contexts . end ( ) ;
+ + itr )
2006-12-22 00:56:20 +08:00
{
2007-01-03 01:39:31 +08:00
if ( _done ) return ;
if ( ! ( ( * itr ) - > getGraphicsThread ( ) ) )
{
2006-12-23 01:46:21 +08:00
( * itr ) - > makeCurrent ( ) ;
( * itr ) - > runOperations ( ) ;
2007-01-09 00:20:10 +08:00
( * itr ) - > releaseContext ( ) ;
2006-12-22 00:56:20 +08:00
}
2007-01-03 01:39:31 +08:00
}
2006-12-22 01:23:07 +08:00
2007-01-03 01:39:31 +08:00
// osg::notify(osg::NOTICE)<<"Joing _endRenderingDispatchBarrier block"<<std::endl;
2006-12-22 01:23:07 +08:00
2007-01-03 01:39:31 +08:00
// wait till the rendering dispatch is done.
if ( _endRenderingDispatchBarrier . valid ( ) ) _endRenderingDispatchBarrier - > block ( ) ;
for ( itr = contexts . begin ( ) ;
itr ! = contexts . end ( ) ;
+ + itr )
{
if ( _done ) return ;
2007-01-04 19:49:15 +08:00
2007-01-03 01:39:31 +08:00
if ( ! ( ( * itr ) - > getGraphicsThread ( ) ) )
{
2006-12-23 01:46:21 +08:00
( * itr ) - > makeCurrent ( ) ;
( * itr ) - > swapBuffers ( ) ;
2007-01-09 00:20:10 +08:00
( * itr ) - > releaseContext ( ) ;
2006-12-23 01:46:21 +08:00
}
2006-12-22 00:56:20 +08:00
}
2006-12-22 01:23:07 +08:00
if ( dp )
{
dp - > signalEndFrame ( ) ;
}
2006-11-29 19:00:02 +08:00
}
void Viewer : : releaseAllGLObjects ( )
{
osg : : notify ( osg : : NOTICE ) < < " Viewer::releaseAllGLObjects() not implemented yet. " < < std : : endl ;
}
void Viewer : : cleanup ( )
{
osg : : notify ( osg : : NOTICE ) < < " Viewer::cleanup() not implemented yet. " < < std : : endl ;
}