root/OpenSceneGraph/trunk/applications/present3D/present3D.cpp @ 12362

Revision 12362, 32.9 kB (checked in by robert, 4 years ago)

Fixed Coverity reported issue.

CID 11388: Resource leak in object (CTOR_DTOR_LEAK)
Allocating memory by calling "new char[numBytes]".
Assigning: "this->_startPtr" = "new char[numBytes]".
The constructor allocates field "_startPtr" of "struct DataConverter?" but there is no destructor.
Assigning: "this->_currentPtr" = "new char[numBytes]".
The constructor allocates field "_currentPtr" of "struct DataConverter?" but there is no destructor.

  • Property svn:eol-style set to native
Line 
1/* -*-c++-*- Present3D - Copyright (C) 1999-2006 Robert Osfield
2 *
3 * This software is open source and may be redistributed and/or modified under 
4 * the terms of the GNU General Public License (GPL) version 2.0.
5 * The full license is in LICENSE.txt file included with this distribution,.
6 *
7 * This software is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 * include LICENSE.txt for more details.
11*/
12
13#include <osg/Geometry>
14#include <osg/CameraNode>
15#include <osg/Texture2D>
16#include <osg/AutoTransform>
17#include <osg/Notify>
18#include <osg/io_utils>
19
20
21#include <osgDB/ReadFile>
22#include <osgDB/WriteFile>
23#include <osgDB/FileNameUtils>
24#include <osgUtil/Optimizer>
25
26#include <osgViewer/Viewer>
27#include <osgViewer/ViewerEventHandlers>
28
29#include <OpenThreads/Thread>
30
31#include <osgGA/TrackballManipulator>
32#include <osgGA/FlightManipulator>
33#include <osgGA/DriveManipulator>
34#include <osgGA/KeySwitchMatrixManipulator>
35#include <osgGA/AnimationPathManipulator>
36#include <osgGA/TerrainManipulator>
37#include <osgGA/AnimationPathManipulator>
38#include <osgGA/StateSetManipulator>
39
40#include <osgPresentation/SlideEventHandler>
41#include <osgPresentation/SlideShowConstructor>
42
43#include "ReadShowFile.h"
44#include "PointsEventHandler.h"
45#include "Cluster.h"
46#include "ExportHTML.h"
47#include "SpellChecker.h"
48
49#include <sstream>
50#include <fstream>
51#include <iostream>
52
53#include <string.h>
54
55#ifdef USE_SDL
56    #include "SDLIntegration.h"
57#endif
58
59#ifdef OSG_LIBRARY_STATIC
60
61    // include the plugins we need
62    USE_OSGPLUGIN(ive)
63    USE_OSGPLUGIN(osg)
64    USE_OSGPLUGIN(osg2)
65    USE_OSGPLUGIN(p3d)
66    USE_OSGPLUGIN(paths)
67    USE_OSGPLUGIN(rgb)
68    USE_OSGPLUGIN(OpenFlight)
69    USE_OSGPLUGIN(obj)
70
71#ifdef USE_FREETYPE
72    USE_OSGPLUGIN(freetype)
73#endif
74
75#ifdef USE_PNG
76    USE_OSGPLUGIN(png)
77#endif
78
79#ifdef USE_JPEG
80    USE_OSGPLUGIN(jpeg)
81#endif
82
83#ifdef USE_FFMPEG
84    USE_OSGPLUGIN(ffmpeg)
85#endif
86
87#ifdef USE_POPPLER_CAIRO
88    USE_OSGPLUGIN(pdf)
89#endif
90
91#ifdef USE_CURL
92    USE_OSGPLUGIN(curl)
93#endif
94
95    USE_DOTOSGWRAPPER_LIBRARY(osg)
96    USE_DOTOSGWRAPPER_LIBRARY(osgFX)
97    USE_DOTOSGWRAPPER_LIBRARY(osgParticle)
98    USE_DOTOSGWRAPPER_LIBRARY(osgShadow)
99    USE_DOTOSGWRAPPER_LIBRARY(osgSim)
100    USE_DOTOSGWRAPPER_LIBRARY(osgTerrain)
101    USE_DOTOSGWRAPPER_LIBRARY(osgText)
102    USE_DOTOSGWRAPPER_LIBRARY(osgViewer)
103    USE_DOTOSGWRAPPER_LIBRARY(osgVolume)
104    USE_DOTOSGWRAPPER_LIBRARY(osgWidget)
105
106    USE_SERIALIZER_WRAPPER_LIBRARY(osg)
107    USE_SERIALIZER_WRAPPER_LIBRARY(osgAnimation)
108    USE_SERIALIZER_WRAPPER_LIBRARY(osgFX)
109    USE_SERIALIZER_WRAPPER_LIBRARY(osgManipulator)
110    USE_SERIALIZER_WRAPPER_LIBRARY(osgParticle)
111    USE_SERIALIZER_WRAPPER_LIBRARY(osgShadow)
112    USE_SERIALIZER_WRAPPER_LIBRARY(osgSim)
113    USE_SERIALIZER_WRAPPER_LIBRARY(osgTerrain)
114    USE_SERIALIZER_WRAPPER_LIBRARY(osgText)
115    USE_SERIALIZER_WRAPPER_LIBRARY(osgVolume)
116
117    // include the platform specific GraphicsWindow implementation.
118    USE_GRAPHICSWINDOW()
119
120#endif
121
122static const char* s_version = "1.4 beta";
123
124void setViewer(osgViewer::Viewer& viewer, float width, float height, float distance)
125{
126    double vfov = osg::RadiansToDegrees(atan2(height/2.0f,distance)*2.0);
127    // double hfov = osg::RadiansToDegrees(atan2(width/2.0f,distance)*2.0);
128
129    viewer.getCamera()->setProjectionMatrixAsPerspective( vfov, width/height, 0.1, 1000.0);
130}
131
132#if 1
133
134class RayFollowsMouseCallback : public osg::Drawable::EventCallback
135{
136    RayFollowsMouseCallback() {}
137
138    /** do customized Event code. */
139    virtual void event(osg::NodeVisitor* nv, osg::Drawable* drawable)
140    {
141        osg::Geometry* geometry = drawable->asGeometry();
142        osgGA::EventVisitor* ev = dynamic_cast<osgGA::EventVisitor*>(nv);
143
144        if (!ev || !geometry) return;
145
146        osgGA::GUIActionAdapter* aa = ev->getActionAdapter();
147        osgViewer::View* view = dynamic_cast<osgViewer::View*>(aa);
148        if (!view) return;
149
150        osg::Vec3Array* vertices = dynamic_cast<osg::Vec3Array*>(geometry->getVertexArray());
151        if (!vertices) return;
152
153        osg::Camera* camera = view->getCamera();
154        osg::Matrix VP =  camera->getViewMatrix() * camera->getProjectionMatrix();
155
156        osg::Matrix inverse_VP;
157        inverse_VP.invert(VP);
158
159        osgGA::EventQueue::Events& events = ev->getEvents();
160        for(osgGA::EventQueue::Events::iterator itr = events.begin();
161            itr != events.end();
162            ++itr)
163        {
164            handle(inverse_VP, *(*itr), vertices);
165        }
166
167    }
168
169    void handle(const osg::Matrix& inverse_VP, osgGA::GUIEventAdapter& ea, osg::Vec3Array* vertices)
170    {
171        osg::Vec3d start_eye(ea.getXnormalized(), ea.getYnormalized(), 0.0);
172        osg::Vec3d end_eye(ea.getXnormalized(), ea.getYnormalized(), 1.0);
173
174        osg::Vec3d start_world = start_eye * inverse_VP;
175        osg::Vec3d end_world = start_eye * inverse_VP;
176
177        osg::notify(osg::NOTICE)<<"start_world="<<start_world<<std::endl;
178        osg::notify(osg::NOTICE)<<"end_world="<<end_world<<std::endl;
179
180        (*vertices)[0] = start_world;
181        (*vertices)[1] = end_world;
182    }
183};
184
185class FollowMouseCallback: public osgGA::GUIEventHandler
186{
187    public:
188
189        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter& aa, osg::Object* object, osg::NodeVisitor* nv)
190        {
191            osg::AutoTransform* transform = dynamic_cast<osg::AutoTransform*>(object);
192            if (!transform) return false;
193
194            switch(ea.getEventType())
195            {
196                case(osgGA::GUIEventAdapter::FRAME):
197                //case(osgGA::GUIEventAdapter::MOVE):
198                //case(osgGA::GUIEventAdapter::DRAG):
199                {
200                    osgViewer::View* view = dynamic_cast<osgViewer::View*>(&aa);
201
202                    transform->setNodeMask(0x0);
203
204                    osg::notify(osg::NOTICE)<<std::endl<<"ea.getGraphicsContext()="<<ea.getGraphicsContext()<<std::endl;
205                    osg::notify(osg::NOTICE)<<"ea.getWindowWidth()="<<ea.getWindowWidth()<<std::endl;
206                    osg::notify(osg::NOTICE)<<"ea.getWindowHeight()="<<ea.getWindowHeight()<<std::endl;
207                    osg::notify(osg::NOTICE)<<"ea.getX()="<<ea.getX()<<std::endl;
208                    osg::notify(osg::NOTICE)<<"ea.getXin()="<<ea.getXmin()<<std::endl;
209                    osg::notify(osg::NOTICE)<<"ea.getXmax()="<<ea.getXmax()<<std::endl;
210                    osg::notify(osg::NOTICE)<<"ea.getY()="<<ea.getY()<<std::endl;
211                    osg::notify(osg::NOTICE)<<"ea.getYin()="<<ea.getYmin()<<std::endl;
212                    osg::notify(osg::NOTICE)<<"ea.getYmax()="<<ea.getYmax()<<std::endl;
213
214                    osg::Camera* camera = view->getCamera();
215                    osg::Matrix VP =  camera->getViewMatrix() * camera->getProjectionMatrix();
216
217                    osg::Matrix inverse_VP;
218                    inverse_VP.invert(VP);
219
220                    osg::Vec3d start_eye(ea.getXnormalized(), ea.getYnormalized(), 0.0);
221                    osg::Vec3d end_eye(ea.getXnormalized(), ea.getYnormalized(), 1.0);
222
223                    osg::Vec3d start_world = start_eye * inverse_VP;
224                    osg::Vec3d end_world = start_eye * inverse_VP;
225
226                    osg::notify(osg::NOTICE)<<"start_world="<<start_world<<std::endl;
227                    osg::notify(osg::NOTICE)<<"end_world="<<end_world<<std::endl;
228
229                    transform->setPosition(end_world);
230
231                    transform->setNodeMask(0xffffffff);
232
233                    break;
234                }
235                case(osgGA::GUIEventAdapter::KEYDOWN):
236                {
237                    if (ea.getKey()=='c')
238                    {
239                        for(unsigned int i=0; i< transform->getNumChildren(); ++i)
240                        {
241                            osg::Node* node = transform->getChild(i);
242                            node->setNodeMask(
243                                node->getNodeMask()!=0 ?
244                                0 :
245                                0xffffff);
246                        }
247                    }
248                    break;
249                }
250                default:
251                    break;
252            }
253            return false;
254        }
255
256        virtual void accept(osgGA::GUIEventHandlerVisitor& v)
257        {
258            v.visit(*this);
259        }
260
261};
262
263osg::Node* createCursorSubgraph(const std::string& filename, float size)
264{
265    osg::Geode* geode = new osg::Geode;
266
267    size = 20.0f;
268
269    osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(-size*0.5f,-size*0.5f,0.0f),osg::Vec3(size,0.0f,0.0f),osg::Vec3(0.0f,size,0.0f));
270
271    osg::Image* image = osgDB::readImageFile(osgDB::findDataFile(filename));
272    if (image)
273    {
274        osg::StateSet* stateset = geom->getOrCreateStateSet();
275        stateset->setTextureAttributeAndModes(0, new osg::Texture2D(image),osg::StateAttribute::ON);
276        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
277        // stateset->setMode(GL_DEPTH_TEST,osg::StateAttribute::OFF);
278        stateset->setRenderBinDetails(1000, "DepthSortedBin");
279    }
280
281    geode->addDrawable(geom);
282
283    osg::AutoTransform* transform = new osg::AutoTransform;
284    transform->setAutoRotateMode(osg::AutoTransform::ROTATE_TO_CAMERA);
285    transform->setAutoScaleToScreen(true);
286
287    transform->addChild(geode);
288
289    transform->setEventCallback(new FollowMouseCallback());
290
291    return transform;
292
293}
294#else
295class FollowMouseCallback: public osgGA::GUIEventHandler
296{
297    public:
298   
299        virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&, osg::Object* object, osg::NodeVisitor*)
300        {
301
302            switch(ea.getEventType())
303            {
304                case(osgGA::GUIEventAdapter::MOVE):
305                case(osgGA::GUIEventAdapter::DRAG):
306                {
307                    osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
308                    if (camera)
309                    {
310                        double x = ea.getXnormalized();
311                        double y = ea.getYnormalized();
312
313                        camera->setViewMatrix(osg::Matrixd::translate(x,y,0.0));
314                    }
315                    break;
316                }
317                case(osgGA::GUIEventAdapter::KEYDOWN):
318                {
319                    if (ea.getKey()=='c')
320                    {
321                        osg::Camera* camera = dynamic_cast<osg::Camera*>(object);
322                        if (camera)
323                        {
324                            for(unsigned int i=0; i< camera->getNumChildren(); ++i)
325                            {
326                                osg::Node* node = camera->getChild(i);
327                                node->setNodeMask(
328                                    node->getNodeMask()!=0 ?
329                                    0 :
330                                    0xffffff);
331                            }
332                        }
333                    }
334                    break;
335                }
336                default:
337                    break;
338            }
339            return false;
340        }
341               
342        virtual void accept(osgGA::GUIEventHandlerVisitor& v)
343        {
344            v.visit(*this);
345        }
346
347};
348 
349osg::Node* createCursorSubgraph(const std::string& filename, float size)
350{
351    osg::Geode* geode = new osg::Geode;
352
353    osg::Geometry* geom = osg::createTexturedQuadGeometry(osg::Vec3(-size*0.5f,-size*0.5f,0.0f),osg::Vec3(size,0.0f,0.0f),osg::Vec3(0.0f,size,0.0f));
354
355    osg::Image* image = osgDB::readImageFile(osgDB::findDataFile(filename));
356    if (image)
357    {
358        osg::StateSet* stateset = geom->getOrCreateStateSet();
359        stateset->setTextureAttributeAndModes(0, new osg::Texture2D(image),osg::StateAttribute::ON);
360        stateset->setMode(GL_BLEND,osg::StateAttribute::ON);
361        stateset->setRenderBinDetails(1000, "DepthSortedBin");
362    }
363   
364    geode->addDrawable(geom);
365   
366    osg::Camera* camera = new osg::Camera;
367
368    // set the projection matrix
369    camera->setProjectionMatrix(osg::Matrix::ortho2D(-1,1,-1,1));
370
371    // set the view matrix   
372    camera->setReferenceFrame(osg::Transform::ABSOLUTE_RF);
373    camera->setViewMatrix(osg::Matrix::identity());
374
375    // only clear the depth buffer
376    camera->setClearMask(GL_DEPTH_BUFFER_BIT);
377
378    // draw subgraph after main camera view.
379    camera->setRenderOrder(osg::CameraNode::NESTED_RENDER);
380
381    camera->addChild(geode);
382   
383    camera->setEventCallback(new FollowMouseCallback());
384   
385    return camera;
386
387}
388#endif
389
390
391enum P3DApplicationType
392{
393    VIEWER,
394    MASTER,
395    SLAVE
396};
397
398
399
400int main( int argc, char **argv )
401{
402    // use an ArgumentParser object to manage the program arguments.
403    osg::ArgumentParser arguments(&argc,argv);
404   
405    // set up the usage document, in case we need to print out how to use this program.
406    arguments.getApplicationUsage()->setApplicationName(arguments.getApplicationName());
407    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the application for presenting 3D interactive slide shows.");
408    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] filename ...");
409    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
410    arguments.getApplicationUsage()->addCommandLineOption("-a","Turn auto stepping on by default");
411    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time duration in seconds between layers/slides");
412    arguments.getApplicationUsage()->addCommandLineOption("-s <float> <float> <float>","width, height, distance and of the screen away from the viewer");
413    arguments.getApplicationUsage()->addCommandLineOption("--viewer","Start Present3D as the viewer version.");
414    arguments.getApplicationUsage()->addCommandLineOption("--authoring","Start Present3D as the authoring version, license required.");
415    arguments.getApplicationUsage()->addCommandLineOption("--master","Start Present3D as the master version, license required.");
416    arguments.getApplicationUsage()->addCommandLineOption("--slave","Start Present3D as the slave version, license required.");
417    arguments.getApplicationUsage()->addCommandLineOption("--publishing","Start Present3D as the publishing version, license required.");
418    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.");
419    arguments.getApplicationUsage()->addCommandLineOption("--targetFrameRate","Set the target frame rate, defaults to 80Hz.");
420    arguments.getApplicationUsage()->addCommandLineOption("--version","Report the Present3D version.");
421    arguments.getApplicationUsage()->addCommandLineOption("--print <filename>","Print out slides to a series of image files.");
422    arguments.getApplicationUsage()->addCommandLineOption("--html <filename>","Print out slides to a series of html & image files.");
423    arguments.getApplicationUsage()->addCommandLineOption("--loop","Switch on looping of presentation.");
424    arguments.getApplicationUsage()->addCommandLineOption("--devices","Print the Video input capability via QuickTime and exit.");
425
426    // add alias from xml to p3d to provide backwards compatibility for old p3d files.
427    osgDB::Registry::instance()->addFileExtensionAlias("xml","p3d");
428
429    // if user requests devices video capability.
430    if (arguments.read("-devices") || arguments.read("--devices"))
431    {
432        // Force load QuickTime plugin, probe video capability, exit
433        osgDB::readImageFile("devices.live");
434        return 1;
435    }
436
437
438    // read any env vars from presentations before we create viewer to make sure the viewer
439    // utilises these env vars
440    if (p3d::readEnvVars(arguments))
441    {
442        osg::DisplaySettings::instance()->readEnvironmentalVariables();
443    }
444
445
446#ifdef USE_SDL
447    SDLIntegration sdlIntegration;
448   
449    osg::notify(osg::INFO)<<"USE_SDL"<<std::endl;
450#endif   
451   
452    bool doSetViewer = true;
453    std::string configurationFile;
454
455    // check env vars for configuration file
456    const char* str = getenv("PRESENT3D_CONFIG_FILE");
457    if (!str) str = getenv("OSG_CONFIG_FILE");
458    if (str) configurationFile = str;
459
460    // check command line parameters for configuration file.
461    while (arguments.read("-c",configurationFile)) {}
462
463    osg::Vec4 clearColor(0.0f,0.0f,0.0f,0.0f);
464   
465    while (arguments.read("--clear-color",clearColor[0],clearColor[1],clearColor[2],clearColor[3])) {}
466
467    std::string filename;
468    if (arguments.read("--spell-check",filename))
469    {
470        p3d::SpellChecker spellChecker;
471        spellChecker.checkP3dXml(filename);
472        return 1;
473    }
474
475    if (arguments.read("--strip-text",filename))
476    {
477        p3d::XmlPatcher patcher;
478        // patcher.stripP3dXml(filename, osg::notify(osg::NOTICE));
479
480        osg::ref_ptr<osgDB::XmlNode> newNode = patcher.simplifyP3dXml(filename);
481        if (newNode.valid())
482        {
483            newNode->write(std::cout);
484        }
485        return 1;
486    }
487
488    std::string lhs_filename, rhs_filename;
489    if (arguments.read("--merge",lhs_filename, rhs_filename))
490    {
491        p3d::XmlPatcher patcher;
492        osg::ref_ptr<osgDB::XmlNode> newNode = patcher.mergeP3dXml(lhs_filename, rhs_filename);
493        if (newNode.valid())
494        {
495            newNode->write(std::cout);
496        }
497        return 1;
498    }
499
500
501    // construct the viewer.
502    osgViewer::Viewer viewer(arguments);
503   
504    // set clear colour to black by default.
505    viewer.getCamera()->setClearColor(clearColor);
506
507    if (!configurationFile.empty())
508    {
509        viewer.readConfiguration(configurationFile);
510        doSetViewer = false;
511    }
512   
513    // set up stereo masks
514    viewer.getCamera()->setCullMask(0xffffffff);
515    viewer.getCamera()->setCullMaskLeft(0x00000001);
516    viewer.getCamera()->setCullMaskRight(0x00000002);   
517
518    // set up the camera manipulators.
519    {
520        osg::ref_ptr<osgGA::KeySwitchMatrixManipulator> keyswitchManipulator = new osgGA::KeySwitchMatrixManipulator;
521
522        keyswitchManipulator->addMatrixManipulator( '1', "Trackball", new osgGA::TrackballManipulator() );
523        keyswitchManipulator->addMatrixManipulator( '2', "Flight", new osgGA::FlightManipulator() );
524        keyswitchManipulator->addMatrixManipulator( '3', "Drive", new osgGA::DriveManipulator() );
525        keyswitchManipulator->addMatrixManipulator( '4', "Terrain", new osgGA::TerrainManipulator() );
526
527        std::string pathfile;
528        char keyForAnimationPath = '5';
529        while (arguments.read("-p",pathfile))
530        {
531            osgGA::AnimationPathManipulator* apm = new osgGA::AnimationPathManipulator(pathfile);
532            if (apm || !apm->valid())
533            {
534                unsigned int num = keyswitchManipulator->getNumMatrixManipulators();
535                keyswitchManipulator->addMatrixManipulator( keyForAnimationPath, "Path", apm );
536                keyswitchManipulator->selectMatrixManipulator(num);
537                ++keyForAnimationPath;
538            }
539        }
540
541        viewer.setCameraManipulator( keyswitchManipulator.get() );
542    }
543
544    // add the state manipulator
545    viewer.addEventHandler( new osgGA::StateSetManipulator(viewer.getCamera()->getOrCreateStateSet()) );
546
547    // add the state manipulator
548    viewer.addEventHandler( new osgViewer::StatsHandler() );
549
550    viewer.addEventHandler( new osgViewer::WindowSizeHandler() );
551
552    // neeed to address.
553    // viewer.getScene()->getUpdateVisitor()->setTraversalMode(osg::NodeVisitor::TRAVERSE_ACTIVE_CHILDREN);
554
555
556    const char* p3dCursor = getenv("P3D_CURSOR");
557    std::string cursorFileName( p3dCursor ? p3dCursor : "");
558    while (arguments.read("--cursor",cursorFileName)) {}
559
560
561    while (arguments.read("--set-viewer")) { doSetViewer = true; }
562   
563    while (arguments.read("--no-set-viewer")) { doSetViewer = false; }
564   
565
566    // cluster related entries.
567    int socketNumber=8100;
568    while (arguments.read("-n",socketNumber)) {}
569
570    float camera_fov=-1.0f;
571    while (arguments.read("-f",camera_fov)) {}
572
573    float camera_offset=45.0f;
574    while (arguments.read("-o",camera_offset)) {}
575
576
577    std::string exportName;
578    while (arguments.read("--print",exportName)) {}
579
580    while (arguments.read("--html",exportName)) {}
581
582    // read any time delay argument.
583    float timeDelayBetweenSlides = 1.0f;
584    while (arguments.read("-d",timeDelayBetweenSlides)) {}
585
586    bool autoSteppingActive = false;
587    while (arguments.read("-a")) autoSteppingActive = true;
588
589    bool loopPresentation = false;
590    while (arguments.read("--loop")) loopPresentation = true;
591
592
593    // register the slide event handler - which moves the presentation from slide to slide, layer to layer.
594    osgPresentation::SlideEventHandler* seh = new osgPresentation::SlideEventHandler(&viewer);
595    viewer.addEventHandler(seh);
596
597    seh->setAutoSteppingActive(autoSteppingActive);
598    seh->setTimeDelayBetweenSlides(timeDelayBetweenSlides);
599    seh->setLoopPresentation(loopPresentation);
600
601    double targetFrameRate = 80.0;
602    while (arguments.read("--targetFrameRate",targetFrameRate)) {}
603
604
605    // set the time delay
606    float timeDelayOnNewSlideWithMovies = 0.4f;
607    while (arguments.read("--timeDelayOnNewSlideWithMovies",timeDelayOnNewSlideWithMovies)) {}
608    seh->setTimeDelayOnNewSlideWithMovies(timeDelayOnNewSlideWithMovies);
609
610    // set up optimizer options
611    unsigned int optimizer_options = osgUtil::Optimizer::DEFAULT_OPTIMIZATIONS;
612    bool relase_and_compile = false;
613    while (arguments.read("--release-and-compile"))
614    {
615        relase_and_compile = true;
616    }
617    seh->setReleaseAndCompileOnEachNewSlide(relase_and_compile);
618    if (relase_and_compile)
619    {
620        // make sure that imagery stays around after being applied to textures.
621        viewer.getDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,false);
622        optimizer_options &= ~osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
623    }
624//
625//     osgDB::Registry::instance()->getOrCreateDatabasePager()->setUnrefImageDataAfterApplyPolicy(true,false);
626//     optimizer_options &= ~osgUtil::Optimizer::OPTIMIZE_TEXTURE_SETTINGS;
627//     osg::Texture::getTextureObjectManager()->setExpiryDelay(0.0f);
628//     osgDB::Registry::instance()->getOrCreateDatabasePager()->setExpiryDelay(1.0f);
629
630    // register the handler for modifying the point size
631    PointsEventHandler* peh = new PointsEventHandler;
632    viewer.addEventHandler(peh);
633   
634    // osg::DisplaySettings::instance()->setSplitStereoAutoAjustAspectRatio(false);
635
636    float width = osg::DisplaySettings::instance()->getScreenWidth();
637    float height = osg::DisplaySettings::instance()->getScreenHeight();
638    float distance = osg::DisplaySettings::instance()->getScreenDistance();
639    bool sizesSpecified = false;
640    while (arguments.read("-s", width, height, distance))
641    {
642        sizesSpecified = true;
643       
644        osg::DisplaySettings::instance()->setScreenDistance(distance);
645        osg::DisplaySettings::instance()->setScreenHeight(height);
646        osg::DisplaySettings::instance()->setScreenWidth(width);
647    }
648
649    std::string outputFileName;
650    while(arguments.read("--output",outputFileName)) {}
651
652
653    // get details on keyboard and mouse bindings used by the viewer.
654    viewer.getUsage(*arguments.getApplicationUsage());
655
656    // if user request help write it out to cout.
657    if (arguments.read("-h") || arguments.read("--help"))
658    {
659        arguments.getApplicationUsage()->write(osg::notify(osg::NOTICE));
660        return 1;
661    }
662
663    P3DApplicationType P3DApplicationType = VIEWER;
664
665    str = getenv("PRESENT3D_TYPE");
666    if (str)
667    {
668        if (strcmp(str,"viewer")==0) P3DApplicationType = VIEWER;
669        else if (strcmp(str,"master")==0) P3DApplicationType = MASTER;
670        else if (strcmp(str,"slave")==0) P3DApplicationType = SLAVE;
671    }
672       
673    while (arguments.read("--viewer")) { P3DApplicationType = VIEWER; }
674    while (arguments.read("--master")) { P3DApplicationType = MASTER; }
675    while (arguments.read("--slave")) { P3DApplicationType = SLAVE; }
676   
677    while (arguments.read("--version"))
678    {
679        std::string appTypeName = "invalid";
680        switch(P3DApplicationType)
681        {
682            case(VIEWER): appTypeName = "viewer"; break;
683            case(MASTER): appTypeName = "master"; break;
684            case(SLAVE): appTypeName = "slave"; break;
685        }
686
687        osg::notify(osg::NOTICE)<<std::endl;
688        osg::notify(osg::NOTICE)<<"Present3D "<<appTypeName<<" version : "<<s_version<<std::endl;
689        osg::notify(osg::NOTICE)<<std::endl;
690
691        return 0;
692    }
693
694    // any option left unread are converted into errors to write out later.
695    //arguments.reportRemainingOptionsAsUnrecognized();
696
697    // report any errors if they have ocured when parsing the program aguments.
698    if (arguments.errors())
699    {
700        arguments.writeErrorMessages(osg::notify(osg::INFO));
701        return 1;
702    }
703
704
705    // read files name from arguments.
706    p3d::FileNameList xmlFiles, normalFiles;
707    if (!p3d::getFileNames(arguments, xmlFiles, normalFiles))
708    {
709        osg::notify(osg::NOTICE)<<std::endl;
710        osg::notify(osg::NOTICE)<<"No file specified, please specify and file to load."<<std::endl;
711        osg::notify(osg::NOTICE)<<std::endl;
712        return 1;
713    }
714
715
716
717    bool viewerInitialized = false;
718    if (!xmlFiles.empty())
719    {
720        osg::ref_ptr<osg::Node> holdingModel = p3d::readHoldingSlide(xmlFiles.front());
721
722        if (holdingModel.valid())
723        {
724            viewer.setSceneData(holdingModel.get());
725
726            seh->selectSlide(0);
727
728            if (!viewerInitialized)
729            {
730                // pass the global stateset to the point event handler so that it can
731                // alter the point size of all points in the scene.
732                peh->setStateSet(viewer.getCamera()->getOrCreateStateSet());
733
734                // create the windows and run the threads.
735                viewer.realize();
736
737                if (doSetViewer) setViewer(viewer, width, height, distance);
738
739                viewerInitialized = true;
740            }
741
742            seh->home();
743
744            // render a frame
745            viewer.frame();
746        }
747    }
748
749    osg::Timer timer;
750    osg::Timer_t start_tick = timer.tick();
751
752
753    osg::ref_ptr<osgDB::ReaderWriter::Options> cacheAllOption = new osgDB::ReaderWriter::Options;
754    cacheAllOption->setObjectCacheHint(osgDB::ReaderWriter::Options::CACHE_ALL);
755    osgDB::Registry::instance()->setOptions(cacheAllOption.get());
756
757    // read the scene from the list of file specified commandline args.
758    osg::ref_ptr<osg::Node> loadedModel = p3d::readShowFiles(arguments,cacheAllOption.get()); // osgDB::readNodeFiles(arguments, cacheAllOption.get());
759
760
761    osgDB::Registry::instance()->setOptions( 0 );
762
763
764    // if no model has been successfully loaded report failure.
765    if (!loadedModel)
766    {
767        osg::notify(osg::INFO) << arguments.getApplicationName() <<": No data loaded" << std::endl;
768        return 1;
769    }
770
771    osg::Timer_t end_tick = timer.tick();
772
773    osg::notify(osg::INFO) << "Time to load = "<<timer.delta_s(start_tick,end_tick)<<std::endl;
774
775
776    if (loadedModel->getNumDescriptions()>0)
777    {
778        for(unsigned int i=0; i<loadedModel->getNumDescriptions(); ++i)
779        {
780            const std::string& desc = loadedModel->getDescription(i);
781            if (desc=="loop")
782            {
783                osg::notify(osg::NOTICE)<<"Enabling looping"<<std::endl;
784                seh->setLoopPresentation(true);
785            }
786            else if (desc=="auto")
787            {
788                osg::notify(osg::NOTICE)<<"Enabling auto run"<<std::endl;
789                seh->setAutoSteppingActive(true);
790            }
791        }
792    }
793
794
795#if !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
796
797    // add back in enabling of the GL_ALPHA_TEST to get around the core OSG no longer setting it by default for opaque bins.
798    // the alpha test is required for the volume rendering alpha clipping to work.
799    loadedModel->getOrCreateStateSet()->setMode(GL_ALPHA_TEST, osg::StateAttribute::ON);
800#endif
801
802
803    // optimize the scene graph, remove rendundent nodes and state etc.
804    osgUtil::Optimizer optimizer;
805    optimizer.optimize(loadedModel.get(), optimizer_options);
806
807    if (!cursorFileName.empty())
808    {
809        osg::ref_ptr<osg::Group> group = new osg::Group;
810        group->addChild(loadedModel.get());
811        group->addChild(createCursorSubgraph(cursorFileName, 0.05f));
812       
813        loadedModel = group.get();
814    }
815
816    // set the scene to render
817    viewer.setSceneData(loadedModel.get());
818
819    if (!viewerInitialized)
820    {
821        // pass the global stateset to the point event handler so that it can
822        // alter the point size of all points in the scene.
823        peh->setStateSet(viewer.getCamera()->getOrCreateStateSet());
824
825        // create the windows and run the threads.
826        viewer.realize();
827
828        if (doSetViewer) setViewer(viewer, width, height, distance);
829
830        viewerInitialized = true;
831    }
832
833    if (!cursorFileName.empty())
834    {
835        // have to add a frame in here to avoid problems with X11 threading issue on switching off the cursor
836        // not yet sure why it makes a difference, but it at least fixes the crash that would otherwise occur
837        // under X11.
838        viewer.frame();
839
840        // switch off the cursor
841        osgViewer::Viewer::Windows windows;
842        viewer.getWindows(windows);
843        for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
844            itr != windows.end();
845            ++itr)
846        {
847            (*itr)->useCursor(false);
848        }
849    }
850
851    // pass the model to the slide event handler so it knows which to manipulate.
852    seh->set(loadedModel.get());
853    seh->selectSlide(0);
854
855    seh->home();
856
857    if (!outputFileName.empty())
858    {
859        osgDB::writeNodeFile(*loadedModel,outputFileName);
860        return 0;
861    }
862   
863    osg::Timer_t startOfFrameTick = osg::Timer::instance()->tick();
864    double targetFrameTime = 1.0/targetFrameRate;
865   
866    if (exportName.empty())
867    {
868        // objects for managing the broadcasting and recieving of camera packets.
869        CameraPacket cp;
870        Broadcaster  bc;
871        Receiver     rc;
872        bc.setPort(static_cast<short int>(socketNumber));
873        rc.setPort(static_cast<short int>(socketNumber));
874
875        bool masterKilled = false;
876        DataConverter scratchPad(1024);
877
878        while( !viewer.done() && !masterKilled)
879        {
880            // wait for all cull and draw threads to complete.
881            viewer.advance();
882
883            osg::Timer_t currentTick = osg::Timer::instance()->tick();
884            double deltaTime = osg::Timer::instance()->delta_s(startOfFrameTick, currentTick);
885
886
887            if (deltaTime<targetFrameTime)
888            {
889                OpenThreads::Thread::microSleep(static_cast<unsigned int>((targetFrameTime-deltaTime)*1000000.0));
890            }
891
892            startOfFrameTick =  osg::Timer::instance()->tick();
893
894#if 0           
895            if (kmcb)
896            {
897                double time = kmcb->getTime();
898                viewer.getFrameStamp()->setReferenceTime(time);
899            }
900#endif
901
902#ifdef USE_SDL
903            sdlIntegration.update(viewer);
904#endif
905
906            if (P3DApplicationType==MASTER)
907            {
908                // take camera zero as the guide.
909                osg::Matrix modelview(viewer.getCamera()->getViewMatrix());
910               
911                cp.setPacket(modelview,viewer.getFrameStamp());
912               
913                // cp.readEventQueue(viewer);
914
915                scratchPad.reset();
916                scratchPad.write(cp);
917
918                scratchPad.reset();
919                scratchPad.read(cp);
920
921                bc.setBuffer(scratchPad.startPtr(), scratchPad.numBytes());
922               
923                std::cout << "bc.sync()"<<scratchPad.numBytes()<<std::endl;
924
925                bc.sync();
926            }
927            else if (P3DApplicationType==SLAVE)
928            {
929                rc.setBuffer(scratchPad.startPtr(), scratchPad.numBytes());
930
931                rc.sync();
932               
933                scratchPad.reset();
934                scratchPad.read(cp);
935   
936                // cp.writeEventQueue(viewer);
937
938                if (cp.getMasterKilled())
939                {
940                    std::cout << "Received master killed."<<std::endl;
941                    // break out of while (!done) loop since we've now want to shut down.
942                    masterKilled = true;
943                }
944            }
945
946            // update the scene by traversing it with the the update visitor which will
947            // call all node update callbacks and animations.
948            viewer.eventTraversal();
949
950            // update the scene by traversing it with the the update visitor which will
951            // call all node update callbacks and animations.
952            viewer.updateTraversal();
953
954            if (P3DApplicationType==SLAVE)
955            {
956                osg::Matrix modelview;
957                cp.getModelView(modelview,camera_offset);
958
959                viewer.getCamera()->setViewMatrix(modelview);
960            }
961
962            // fire off the cull and draw traversals of the scene.
963            if(!masterKilled)
964                viewer.renderingTraversals();
965        }
966    }
967    else
968    {
969        ExportHTML::write(seh, viewer, exportName);
970    }
971           
972    return 0;
973}
Note: See TracBrowser for help on using the browser.