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

Revision 11764, 31.8 kB (checked in by robert, 4 years ago)

From Magnus Kessler, "Fix a small typo in present3D usage string"

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