2013-07-30 14:36:49 +08:00
/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2009-04-28 19:57:51 +08:00
*
2013-07-30 14:36:49 +08:00
* This software is open source and may be redistributed and / or modified under
2009-04-28 19:57:51 +08:00
* the terms of the GNU General Public License ( GPL ) version 2.0 .
* The full license is in LICENSE . txt file included with this distribution , .
2013-07-30 14:36:49 +08:00
*
2009-04-28 19:57:51 +08:00
* This software is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
2013-07-30 14:36:49 +08:00
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
2009-04-28 19:57:51 +08:00
* include LICENSE . txt for more details .
*/
# include <osg/Geometry>
# include <osg/Texture2D>
2009-08-20 22:20:55 +08:00
# include <osg/AutoTransform>
2009-04-28 19:57:51 +08:00
# include <osg/Notify>
2009-08-20 22:20:55 +08:00
# include <osg/io_utils>
2009-04-28 19:57:51 +08:00
# include <osgDB/ReadFile>
# include <osgDB/WriteFile>
# include <osgDB/FileNameUtils>
# include <osgUtil/Optimizer>
# include <osgViewer/Viewer>
# include <osgViewer/ViewerEventHandlers>
# include <OpenThreads/Thread>
2012-11-28 18:43:58 +08:00
# include <osgGA/GUIEventHandler>
2009-04-28 19:57:51 +08:00
# include <osgGA/TrackballManipulator>
# include <osgGA/FlightManipulator>
# include <osgGA/DriveManipulator>
# include <osgGA/KeySwitchMatrixManipulator>
# include <osgGA/AnimationPathManipulator>
# include <osgGA/TerrainManipulator>
# include <osgGA/AnimationPathManipulator>
# include <osgGA/StateSetManipulator>
2014-01-23 23:37:48 +08:00
# include <osgGA/MultiTouchTrackballManipulator>
2009-04-28 19:57:51 +08:00
2013-08-19 02:10:39 +08:00
# include <osgPresentation/deprecated/SlideEventHandler>
2013-08-09 00:49:33 +08:00
# include <osgPresentation/Cursor>
2009-06-25 00:03:49 +08:00
2009-04-28 19:57:51 +08:00
# include "ReadShowFile.h"
# include "PointsEventHandler.h"
# include "Cluster.h"
# include "ExportHTML.h"
2010-04-30 23:51:38 +08:00
# include "SpellChecker.h"
2009-04-28 19:57:51 +08:00
# include <sstream>
# include <fstream>
# include <iostream>
2014-01-23 23:37:48 +08:00
2009-04-28 19:57:51 +08:00
# include <string.h>
# ifdef USE_SDL
# include "SDLIntegration.h"
# endif
2010-11-09 22:57:20 +08:00
# ifdef OSG_LIBRARY_STATIC
2009-06-21 01:03:38 +08:00
// include the plugins we need
USE_OSGPLUGIN ( ive )
USE_OSGPLUGIN ( osg )
2010-11-11 19:47:24 +08:00
USE_OSGPLUGIN ( osg2 )
2009-06-25 01:34:30 +08:00
USE_OSGPLUGIN ( p3d )
USE_OSGPLUGIN ( paths )
2010-11-09 22:57:20 +08:00
USE_OSGPLUGIN ( rgb )
USE_OSGPLUGIN ( OpenFlight )
USE_OSGPLUGIN ( obj )
2009-06-23 00:08:12 +08:00
2010-11-09 22:57:20 +08:00
# ifdef USE_FREETYPE
2009-06-23 00:08:12 +08:00
USE_OSGPLUGIN ( freetype )
2010-11-09 22:57:20 +08:00
# endif
# ifdef USE_PNG
2009-06-21 01:03:38 +08:00
USE_OSGPLUGIN ( png )
2010-11-09 22:57:20 +08:00
# endif
# ifdef USE_JPEG
2009-06-21 01:03:38 +08:00
USE_OSGPLUGIN ( jpeg )
2010-11-09 22:57:20 +08:00
# endif
2009-06-23 00:08:12 +08:00
2010-11-09 22:57:20 +08:00
# ifdef USE_FFMPEG
2009-06-21 01:03:38 +08:00
USE_OSGPLUGIN ( ffmpeg )
2010-11-09 22:57:20 +08:00
# endif
2009-06-21 01:03:38 +08:00
2010-11-09 22:57:20 +08:00
# ifdef USE_POPPLER_CAIRO
USE_OSGPLUGIN ( pdf )
# endif
2009-06-23 00:08:12 +08:00
2010-11-09 22:57:20 +08:00
# ifdef USE_CURL
2009-06-23 00:08:12 +08:00
USE_OSGPLUGIN ( curl )
2010-11-09 22:57:20 +08:00
# endif
2009-06-21 01:03:38 +08:00
2010-11-11 19:47:24 +08:00
USE_DOTOSGWRAPPER_LIBRARY ( osg )
USE_DOTOSGWRAPPER_LIBRARY ( osgFX )
USE_DOTOSGWRAPPER_LIBRARY ( osgParticle )
USE_DOTOSGWRAPPER_LIBRARY ( osgShadow )
USE_DOTOSGWRAPPER_LIBRARY ( osgSim )
USE_DOTOSGWRAPPER_LIBRARY ( osgTerrain )
USE_DOTOSGWRAPPER_LIBRARY ( osgText )
USE_DOTOSGWRAPPER_LIBRARY ( osgViewer )
USE_DOTOSGWRAPPER_LIBRARY ( osgVolume )
USE_DOTOSGWRAPPER_LIBRARY ( osgWidget )
USE_SERIALIZER_WRAPPER_LIBRARY ( osg )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgAnimation )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgFX )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgManipulator )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgParticle )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgShadow )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgSim )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgTerrain )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgText )
USE_SERIALIZER_WRAPPER_LIBRARY ( osgVolume )
2009-06-21 01:03:38 +08:00
// include the platform specific GraphicsWindow implementation.
USE_GRAPHICSWINDOW ( )
# endif
2009-08-05 00:19:28 +08:00
static const char * s_version = " 1.4 beta " ;
2009-04-28 19:57:51 +08:00
void setViewer ( osgViewer : : Viewer & viewer , float width , float height , float distance )
{
double vfov = osg : : RadiansToDegrees ( atan2 ( height / 2.0f , distance ) * 2.0 ) ;
2009-04-28 22:03:02 +08:00
// double hfov = osg::RadiansToDegrees(atan2(width/2.0f,distance)*2.0);
2009-04-28 19:57:51 +08:00
viewer . getCamera ( ) - > setProjectionMatrixAsPerspective ( vfov , width / height , 0.1 , 1000.0 ) ;
2012-12-17 23:58:57 +08:00
2013-08-22 19:18:45 +08:00
OSG_INFO < < " setProjectionMatrixAsPerspective( " < < vfov < < " , " < < width / height < < " , " < < 0.1 < < " , " < < 1000.0 < < " ); " < < std : : endl ;
2009-04-28 19:57:51 +08:00
}
2012-11-28 18:43:58 +08:00
class ForwardToDeviceEventHandler : public osgGA : : GUIEventHandler {
public :
2013-12-19 21:49:27 +08:00
ForwardToDeviceEventHandler ( osgGA : : Device * device , bool format_mouse_events ) : osgGA : : GUIEventHandler ( ) , _device ( device ) , _forwardMouseEvents ( format_mouse_events ) { }
2013-07-30 14:36:49 +08:00
2012-11-28 18:43:58 +08:00
virtual bool handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & aa , osg : : Object * , osg : : NodeVisitor * )
{
2013-12-19 21:49:27 +08:00
switch ( ea . getEventType ( ) )
{
case osgGA : : GUIEventAdapter : : PUSH :
case osgGA : : GUIEventAdapter : : RELEASE :
case osgGA : : GUIEventAdapter : : MOVE :
case osgGA : : GUIEventAdapter : : DRAG :
case osgGA : : GUIEventAdapter : : SCROLL :
if ( _forwardMouseEvents )
_device - > sendEvent ( ea ) ;
break ;
default :
_device - > sendEvent ( ea ) ;
break ;
}
2012-11-28 18:43:58 +08:00
return false ;
}
2013-12-19 21:49:27 +08:00
bool handle ( osgGA : : Event * event , osg : : Object * object , osg : : NodeVisitor * nv )
{
if ( event - > asGUIEventAdapter ( ) )
return osgGA : : GUIEventHandler : : handle ( event , object , nv ) ;
else
{
_device - > sendEvent ( * event ) ;
return false ;
}
}
2013-07-30 14:36:49 +08:00
2012-11-28 18:43:58 +08:00
private :
osg : : ref_ptr < osgGA : : Device > _device ;
2013-12-19 21:49:27 +08:00
bool _forwardMouseEvents ;
2012-11-28 18:43:58 +08:00
} ;
2014-01-23 23:37:48 +08:00
class DumpEventHandler : public osgGA : : GUIEventHandler {
public :
DumpEventHandler ( ) : osgGA : : GUIEventHandler ( ) { }
virtual bool handle ( const osgGA : : GUIEventAdapter & ea , osgGA : : GUIActionAdapter & aa , osg : : Object * , osg : : NodeVisitor * )
{
switch ( ea . getEventType ( ) )
{
case osgGA : : GUIEventAdapter : : FRAME :
return false ;
break ;
case osgGA : : GUIEventAdapter : : PUSH :
std : : cout < < " PUSH: " ;
break ;
case osgGA : : GUIEventAdapter : : RELEASE :
std : : cout < < " RELEASE: " ;
break ;
case osgGA : : GUIEventAdapter : : MOVE :
std : : cout < < " MOVE: " ;
break ;
case osgGA : : GUIEventAdapter : : DRAG :
std : : cout < < " DRAG: " ;
break ;
case osgGA : : GUIEventAdapter : : SCROLL :
std : : cout < < " SCROLL: " ;
break ;
break ;
default :
std : : cout < < ea . getEventType ( ) < < " " ;
break ;
}
std : : cout < < ea . getX ( ) < < " / " < < ea . getY ( ) < < " " < < ea . isMultiTouchEvent ( ) < < std : : endl ;
return false ;
}
bool handle ( osgGA : : Event * event , osg : : Object * object , osg : : NodeVisitor * nv )
{
if ( event - > asGUIEventAdapter ( ) )
return osgGA : : GUIEventHandler : : handle ( event , object , nv ) ;
else
{
return false ;
}
}
private :
} ;
2009-04-28 19:57:51 +08:00
enum P3DApplicationType
{
VIEWER ,
MASTER ,
2009-04-28 22:03:02 +08:00
SLAVE
2009-04-28 19:57:51 +08:00
} ;
2011-11-04 20:50:05 +08:00
void processLoadedModel ( osg : : ref_ptr < osg : : Node > & loadedModel , int optimizer_options , const std : : string & cursorFileName )
{
if ( ! loadedModel ) return ;
2013-07-30 14:36:49 +08:00
2011-11-04 20:50:05 +08:00
# if !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
// add back in enabling of the GL_ALPHA_TEST to get around the core OSG no longer setting it by default for opaque bins.
// the alpha test is required for the volume rendering alpha clipping to work.
loadedModel - > getOrCreateStateSet ( ) - > setMode ( GL_ALPHA_TEST , osg : : StateAttribute : : ON ) ;
# endif
// optimize the scene graph, remove rendundent nodes and state etc.
osgUtil : : Optimizer optimizer ;
optimizer . optimize ( loadedModel . get ( ) , optimizer_options ) ;
if ( ! cursorFileName . empty ( ) )
{
osg : : ref_ptr < osg : : Group > group = new osg : : Group ;
group - > addChild ( loadedModel . get ( ) ) ;
2013-08-09 15:38:32 +08:00
2013-08-09 00:49:33 +08:00
OSG_NOTICE < < " Creating Cursor " < < std : : endl ;
group - > addChild ( new osgPresentation : : Cursor ( cursorFileName , 20.0f ) ) ;
2013-08-09 15:38:32 +08:00
2011-11-04 20:50:05 +08:00
loadedModel = group ;
}
}
2009-04-28 19:57:51 +08:00
2013-12-19 21:49:27 +08:00
void addDeviceTo ( osgViewer : : Viewer & viewer , const std : : string & device_name , bool forward_mouse_events )
2012-12-06 01:15:53 +08:00
{
osg : : ref_ptr < osgGA : : Device > dev = osgDB : : readFile < osgGA : : Device > ( device_name ) ;
if ( dev . valid ( ) )
{
OSG_INFO < < " Adding Device : " < < device_name < < std : : endl ;
2013-01-07 20:17:26 +08:00
viewer . addDevice ( dev . get ( ) ) ;
2013-07-30 14:36:49 +08:00
2013-12-19 21:49:27 +08:00
if ( ( dev - > getCapabilities ( ) & osgGA : : Device : : SEND_EVENTS ) )
viewer . getEventHandlers ( ) . push_front ( new ForwardToDeviceEventHandler ( dev . get ( ) , forward_mouse_events ) ) ;
2012-12-06 01:15:53 +08:00
}
else
{
OSG_WARN < < " could not open device: " < < device_name < < std : : endl ;
}
}
2009-04-28 19:57:51 +08:00
int main ( int argc , char * * argv )
{
// use an ArgumentParser object to manage the program arguments.
osg : : ArgumentParser arguments ( & argc , argv ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// set up the usage document, in case we need to print out how to use this program.
arguments . getApplicationUsage ( ) - > setApplicationName ( arguments . getApplicationName ( ) ) ;
arguments . getApplicationUsage ( ) - > setDescription ( arguments . getApplicationName ( ) + " is the application for presenting 3D interactive slide shows. " ) ;
arguments . getApplicationUsage ( ) - > setCommandLineUsage ( arguments . getApplicationName ( ) + " [options] filename ... " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -h or --help " , " Display this information " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -a " , " Turn auto stepping on by default " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -d <float> " , " Time duration in seconds between layers/slides " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " -s <float> <float> <float> " , " width, height, distance and of the screen away from the viewer " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --viewer " , " Start Present3D as the viewer version. " ) ;
2010-09-15 20:50:16 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --authoring " , " Start Present3D as the authoring version, license required. " ) ;
2009-04-28 19:57:51 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --master " , " Start Present3D as the master version, license required. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --slave " , " Start Present3D as the slave version, license required. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --publishing " , " Start Present3D as the publishing version, license required. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --timeDelayOnNewSlideWithMovies " , " Set the time delay on new slide with movies, done to allow movie threads to get in sync with rendering thread. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --targetFrameRate " , " Set the target frame rate, defaults to 80Hz. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --version " , " Report the Present3D version. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --print <filename> " , " Print out slides to a series of image files. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --html <filename> " , " Print out slides to a series of html & image files. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --loop " , " Switch on looping of presentation. " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --devices " , " Print the Video input capability via QuickTime and exit. " ) ;
2013-12-19 21:49:27 +08:00
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --forwardMouseEvents " , " forward also mouse/touch-events to the devices " ) ;
arguments . getApplicationUsage ( ) - > addCommandLineOption ( " --suppressEnvTags " , " suppresses all found ENV-tags in the presentation " ) ;
2009-04-28 19:57:51 +08:00
2009-07-16 01:01:47 +08:00
// add alias from xml to p3d to provide backwards compatibility for old p3d files.
osgDB : : Registry : : instance ( ) - > addFileExtensionAlias ( " xml " , " p3d " ) ;
2009-04-28 19:57:51 +08:00
// if user requests devices video capability.
if ( arguments . read ( " -devices " ) | | arguments . read ( " --devices " ) )
{
// Force load QuickTime plugin, probe video capability, exit
osgDB : : readImageFile ( " devices.live " ) ;
return 1 ;
}
2013-12-19 21:49:27 +08:00
bool suppress_env_tags = false ;
if ( arguments . read ( " --suppressEnvTags " ) )
suppress_env_tags = true ;
2009-04-28 19:57:51 +08:00
// read any env vars from presentations before we create viewer to make sure the viewer
// utilises these env vars
2013-12-19 21:49:27 +08:00
if ( ! suppress_env_tags & & p3d : : readEnvVars ( arguments ) )
2009-04-28 19:57:51 +08:00
{
osg : : DisplaySettings : : instance ( ) - > readEnvironmentalVariables ( ) ;
}
2011-10-26 20:48:57 +08:00
// set up any logins required for http access
std : : string url , username , password ;
while ( arguments . read ( " --login " , url , username , password ) )
{
if ( ! osgDB : : Registry : : instance ( ) - > getAuthenticationMap ( ) )
{
osgDB : : Registry : : instance ( ) - > setAuthenticationMap ( new osgDB : : AuthenticationMap ) ;
osgDB : : Registry : : instance ( ) - > getAuthenticationMap ( ) - > addAuthenticationDetails (
url ,
new osgDB : : AuthenticationDetails ( username , password )
) ;
}
}
2009-04-28 19:57:51 +08:00
# ifdef USE_SDL
SDLIntegration sdlIntegration ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
osg : : notify ( osg : : INFO ) < < " USE_SDL " < < std : : endl ;
2013-07-30 14:36:49 +08:00
# endif
2009-04-28 19:57:51 +08:00
bool doSetViewer = true ;
std : : string configurationFile ;
// check env vars for configuration file
const char * str = getenv ( " PRESENT3D_CONFIG_FILE " ) ;
if ( ! str ) str = getenv ( " OSG_CONFIG_FILE " ) ;
if ( str ) configurationFile = str ;
// check command line parameters for configuration file.
while ( arguments . read ( " -c " , configurationFile ) ) { }
osg : : Vec4 clearColor ( 0.0f , 0.0f , 0.0f , 0.0f ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
while ( arguments . read ( " --clear-color " , clearColor [ 0 ] , clearColor [ 1 ] , clearColor [ 2 ] , clearColor [ 3 ] ) ) { }
2010-04-30 23:51:38 +08:00
std : : string filename ;
if ( arguments . read ( " --spell-check " , filename ) )
{
p3d : : SpellChecker spellChecker ;
spellChecker . checkP3dXml ( filename ) ;
return 1 ;
}
2010-05-01 03:42:43 +08:00
if ( arguments . read ( " --strip-text " , filename ) )
{
p3d : : XmlPatcher patcher ;
// patcher.stripP3dXml(filename, osg::notify(osg::NOTICE));
osg : : ref_ptr < osgDB : : XmlNode > newNode = patcher . simplifyP3dXml ( filename ) ;
if ( newNode . valid ( ) )
{
newNode - > write ( std : : cout ) ;
}
return 1 ;
}
std : : string lhs_filename , rhs_filename ;
if ( arguments . read ( " --merge " , lhs_filename , rhs_filename ) )
{
p3d : : XmlPatcher patcher ;
osg : : ref_ptr < osgDB : : XmlNode > newNode = patcher . mergeP3dXml ( lhs_filename , rhs_filename ) ;
if ( newNode . valid ( ) )
{
newNode - > write ( std : : cout ) ;
}
return 1 ;
}
2010-04-30 23:51:38 +08:00
2009-04-28 19:57:51 +08:00
// construct the viewer.
osgViewer : : Viewer viewer ( arguments ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// set clear colour to black by default.
viewer . getCamera ( ) - > setClearColor ( clearColor ) ;
if ( ! configurationFile . empty ( ) )
{
viewer . readConfiguration ( configurationFile ) ;
doSetViewer = false ;
}
2013-12-19 21:49:27 +08:00
bool forwardMouseEvents = false ;
if ( arguments . read ( " --forwardMouseEvents " ) )
forwardMouseEvents = true ;
2012-10-30 20:31:27 +08:00
2012-11-01 01:06:29 +08:00
const char * p3dDevice = getenv ( " P3D_DEVICE " ) ;
if ( p3dDevice )
{
2012-12-08 03:05:47 +08:00
osgDB : : StringList devices ;
osgDB : : split ( p3dDevice , devices ) ;
for ( osgDB : : StringList : : iterator i = devices . begin ( ) ; i ! = devices . end ( ) ; + + i )
{
2013-12-19 21:49:27 +08:00
addDeviceTo ( viewer , * i , forwardMouseEvents ) ;
2012-12-08 03:05:47 +08:00
}
2012-11-01 01:06:29 +08:00
}
2012-10-30 20:31:27 +08:00
std : : string device ;
while ( arguments . read ( " --device " , device ) )
{
2013-12-19 21:49:27 +08:00
addDeviceTo ( viewer , device , forwardMouseEvents ) ;
2013-07-30 14:36:49 +08:00
2012-10-30 20:31:27 +08:00
}
if ( arguments . read ( " --http-control " ) )
{
2013-07-30 14:36:49 +08:00
2012-10-30 20:31:27 +08:00
std : : string server_address = " localhost " ;
std : : string server_port = " 8080 " ;
std : : string document_root = " htdocs " ;
while ( arguments . read ( " --http-server-address " , server_address ) ) { }
while ( arguments . read ( " --http-server-port " , server_port ) ) { }
while ( arguments . read ( " --http-document-root " , document_root ) ) { }
osg : : ref_ptr < osgDB : : Options > device_options = new osgDB : : Options ( " documentRegisteredHandlers " ) ;
2012-11-19 19:25:52 +08:00
osg : : ref_ptr < osgGA : : Device > rest_http_device = osgDB : : readFile < osgGA : : Device > ( server_address + " : " + server_port + " / " + document_root + " .resthttp " , device_options . get ( ) ) ;
2012-10-30 20:31:27 +08:00
if ( rest_http_device . valid ( ) )
{
viewer . addDevice ( rest_http_device . get ( ) ) ;
}
}
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// set up stereo masks
2013-07-30 14:39:33 +08:00
2009-04-28 19:57:51 +08:00
viewer . getCamera ( ) - > setCullMaskLeft ( 0x00000001 ) ;
2013-07-30 14:36:49 +08:00
viewer . getCamera ( ) - > setCullMaskRight ( 0x00000002 ) ;
2009-04-28 19:57:51 +08:00
2013-07-30 14:39:33 +08:00
bool assignLeftCullMaskForMono = true ;
if ( assignLeftCullMaskForMono )
{
viewer . getCamera ( ) - > setCullMask ( viewer . getCamera ( ) - > getCullMaskLeft ( ) ) ;
}
else
{
viewer . getCamera ( ) - > setCullMask ( 0xffffffff ) ;
}
2009-04-28 19:57:51 +08:00
// set up the camera manipulators.
{
osg : : ref_ptr < osgGA : : KeySwitchMatrixManipulator > keyswitchManipulator = new osgGA : : KeySwitchMatrixManipulator ;
2014-01-23 23:37:48 +08:00
keyswitchManipulator - > addMatrixManipulator ( ' 1 ' , " Trackball " , new osgGA : : MultiTouchTrackballManipulator ( ) ) ;
2009-04-28 19:57:51 +08:00
keyswitchManipulator - > addMatrixManipulator ( ' 2 ' , " Flight " , new osgGA : : FlightManipulator ( ) ) ;
keyswitchManipulator - > addMatrixManipulator ( ' 3 ' , " Drive " , new osgGA : : DriveManipulator ( ) ) ;
keyswitchManipulator - > addMatrixManipulator ( ' 4 ' , " Terrain " , new osgGA : : TerrainManipulator ( ) ) ;
std : : string pathfile ;
char keyForAnimationPath = ' 5 ' ;
while ( arguments . read ( " -p " , pathfile ) )
{
osgGA : : AnimationPathManipulator * apm = new osgGA : : AnimationPathManipulator ( pathfile ) ;
2013-07-30 14:36:49 +08:00
if ( apm | | ! apm - > valid ( ) )
2009-04-28 19:57:51 +08:00
{
unsigned int num = keyswitchManipulator - > getNumMatrixManipulators ( ) ;
keyswitchManipulator - > addMatrixManipulator ( keyForAnimationPath , " Path " , apm ) ;
keyswitchManipulator - > selectMatrixManipulator ( num ) ;
+ + keyForAnimationPath ;
}
}
viewer . setCameraManipulator ( keyswitchManipulator . get ( ) ) ;
}
2014-01-23 23:37:48 +08:00
//viewer.getEventHandlers().push_front(new DumpEventHandler());
2009-04-28 19:57:51 +08:00
// add the state manipulator
2012-01-25 23:38:31 +08:00
osg : : ref_ptr < osgGA : : StateSetManipulator > ssManipulator = new osgGA : : StateSetManipulator ( viewer . getCamera ( ) - > getOrCreateStateSet ( ) ) ;
ssManipulator - > setKeyEventToggleTexturing ( ' e ' ) ;
viewer . addEventHandler ( ssManipulator . get ( ) ) ;
2009-04-28 19:57:51 +08:00
// add the state manipulator
viewer . addEventHandler ( new osgViewer : : StatsHandler ( ) ) ;
viewer . addEventHandler ( new osgViewer : : WindowSizeHandler ( ) ) ;
// neeed to address.
// viewer.getScene()->getUpdateVisitor()->setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
const char * p3dCursor = getenv ( " P3D_CURSOR " ) ;
std : : string cursorFileName ( p3dCursor ? p3dCursor : " " ) ;
while ( arguments . read ( " --cursor " , cursorFileName ) ) { }
2013-01-07 20:41:16 +08:00
const char * p3dShowCursor = getenv ( " P3D_SHOW_CURSOR " ) ;
std : : string showCursor ( p3dShowCursor ? p3dShowCursor : " YES " ) ;
while ( arguments . read ( " --show-cursor " ) ) { showCursor = " YES " ; }
while ( arguments . read ( " --hide-cursor " ) ) { showCursor = " NO " ; }
bool hideCursor = ( showCursor = = " No " | | showCursor = = " NO " | | showCursor = = " no " ) ;
2009-04-28 19:57:51 +08:00
while ( arguments . read ( " --set-viewer " ) ) { doSetViewer = true ; }
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
while ( arguments . read ( " --no-set-viewer " ) ) { doSetViewer = false ; }
2013-01-10 00:03:22 +08:00
// if we want to hide the cursor override the custom cursor.
if ( hideCursor ) cursorFileName . clear ( ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// cluster related entries.
int socketNumber = 8100 ;
while ( arguments . read ( " -n " , socketNumber ) ) { }
float camera_fov = - 1.0f ;
while ( arguments . read ( " -f " , camera_fov ) ) { }
float camera_offset = 45.0f ;
while ( arguments . read ( " -o " , camera_offset ) ) { }
std : : string exportName ;
while ( arguments . read ( " --print " , exportName ) ) { }
while ( arguments . read ( " --html " , exportName ) ) { }
// read any time delay argument.
float timeDelayBetweenSlides = 1.0f ;
while ( arguments . read ( " -d " , timeDelayBetweenSlides ) ) { }
bool autoSteppingActive = false ;
while ( arguments . read ( " -a " ) ) autoSteppingActive = true ;
bool loopPresentation = false ;
while ( arguments . read ( " --loop " ) ) loopPresentation = true ;
2012-11-14 00:15:20 +08:00
{
// set update hte default traversal mode settings for update visitor
2012-12-21 00:16:07 +08:00
// default to osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN.
osg : : NodeVisitor : : TraversalMode updateTraversalMode = osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ; // viewer.getUpdateVisitor()->getTraversalMode();
2012-11-14 00:15:20 +08:00
const char * p3dUpdateStr = getenv ( " P3D_UPDATE " ) ;
if ( p3dUpdateStr )
{
std : : string updateStr ( p3dUpdateStr ) ;
if ( updateStr = = " active " | | updateStr = = " Active " | | updateStr = = " ACTIVE " ) updateTraversalMode = osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ;
else if ( updateStr = = " all " | | updateStr = = " All " | | updateStr = = " ALL " ) updateTraversalMode = osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ;
}
2009-06-25 00:03:49 +08:00
2012-11-14 00:15:20 +08:00
while ( arguments . read ( " --update-active " ) ) updateTraversalMode = osg : : NodeVisitor : : TRAVERSE_ACTIVE_CHILDREN ;
while ( arguments . read ( " --update-all " ) ) updateTraversalMode = osg : : NodeVisitor : : TRAVERSE_ALL_CHILDREN ;
2012-11-13 23:26:06 +08:00
2012-11-14 00:15:20 +08:00
viewer . getUpdateVisitor ( ) - > setTraversalMode ( updateTraversalMode ) ;
}
2012-11-13 23:26:06 +08:00
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// register the slide event handler - which moves the presentation from slide to slide, layer to layer.
2011-11-04 20:50:05 +08:00
osg : : ref_ptr < osgPresentation : : SlideEventHandler > seh = new osgPresentation : : SlideEventHandler ( & viewer ) ;
viewer . addEventHandler ( seh . get ( ) ) ;
2009-04-28 19:57:51 +08:00
seh - > setAutoSteppingActive ( autoSteppingActive ) ;
seh - > setTimeDelayBetweenSlides ( timeDelayBetweenSlides ) ;
seh - > setLoopPresentation ( loopPresentation ) ;
double targetFrameRate = 80.0 ;
while ( arguments . read ( " --targetFrameRate " , targetFrameRate ) ) { }
// set the time delay
float timeDelayOnNewSlideWithMovies = 0.4f ;
while ( arguments . read ( " --timeDelayOnNewSlideWithMovies " , timeDelayOnNewSlideWithMovies ) ) { }
seh - > setTimeDelayOnNewSlideWithMovies ( timeDelayOnNewSlideWithMovies ) ;
// set up optimizer options
unsigned int optimizer_options = osgUtil : : Optimizer : : DEFAULT_OPTIMIZATIONS ;
bool relase_and_compile = false ;
2013-07-30 14:36:49 +08:00
while ( arguments . read ( " --release-and-compile " ) )
2009-04-28 19:57:51 +08:00
{
relase_and_compile = true ;
}
seh - > setReleaseAndCompileOnEachNewSlide ( relase_and_compile ) ;
if ( relase_and_compile )
{
// make sure that imagery stays around after being applied to textures.
viewer . getDatabasePager ( ) - > setUnrefImageDataAfterApplyPolicy ( true , false ) ;
2009-08-20 22:20:55 +08:00
optimizer_options & = ~ osgUtil : : Optimizer : : OPTIMIZE_TEXTURE_SETTINGS ;
2009-04-28 19:57:51 +08:00
}
2013-07-30 14:36:49 +08:00
//
2009-04-28 19:57:51 +08:00
// osgDB::Registry::instance()->getOrCreateDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,false);
// optimizer_options &= ~osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
// osg::Texture::getTextureObjectManager()->setExpiryDelay(0.0f);
// osgDB::Registry::instance()->getOrCreateDatabasePager()->setExpiryDelay(1.0f);
// register the handler for modifying the point size
2011-11-04 20:50:05 +08:00
osg : : ref_ptr < PointsEventHandler > peh = new PointsEventHandler ;
viewer . addEventHandler ( peh . get ( ) ) ;
2011-11-01 21:36:07 +08:00
// add the screen capture handler
2012-12-06 19:36:35 +08:00
std : : string screenCaptureFilename = " screen_shot.jpg " ;
2011-11-01 21:36:07 +08:00
while ( arguments . read ( " --screenshot " , screenCaptureFilename ) ) { }
osg : : ref_ptr < osgViewer : : ScreenCaptureHandler : : WriteToFile > writeFile = new osgViewer : : ScreenCaptureHandler : : WriteToFile (
osgDB : : getNameLessExtension ( screenCaptureFilename ) ,
osgDB : : getFileExtension ( screenCaptureFilename ) ) ;
osg : : ref_ptr < osgViewer : : ScreenCaptureHandler > screenCaptureHandler = new osgViewer : : ScreenCaptureHandler ( writeFile . get ( ) ) ;
2011-11-02 00:13:24 +08:00
screenCaptureHandler - > setKeyEventTakeScreenShot ( ' m ' ) ; //osgGA::GUIEventAdapter::KEY_Print);
screenCaptureHandler - > setKeyEventToggleContinuousCapture ( ' M ' ) ;
2011-11-01 21:36:07 +08:00
viewer . addEventHandler ( screenCaptureHandler . get ( ) ) ;
2009-04-28 19:57:51 +08:00
// osg::DisplaySettings::instance()->setSplitStereoAutoAjustAspectRatio(false);
float width = osg : : DisplaySettings : : instance ( ) - > getScreenWidth ( ) ;
float height = osg : : DisplaySettings : : instance ( ) - > getScreenHeight ( ) ;
float distance = osg : : DisplaySettings : : instance ( ) - > getScreenDistance ( ) ;
2013-07-30 14:36:49 +08:00
while ( arguments . read ( " -s " , width , height , distance ) )
2009-04-28 19:57:51 +08:00
{
osg : : DisplaySettings : : instance ( ) - > setScreenDistance ( distance ) ;
osg : : DisplaySettings : : instance ( ) - > setScreenHeight ( height ) ;
osg : : DisplaySettings : : instance ( ) - > setScreenWidth ( width ) ;
}
2009-09-09 21:23:49 +08:00
std : : string outputFileName ;
while ( arguments . read ( " --output " , outputFileName ) ) { }
2009-04-28 19:57:51 +08:00
// get details on keyboard and mouse bindings used by the viewer.
viewer . getUsage ( * arguments . getApplicationUsage ( ) ) ;
// if user request help write it out to cout.
2013-10-24 20:15:37 +08:00
unsigned int helpType = 0 ;
if ( ( helpType = arguments . readHelpType ( ) ) )
2009-04-28 19:57:51 +08:00
{
2013-10-24 20:15:37 +08:00
arguments . getApplicationUsage ( ) - > write ( std : : cout , helpType ) ;
2009-04-28 19:57:51 +08:00
return 1 ;
}
P3DApplicationType P3DApplicationType = VIEWER ;
str = getenv ( " PRESENT3D_TYPE " ) ;
if ( str )
{
if ( strcmp ( str , " viewer " ) = = 0 ) P3DApplicationType = VIEWER ;
else if ( strcmp ( str , " master " ) = = 0 ) P3DApplicationType = MASTER ;
else if ( strcmp ( str , " slave " ) = = 0 ) P3DApplicationType = SLAVE ;
}
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
while ( arguments . read ( " --viewer " ) ) { P3DApplicationType = VIEWER ; }
while ( arguments . read ( " --master " ) ) { P3DApplicationType = MASTER ; }
while ( arguments . read ( " --slave " ) ) { P3DApplicationType = SLAVE ; }
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
while ( arguments . read ( " --version " ) )
{
std : : string appTypeName = " invalid " ;
switch ( P3DApplicationType )
{
case ( VIEWER ) : appTypeName = " viewer " ; break ;
case ( MASTER ) : appTypeName = " master " ; break ;
case ( SLAVE ) : appTypeName = " slave " ; break ;
}
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " Present3D " < < appTypeName < < " version : " < < s_version < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
return 0 ;
}
// any option left unread are converted into errors to write out later.
//arguments.reportRemainingOptionsAsUnrecognized();
2009-08-06 18:06:20 +08:00
// report any errors if they have ocured when parsing the program aguments.
2009-04-28 19:57:51 +08:00
if ( arguments . errors ( ) )
{
arguments . writeErrorMessages ( osg : : notify ( osg : : INFO ) ) ;
return 1 ;
}
// read files name from arguments.
p3d : : FileNameList xmlFiles , normalFiles ;
if ( ! p3d : : getFileNames ( arguments , xmlFiles , normalFiles ) )
{
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < " No file specified, please specify and file to load. " < < std : : endl ;
osg : : notify ( osg : : NOTICE ) < < std : : endl ;
return 1 ;
}
bool viewerInitialized = false ;
if ( ! xmlFiles . empty ( ) )
{
osg : : ref_ptr < osg : : Node > holdingModel = p3d : : readHoldingSlide ( xmlFiles . front ( ) ) ;
if ( holdingModel . valid ( ) )
{
viewer . setSceneData ( holdingModel . get ( ) ) ;
2009-05-05 18:27:59 +08:00
seh - > selectSlide ( 0 ) ;
2009-04-28 19:57:51 +08:00
if ( ! viewerInitialized )
{
// pass the global stateset to the point event handler so that it can
// alter the point size of all points in the scene.
peh - > setStateSet ( viewer . getCamera ( ) - > getOrCreateStateSet ( ) ) ;
// create the windows and run the threads.
viewer . realize ( ) ;
if ( doSetViewer ) setViewer ( viewer , width , height , distance ) ;
viewerInitialized = true ;
}
seh - > home ( ) ;
// render a frame
viewer . frame ( ) ;
}
}
osg : : Timer timer ;
osg : : Timer_t start_tick = timer . tick ( ) ;
osg : : ref_ptr < osgDB : : ReaderWriter : : Options > cacheAllOption = new osgDB : : ReaderWriter : : Options ;
2013-12-19 21:49:27 +08:00
if ( suppress_env_tags )
cacheAllOption - > setPluginStringData ( " suppressEnvTags " , " true " ) ;
2009-04-28 19:57:51 +08:00
cacheAllOption - > setObjectCacheHint ( osgDB : : ReaderWriter : : Options : : CACHE_ALL ) ;
osgDB : : Registry : : instance ( ) - > setOptions ( cacheAllOption . get ( ) ) ;
// read the scene from the list of file specified commandline args.
osg : : ref_ptr < osg : : Node > loadedModel = p3d : : readShowFiles ( arguments , cacheAllOption . get ( ) ) ; // osgDB::readNodeFiles(arguments, cacheAllOption.get());
osgDB : : Registry : : instance ( ) - > setOptions ( 0 ) ;
// if no model has been successfully loaded report failure.
2013-07-30 14:36:49 +08:00
if ( ! loadedModel )
2009-04-28 19:57:51 +08:00
{
osg : : notify ( osg : : INFO ) < < arguments . getApplicationName ( ) < < " : No data loaded " < < std : : endl ;
return 1 ;
}
osg : : Timer_t end_tick = timer . tick ( ) ;
osg : : notify ( osg : : INFO ) < < " Time to load = " < < timer . delta_s ( start_tick , end_tick ) < < std : : endl ;
if ( loadedModel - > getNumDescriptions ( ) > 0 )
{
for ( unsigned int i = 0 ; i < loadedModel - > getNumDescriptions ( ) ; + + i )
{
const std : : string & desc = loadedModel - > getDescription ( i ) ;
2013-07-30 14:36:49 +08:00
if ( desc = = " loop " )
2009-04-28 19:57:51 +08:00
{
osg : : notify ( osg : : NOTICE ) < < " Enabling looping " < < std : : endl ;
seh - > setLoopPresentation ( true ) ;
}
2013-07-30 14:36:49 +08:00
else if ( desc = = " auto " )
2009-04-28 19:57:51 +08:00
{
osg : : notify ( osg : : NOTICE ) < < " Enabling auto run " < < std : : endl ;
seh - > setAutoSteppingActive ( true ) ;
}
}
}
2011-11-04 20:50:05 +08:00
processLoadedModel ( loadedModel , optimizer_options , cursorFileName ) ;
2009-04-28 19:57:51 +08:00
// set the scene to render
viewer . setSceneData ( loadedModel . get ( ) ) ;
if ( ! viewerInitialized )
{
// pass the global stateset to the point event handler so that it can
// alter the point size of all points in the scene.
peh - > setStateSet ( viewer . getCamera ( ) - > getOrCreateStateSet ( ) ) ;
// create the windows and run the threads.
viewer . realize ( ) ;
if ( doSetViewer ) setViewer ( viewer , width , height , distance ) ;
viewerInitialized = true ;
}
2009-08-06 18:57:42 +08:00
2011-11-04 20:50:05 +08:00
2013-07-30 14:36:49 +08:00
2011-11-04 20:50:05 +08:00
2011-10-24 21:40:29 +08:00
// pass the model to the slide event handler so it knows which to manipulate.
seh - > set ( loadedModel . get ( ) ) ;
seh - > selectSlide ( 0 ) ;
seh - > home ( ) ;
if ( ! outputFileName . empty ( ) )
{
osgDB : : writeNodeFile ( * loadedModel , outputFileName ) ;
return 0 ;
}
2013-07-30 14:36:49 +08:00
2011-10-24 21:40:29 +08:00
2013-01-07 20:41:16 +08:00
if ( ! cursorFileName . empty ( ) | | hideCursor )
2009-04-28 19:57:51 +08:00
{
2009-08-06 18:57:42 +08:00
// have to add a frame in here to avoid problems with X11 threading issue on switching off the cursor
// not yet sure why it makes a difference, but it at least fixes the crash that would otherwise occur
// under X11.
viewer . frame ( ) ;
2009-04-28 19:57:51 +08:00
// switch off the cursor
osgViewer : : Viewer : : Windows windows ;
viewer . getWindows ( windows ) ;
for ( osgViewer : : Viewer : : Windows : : iterator itr = windows . begin ( ) ;
itr ! = windows . end ( ) ;
+ + itr )
{
( * itr ) - > useCursor ( false ) ;
}
}
osg : : Timer_t startOfFrameTick = osg : : Timer : : instance ( ) - > tick ( ) ;
double targetFrameTime = 1.0 / targetFrameRate ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
if ( exportName . empty ( ) )
{
// objects for managing the broadcasting and recieving of camera packets.
CameraPacket cp ;
Broadcaster bc ;
Receiver rc ;
bc . setPort ( static_cast < short int > ( socketNumber ) ) ;
rc . setPort ( static_cast < short int > ( socketNumber ) ) ;
bool masterKilled = false ;
DataConverter scratchPad ( 1024 ) ;
while ( ! viewer . done ( ) & & ! masterKilled )
{
// wait for all cull and draw threads to complete.
viewer . advance ( ) ;
osg : : Timer_t currentTick = osg : : Timer : : instance ( ) - > tick ( ) ;
double deltaTime = osg : : Timer : : instance ( ) - > delta_s ( startOfFrameTick , currentTick ) ;
if ( deltaTime < targetFrameTime )
{
OpenThreads : : Thread : : microSleep ( static_cast < unsigned int > ( ( targetFrameTime - deltaTime ) * 1000000.0 ) ) ;
}
startOfFrameTick = osg : : Timer : : instance ( ) - > tick ( ) ;
2013-07-30 14:36:49 +08:00
#if 0
2009-04-28 19:57:51 +08:00
if ( kmcb )
{
double time = kmcb - > getTime ( ) ;
viewer . getFrameStamp ( ) - > setReferenceTime ( time ) ;
}
# endif
# ifdef USE_SDL
sdlIntegration . update ( viewer ) ;
# endif
if ( P3DApplicationType = = MASTER )
{
// take camera zero as the guide.
osg : : Matrix modelview ( viewer . getCamera ( ) - > getViewMatrix ( ) ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
cp . setPacket ( modelview , viewer . getFrameStamp ( ) ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// cp.readEventQueue(viewer);
scratchPad . reset ( ) ;
scratchPad . write ( cp ) ;
scratchPad . reset ( ) ;
scratchPad . read ( cp ) ;
2011-05-06 17:22:17 +08:00
bc . setBuffer ( scratchPad . startPtr ( ) , scratchPad . numBytes ( ) ) ;
2013-07-30 14:36:49 +08:00
2011-05-06 17:22:17 +08:00
std : : cout < < " bc.sync() " < < scratchPad . numBytes ( ) < < std : : endl ;
2009-04-28 19:57:51 +08:00
bc . sync ( ) ;
}
else if ( P3DApplicationType = = SLAVE )
{
2011-05-06 17:22:17 +08:00
rc . setBuffer ( scratchPad . startPtr ( ) , scratchPad . numBytes ( ) ) ;
2009-04-28 19:57:51 +08:00
rc . sync ( ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
scratchPad . reset ( ) ;
scratchPad . read ( cp ) ;
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
// cp.writeEventQueue(viewer);
2013-07-30 14:36:49 +08:00
if ( cp . getMasterKilled ( ) )
2009-04-28 19:57:51 +08:00
{
std : : cout < < " Received master killed. " < < std : : endl ;
// break out of while (!done) loop since we've now want to shut down.
masterKilled = true ;
}
}
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer . eventTraversal ( ) ;
2011-11-04 20:50:05 +08:00
if ( seh - > getRequestReload ( ) )
{
OSG_INFO < < " Reload requested " < < std : : endl ;
seh - > setRequestReload ( false ) ;
int previous_ActiveSlide = seh - > getActiveSlide ( ) ;
int previous_ActiveLayer = seh - > getActiveLayer ( ) ;
// reset time so any event key generate
loadedModel = p3d : : readShowFiles ( arguments , cacheAllOption . get ( ) ) ;
processLoadedModel ( loadedModel , optimizer_options , cursorFileName ) ;
if ( ! loadedModel )
{
return 0 ;
}
viewer . setSceneData ( loadedModel . get ( ) ) ;
seh - > set ( loadedModel . get ( ) ) ;
seh - > selectSlide ( previous_ActiveSlide , previous_ActiveLayer ) ;
continue ;
2013-07-30 14:36:49 +08:00
2011-11-04 20:50:05 +08:00
}
2009-04-28 19:57:51 +08:00
// update the scene by traversing it with the the update visitor which will
// call all node update callbacks and animations.
viewer . updateTraversal ( ) ;
if ( P3DApplicationType = = SLAVE )
{
osg : : Matrix modelview ;
cp . getModelView ( modelview , camera_offset ) ;
viewer . getCamera ( ) - > setViewMatrix ( modelview ) ;
}
// fire off the cull and draw traversals of the scene.
if ( ! masterKilled )
viewer . renderingTraversals ( ) ;
}
}
else
{
2011-11-18 02:45:18 +08:00
ExportHTML : : write ( seh . get ( ) , viewer , exportName ) ;
2009-04-28 19:57:51 +08:00
}
2013-07-30 14:36:49 +08:00
2009-04-28 19:57:51 +08:00
return 0 ;
}