root/OpenSceneGraph/trunk/examples/osgstereoimage/osgstereoimage.cpp @ 13662

Revision 13574, 22.8 kB (checked in by robert, 29 hours ago)

From Alberto Luaces,"the current code uses the preprocessor for generating the plugin path in
a way that when CMAKE_INSTALL_PREFIX contains something along the lines
of

/usr/x86_64-linux-gnu/

it gets substituted as

/usr/x86_64-1-gnu/

that is, the string is preprocessed again, thereby making changes to
anything that matches any defined symbol, as "linux" in this example
(https://bugs.debian.org/cgi-bin/bugreport.cgi?bug=763816).

Quoting that path directly in CMake scripts solves that problem.
"

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* OpenSceneGraph example, osgstereoimage.
2*
3*  Permission is hereby granted, free of charge, to any person obtaining a copy
4*  of this software and associated documentation files (the "Software"), to deal
5*  in the Software without restriction, including without limitation the rights
6*  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
7*  copies of the Software, and to permit persons to whom the Software is
8*  furnished to do so, subject to the following conditions:
9*
10*  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
11*  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
12*  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
13*  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
14*  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
15*  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
16*  THE SOFTWARE.
17*/
18
19#include <osgViewer/Viewer>
20#include <osgDB/fstream>
21#include <osgDB/ReadFile>
22#include <osgDB/WriteFile>
23#include <osgUtil/Optimizer>
24
25#include <osg/ImageStream>
26#include <osg/Geode>
27#include <osg/Notify>
28#include <osg/MatrixTransform>
29#include <osg/Switch>
30#include <osg/TexMat>
31#include <osg/Texture2D>
32
33#include <iostream>
34
35typedef std::vector<std::string> FileList;
36
37#include <osg/Program>
38#include <osg/Shader>
39
40osg::StateSet* createColorToGreyscaleStateSet()
41{
42    osg::StateSet* stateset = new osg::StateSet;
43
44    osg::Program* program = new osg::Program;
45    stateset->setAttribute(program);
46
47    const char* fragSource =
48    {
49        "uniform sampler2D baseTexture;\n"
50        "uniform mat4 colorMatrix;\n"
51        "void main(void)\n"
52        "{\n"
53        "    vec4 color = texture2D( baseTexture, gl_TexCoord[0].st );\n"
54        "    gl_FragColor = colorMatrix * color;\n"
55        "}\n"
56    };
57    program->addShader(new osg::Shader(osg::Shader::FRAGMENT, fragSource));
58
59    stateset->addUniform(new osg::Uniform("baseTexture",0));
60
61    osg::Matrixf colorMatrix(
62        0.3f, 0.3f, 0.3f, 0.0f,
63        0.59f, 0.59f, 0.59f, 0.0f,
64        0.11f, 0.11f, 0.11f, 0.0f,
65        0.0f, 0.0f, 0.0f, 1.0f
66    );
67
68    stateset->addUniform(new osg::Uniform("colorMatrix",colorMatrix));
69
70    return stateset;
71}
72
73
74osg::Geode* createSectorForImage(osg::Image* image, osg::TexMat* texmat, float s,float t, float radius, float height, float length)
75{
76    bool flip = image->getOrigin()==osg::Image::TOP_LEFT;
77
78    int numSegments = 20;
79    float Theta = length/radius;
80    float dTheta = Theta/(float)(numSegments-1);
81
82    float ThetaZero = height*s/(t*radius);
83
84    // set up the texture.
85    osg::Texture2D* texture = new osg::Texture2D;
86    texture->setFilter(osg::Texture2D::MIN_FILTER,osg::Texture2D::LINEAR);
87    texture->setFilter(osg::Texture2D::MAG_FILTER,osg::Texture2D::LINEAR);
88    texture->setWrap(osg::Texture2D::WRAP_S,osg::Texture2D::CLAMP_TO_BORDER);
89    texture->setWrap(osg::Texture2D::WRAP_T,osg::Texture2D::CLAMP_TO_BORDER);
90    texture->setResizeNonPowerOfTwoHint(false);
91    texture->setImage(image);
92
93    // set up the drawstate.
94    osg::StateSet* dstate = new osg::StateSet;
95    dstate->setMode(GL_CULL_FACE,osg::StateAttribute::OFF);
96    dstate->setMode(GL_LIGHTING,osg::StateAttribute::OFF);
97    dstate->setTextureAttributeAndModes(0, texture,osg::StateAttribute::ON);
98    dstate->setTextureAttribute(0, texmat);
99
100    // set up the geoset.
101    osg::Geometry* geom = new osg::Geometry;
102    geom->setStateSet(dstate);
103
104    osg::Vec3Array* coords = new osg::Vec3Array();
105    osg::Vec2Array* tcoords = new osg::Vec2Array();
106
107    int i;
108    float angle = -Theta/2.0f;
109    for(i=0;
110        i<numSegments;
111        ++i, angle+=dTheta)
112    {
113        coords->push_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,height*0.5f)); // top
114        coords->push_back(osg::Vec3(sinf(angle)*radius,cosf(angle)*radius,-height*0.5f)); // bottom.
115
116        tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f, flip ? 0.0f : 1.0f)); // top
117        tcoords->push_back(osg::Vec2(angle/ThetaZero+0.5f, flip ? 1.0f : 0.0f)); // bottom.
118
119    }
120
121    osg::Vec4Array* colors = new osg::Vec4Array();
122    colors->push_back(osg::Vec4(1.0f,1.0f,1.0f,1.0f));
123
124    osg::DrawArrays* elements = new osg::DrawArrays(osg::PrimitiveSet::QUAD_STRIP,0,coords->size());
125
126
127
128    geom->setVertexArray(coords);
129    geom->setTexCoordArray(0,tcoords);
130    geom->setColorArray(colors, osg::Array::BIND_OVERALL);
131
132    geom->addPrimitiveSet(elements);
133
134    // set up the geode.
135    osg::Geode* geode = new osg::Geode;
136    geode->addDrawable(geom);
137
138    return geode;
139
140}
141
142osg::Group * loadImages(std::string image1, std::string image2, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length)
143{
144    osg::ref_ptr<osg::Image> imageLeft = osgDB::readImageFile(image1);
145    osg::ref_ptr<osg::Image> imageRight = osgDB::readImageFile(image2);
146    if (imageLeft.valid() && imageRight.valid())
147    {
148        osg::ImageStream* streamLeft = dynamic_cast<osg::ImageStream*>(imageLeft.get());
149        if (streamLeft) streamLeft->play();
150
151        osg::ImageStream* streamRight = dynamic_cast<osg::ImageStream*>(imageRight.get());
152        if (streamRight) streamRight->play();
153
154
155        float average_s = (imageLeft->s()+imageRight->s())*0.5f;
156        float average_t = (imageLeft->t()+imageRight->t())*0.5f;
157        osg::Geode* geodeLeft = createSectorForImage(imageLeft.get(),texmatLeft,average_s,average_t, radius, height, length);
158        geodeLeft->setNodeMask(0x01);
159
160        osg::Geode* geodeRight = createSectorForImage(imageRight.get(),texmatRight,average_s,average_t, radius, height, length);
161        geodeRight->setNodeMask(0x02);
162
163        osg::Group * imageGroup = new osg::Group;
164
165        imageGroup->addChild(geodeLeft);
166        imageGroup->addChild(geodeRight);
167        return imageGroup;
168    }
169    else
170    {
171        std::cout << "Warning: Unable to load both image files, '"<<image1<<"' & '"<<image2<<"', required for stereo imaging."<<std::endl;
172        return 0;
173    }
174}
175
176// create a switch containing a set of child each containing a
177// stereo image pair.
178osg::Switch* createScene(FileList fileList, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length)
179{
180    osg::Switch* sw = new osg::Switch;
181
182    // load the images.
183    for(unsigned int i=0;i+1<fileList.size();i+=2)
184    {
185        osg::Group * imageGroup = loadImages(fileList[i],fileList[i+1],texmatLeft,texmatRight, radius,  height, length);
186        if (imageGroup) sw->addChild(imageGroup);
187    }
188
189
190    if (sw->getNumChildren()>0)
191    {
192        // select first child.
193        sw->setSingleChildOn(0);
194    }
195
196    return sw;
197}
198
199class SlideEventHandler : public osgGA::GUIEventHandler
200{
201public:
202
203    SlideEventHandler();
204
205    META_Object(osgStereImageApp,SlideEventHandler);
206
207
208    void set(osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float timePerSlide, bool autoSteppingActive);
209
210    void set(FileList fileList, osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length, float timePerSlide, bool autoSteppingActive);
211
212
213    virtual bool handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&);
214
215    virtual void getUsage(osg::ApplicationUsage& usage) const;
216
217    virtual void operator()(osg::Node* node, osg::NodeVisitor* nv);
218
219    void nextSlide();
220
221    void previousSlide();
222
223    void scaleImage(float s);
224
225    void offsetImage(float ds,float dt);
226
227    void rotateImage(float rx,float ry);
228
229    void initTexMatrices();
230
231protected:
232
233    ~SlideEventHandler() {}
234    SlideEventHandler(const SlideEventHandler&,const osg::CopyOp&) {}
235
236    osg::ref_ptr<osg::Switch>   _switch;
237    osg::ref_ptr<osg::TexMat>   _texmatLeft;
238    osg::ref_ptr<osg::TexMat>   _texmatRight;
239    float                        _radius;
240    float                        _height;
241    float                        _length;
242    bool                        _firstTraversal;
243    unsigned int                _activeSlide;
244    double                      _previousTime;
245    double                      _timePerSlide;
246    bool                        _autoSteppingActive;
247    float                       _initSeperationX;
248    float                       _currentSeperationX;
249    float                       _initSeperationY;
250    float                       _currentSeperationY;
251    FileList                     _fileList;
252
253};
254
255SlideEventHandler::SlideEventHandler():
256    _switch(0),
257    _texmatLeft(0),
258    _texmatRight(0),
259    _firstTraversal(true),
260    _activeSlide(0),
261    _previousTime(-1.0f),
262    _timePerSlide(5.0),
263    _autoSteppingActive(false)
264{
265}
266
267void SlideEventHandler::set(osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float timePerSlide, bool autoSteppingActive)
268{
269    _switch = sw;
270    _switch->setUpdateCallback(this);
271
272    _texmatLeft = texmatLeft;
273    _texmatRight = texmatRight;
274
275    _timePerSlide = timePerSlide;
276    _autoSteppingActive = autoSteppingActive;
277
278    _initSeperationX = offsetX;
279    _currentSeperationX = _initSeperationX;
280
281    _initSeperationY = offsetY;
282    _currentSeperationY = _initSeperationY;
283
284    initTexMatrices();
285
286}
287
288void SlideEventHandler::set(FileList fileList, osg::Switch* sw, float offsetX, float offsetY, osg::TexMat* texmatLeft, osg::TexMat* texmatRight, float radius, float height, float length, float timePerSlide, bool autoSteppingActive)
289{
290    _switch = sw;
291    _switch->setUpdateCallback(this);
292    _fileList=FileList(fileList);
293
294    osg::ref_ptr<osg::Group> imageGroup = loadImages(fileList[0],fileList[1],texmatLeft,texmatRight, radius,  height, length);
295    if (imageGroup.get())_switch->addChild(imageGroup.get());
296
297    _texmatLeft = texmatLeft;
298    _texmatRight = texmatRight;
299
300    _radius=radius;
301    _height=height;
302    _length=length;
303
304    _timePerSlide = timePerSlide;
305    _autoSteppingActive = autoSteppingActive;
306
307    _initSeperationX = offsetX;
308    _currentSeperationX = _initSeperationX;
309
310    _initSeperationY = offsetY;
311    _currentSeperationY = _initSeperationY;
312
313    initTexMatrices();
314}
315
316
317bool SlideEventHandler::handle(const osgGA::GUIEventAdapter& ea,osgGA::GUIActionAdapter&)
318{
319    switch(ea.getEventType())
320    {
321        case(osgGA::GUIEventAdapter::KEYDOWN):
322        {
323            if (ea.getKey()=='a')
324            {
325                _autoSteppingActive = !_autoSteppingActive;
326                _previousTime = ea.getTime();
327                return true;
328            }
329            else if ((ea.getKey()=='n') || (ea.getKey()==osgGA::GUIEventAdapter::KEY_Right))
330            {
331                nextSlide();
332                return true;
333            }
334            else if ((ea.getKey()=='p') || (ea.getKey()==osgGA::GUIEventAdapter::KEY_Left))
335            {
336                previousSlide();
337                return true;
338            }
339            else if ((ea.getKey()=='w') || (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Add))
340            {
341                scaleImage(0.99f);
342                return true;
343            }
344            else if ((ea.getKey()=='s') || (ea.getKey()==osgGA::GUIEventAdapter::KEY_KP_Subtract))
345            {
346                scaleImage(1.01f);
347                return true;
348            }
349            else if (ea.getKey()=='j')
350            {
351                offsetImage(-0.001f,0.0f);
352                return true;
353            }
354            else if (ea.getKey()=='k')
355            {
356                offsetImage(0.001f,0.0f);
357                return true;
358            }
359            else if (ea.getKey()=='i')
360            {
361                offsetImage(0.0f,-0.001f);
362                return true;
363            }
364            else if (ea.getKey()=='m')
365            {
366                offsetImage(0.0f,0.001f);
367                return true;
368            }
369            else if (ea.getKey()==' ')
370            {
371                initTexMatrices();
372                return true;
373            }
374            return false;
375        }
376        case(osgGA::GUIEventAdapter::DRAG):
377        case(osgGA::GUIEventAdapter::MOVE):
378        {
379            static float px = ea.getXnormalized();
380            static float py = ea.getYnormalized();
381
382            float dx = ea.getXnormalized()-px;
383            float dy = ea.getYnormalized()-py;
384
385            px = ea.getXnormalized();
386            py = ea.getYnormalized();
387
388            rotateImage(dx,dy);
389
390            return true;
391        }
392
393        default:
394            return false;
395    }
396}
397
398void SlideEventHandler::getUsage(osg::ApplicationUsage& usage) const
399{
400    usage.addKeyboardMouseBinding("Space","Reset the image position to center");
401    usage.addKeyboardMouseBinding("a","Toggle on/off the automatic advancement for image to image");
402    usage.addKeyboardMouseBinding("n","Advance to next image");
403    usage.addKeyboardMouseBinding("p","Move to previous image");
404    usage.addKeyboardMouseBinding("q","Zoom into the image");
405    usage.addKeyboardMouseBinding("a","Zoom out of the image");
406    usage.addKeyboardMouseBinding("j","Reduce horizontal offset");
407    usage.addKeyboardMouseBinding("k","Increase horizontal offset");
408    usage.addKeyboardMouseBinding("m","Reduce vertical offset");
409    usage.addKeyboardMouseBinding("i","Increase vertical offset");
410}
411
412void SlideEventHandler::operator()(osg::Node* node, osg::NodeVisitor* nv)
413{
414    if (_autoSteppingActive && nv->getFrameStamp())
415    {
416        double time = nv->getFrameStamp()->getSimulationTime();
417
418        if (_firstTraversal)
419        {
420            _firstTraversal = false;
421            _previousTime = time;
422        }
423        else if (time-_previousTime>_timePerSlide)
424        {
425            _previousTime = time;
426
427            nextSlide();
428        }
429
430    }
431
432    traverse(node,nv);
433}
434
435void SlideEventHandler::nextSlide()
436{
437
438    if (_switch->getNumChildren()==0) return;
439
440    ++_activeSlide;
441
442    if (_fileList.size()>0) {
443        if (_activeSlide>= _fileList.size()/2 ) _activeSlide = 0;
444        osg::ref_ptr<osg::Group> images = loadImages(_fileList[2*_activeSlide],_fileList[2*_activeSlide+1],_texmatLeft.get(),_texmatRight.get(),_radius,_height,_length);
445        if (images.valid()) _switch->replaceChild(_switch->getChild(0),images.get());
446
447    } else {
448        if (_activeSlide>=_switch->getNumChildren()) _activeSlide = 0;
449
450        _switch->setSingleChildOn(_activeSlide);
451    }
452}
453
454void SlideEventHandler::previousSlide()
455{
456    if (_switch->getNumChildren()==0) return;
457
458    if (_fileList.size()>0) {
459        if (_activeSlide==0) _activeSlide = _fileList.size()/2-1;
460        else --_activeSlide;
461        osg::ref_ptr<osg::Group> images = loadImages(_fileList[2*_activeSlide],_fileList[2*_activeSlide+1],_texmatLeft.get(),_texmatRight.get(),_radius,_height,_length);
462        if (images.valid()) _switch->replaceChild(_switch->getChild(0),images.get());
463    } else {
464        if (_activeSlide==0) _activeSlide = _switch->getNumChildren()-1;
465        else --_activeSlide;
466
467        _switch->setSingleChildOn(_activeSlide);
468    }
469}
470
471void SlideEventHandler::scaleImage(float s)
472{
473    _texmatLeft->setMatrix(_texmatLeft->getMatrix()*osg::Matrix::translate(-0.5f,-0.5f,0.0f)*osg::Matrix::scale(s,s,1.0f)*osg::Matrix::translate(0.5f,0.5f,0.0f));
474    _texmatRight->setMatrix(_texmatRight->getMatrix()*osg::Matrix::translate(-0.5f,-0.5f,0.0f)*osg::Matrix::scale(s,s,1.0f)*osg::Matrix::translate(0.5f,0.5f,0.0f));
475}
476
477void SlideEventHandler::offsetImage(float ds,float dt)
478{
479    _currentSeperationX+=ds;
480    _currentSeperationY+=dt;
481    osg::notify(osg::NOTICE)<<"image offset x = "<<_currentSeperationX<<"  y ="<<_currentSeperationY<<std::endl;
482    _texmatLeft->setMatrix(_texmatLeft->getMatrix()*osg::Matrix::translate(ds,dt,0.0f));
483    _texmatRight->setMatrix(_texmatRight->getMatrix()*osg::Matrix::translate(-ds,-dt,0.0f));
484}
485
486void SlideEventHandler::rotateImage(float rx,float ry)
487{
488    const float scale = 0.5f;
489    _texmatLeft->setMatrix(_texmatLeft->getMatrix()*osg::Matrix::translate(-rx*scale,-ry*scale,0.0f));
490    _texmatRight->setMatrix(_texmatRight->getMatrix()*osg::Matrix::translate(-rx*scale,-ry*scale,0.0f));
491}
492
493void SlideEventHandler::initTexMatrices()
494{
495    _texmatLeft->setMatrix(osg::Matrix::translate(_initSeperationX,_initSeperationY,0.0f));
496    _texmatRight->setMatrix(osg::Matrix::translate(-_initSeperationX,-_initSeperationY,0.0f));
497}
498
499
500
501int main( int argc, char **argv )
502{
503    // use an ArgumentParser object to manage the program arguments.
504    osg::ArgumentParser arguments(&argc,argv);
505
506    // set up the usage document, in case we need to print out how to use this program.
507    arguments.getApplicationUsage()->setDescription(arguments.getApplicationName()+" is the example which demonstrates use node masks to create stereo images.");
508    arguments.getApplicationUsage()->setCommandLineUsage(arguments.getApplicationName()+" [options] image_file_left_eye image_file_right_eye");
509    arguments.getApplicationUsage()->addCommandLineOption("-d <float>","Time delay in seconds between the display of successive image pairs when in auto advance mode.");
510    arguments.getApplicationUsage()->addCommandLineOption("-a","Enter auto advance of image pairs on start up.");
511    arguments.getApplicationUsage()->addCommandLineOption("-x <float>","Horizontal offset of left and right images.");
512    arguments.getApplicationUsage()->addCommandLineOption("-y <float>","Vertical offset of left and right images.");
513    arguments.getApplicationUsage()->addCommandLineOption("--disk","Keep images on disk");
514    arguments.getApplicationUsage()->addCommandLineOption("-files <filename>","Load filenames from a file");
515    arguments.getApplicationUsage()->addCommandLineOption("-h or --help","Display this information");
516    arguments.getApplicationUsage()->addCommandLineOption("--SingleThreaded","Select SingleThreaded threading model for viewer.");
517    arguments.getApplicationUsage()->addCommandLineOption("--CullDrawThreadPerContext","Select CullDrawThreadPerContext threading model for viewer.");
518    arguments.getApplicationUsage()->addCommandLineOption("--DrawThreadPerContext","Select DrawThreadPerContext threading model for viewer.");
519    arguments.getApplicationUsage()->addCommandLineOption("--CullThreadPerCameraDrawThreadPerContext","Select CullThreadPerCameraDrawThreadPerContext threading model for viewer.");
520
521
522    // construct the viewer.
523    osgViewer::Viewer viewer(arguments);
524
525    // register the handler to add keyboard and mouse handling.
526    SlideEventHandler* seh = new SlideEventHandler();
527    viewer.addEventHandler(seh);
528
529    // read any time delay argument.
530    float timeDelayBetweenSlides = 5.0f;
531    while (arguments.read("-d",timeDelayBetweenSlides)) {}
532
533    bool autoSteppingActive = false;
534    while (arguments.read("-a")) autoSteppingActive = true;
535
536    float offsetX=0.0f;
537    while (arguments.read("-x",offsetX)) {}
538
539    float offsetY=0.0f;
540    while (arguments.read("-y",offsetY)) {}
541
542    bool onDisk=false;
543    while (arguments.read("--disk")) { onDisk=true;}
544
545    std::string filename="";
546    FileList fileList;
547    // extract the filenames from the a file, one filename per line.
548    while (arguments.read("-files",filename)) {
549        osgDB::ifstream is(filename.c_str());
550        if (is) {
551                std::string line;
552                while (std::getline(is,line,'\n')) fileList.push_back(line);
553                is.close();
554            }
555
556    }
557
558    // if user request help write it out to cout.
559    if (arguments.read("-h") || arguments.read("--help"))
560    {
561        arguments.getApplicationUsage()->write(std::cout);
562        return 1;
563    }
564
565    osgViewer::Viewer::ThreadingModel threading = osgViewer::Viewer::SingleThreaded;
566    while (arguments.read("--SingleThreaded")) threading = osgViewer::Viewer::SingleThreaded;
567    while (arguments.read("--CullDrawThreadPerContext")) threading = osgViewer::Viewer::CullDrawThreadPerContext;
568    while (arguments.read("--DrawThreadPerContext")) threading = osgViewer::Viewer::DrawThreadPerContext;
569    while (arguments.read("--CullThreadPerCameraDrawThreadPerContext")) threading = osgViewer::Viewer::CullThreadPerCameraDrawThreadPerContext;
570
571    viewer.setThreadingModel(threading);
572
573    // any option left unread are converted into errors to write out later.
574    arguments.reportRemainingOptionsAsUnrecognized();
575
576    // report any errors if they have occurred when parsing the program arguments.
577    if (arguments.errors())
578    {
579        arguments.writeErrorMessages(std::cout);
580        return 1;
581    }
582
583    // extract the filenames from the arguments list.
584    for(int pos=1;pos<arguments.argc();++pos)
585    {
586        if (arguments.isString(pos)) fileList.push_back(arguments[pos]);
587    }
588
589    if (fileList.empty())
590    {
591        fileList.push_back("Images/dog_left_eye.jpg");
592         fileList.push_back("Images/dog_right_eye.jpg");
593    }
594    else if (fileList.size()<2)
595    {
596        arguments.getApplicationUsage()->write(std::cout,osg::ApplicationUsage::COMMAND_LINE_OPTION);
597        return 1;
598    }
599
600    // now the windows have been realized we switch off the cursor to prevent it
601    // distracting the people seeing the stereo images.
602    double fovy, aspectRatio, zNear, zFar;
603    viewer.getCamera()->getProjectionMatrixAsPerspective(fovy, aspectRatio, zNear, zFar);
604
605    float radius = 1.0f;
606    float height = 2*radius*tan(osg::DegreesToRadians(fovy)*0.5f);
607    float length = osg::PI*radius;  // half a cylinder.
608
609    // use a texture matrix to control the placement of the image.
610    osg::TexMat* texmatLeft = new osg::TexMat;
611    osg::TexMat* texmatRight = new osg::TexMat;
612
613    // creat the scene from the file list.
614    osg::ref_ptr<osg::Switch> rootNode;
615    if (!onDisk)  rootNode = createScene(fileList,texmatLeft,texmatRight,radius,height,length);
616    else rootNode=new osg::Switch();
617
618    //osgDB::writeNodeFile(*rootNode,"test.osgt");
619
620
621
622    viewer.getCamera()->setCullMask(0xffffffff);
623    viewer.getCamera()->setCullMaskLeft(0x00000001);
624    viewer.getCamera()->setCullMaskRight(0x00000002);
625
626    // set up the use of stereo by default.
627    osg::DisplaySettings::instance()->setStereo(true);
628
629    if (osg::DisplaySettings::instance()->getStereoMode()==osg::DisplaySettings::ANAGLYPHIC)
630    {
631        rootNode->setStateSet(createColorToGreyscaleStateSet());
632    }
633
634
635    // set the scene to render
636    viewer.setSceneData(rootNode.get());
637
638
639    // create the windows and run the threads.
640    viewer.realize();
641
642
643    // switch off the cursor
644    osgViewer::Viewer::Windows windows;
645    viewer.getWindows(windows);
646    for(osgViewer::Viewer::Windows::iterator itr = windows.begin();
647        itr != windows.end();
648        ++itr)
649    {
650        (*itr)->useCursor(false);
651    }
652
653    viewer.setFusionDistance(osgUtil::SceneView::USE_FUSION_DISTANCE_VALUE,radius);
654
655    // set up the SlideEventHandler.
656    if (onDisk) seh->set(fileList,rootNode.get(),offsetX,offsetY,texmatLeft,texmatRight,radius,height,length,timeDelayBetweenSlides,autoSteppingActive);
657    else seh->set(rootNode.get(),offsetX,offsetY,texmatLeft,texmatRight,timeDelayBetweenSlides,autoSteppingActive);
658
659    osg::Matrix homePosition;
660    homePosition.makeLookAt(osg::Vec3(0.0f,0.0f,0.0f),osg::Vec3(0.0f,1.0f,0.0f),osg::Vec3(0.0f,0.0f,1.0f));
661
662    while( !viewer.done() )
663    {
664        viewer.getCamera()->setViewMatrix(homePosition);
665
666        // fire off the cull and draw traversals of the scene.
667        viewer.frame();
668
669    }
670
671    return 0;
672}
Note: See TracBrowser for help on using the browser.