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

Revision 11905, 32.0 kB (checked in by robert, 3 years ago)

From Wang Rui, "I'm now testing static building of OSG and found a possible bug in the
present3D application. As static-link present3d should depend on
freetype, png, pdf and some other plugins, any mis-compiling of these
plugins will make present3d fail to be built. Some lirbaries like
poppler and cairo are not popular under Windows, so it is very common
that we don't have osgdb_pdf compiled and thus get errors when
building present3d. I've modified the CMakeLists and present3d.cpp to
avoid this problem."

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