root/OpenSceneGraph/trunk/src/osgUtil/SceneView.cpp @ 10602

Revision 10602, 66.7 kB (checked in by robert, 5 years ago)

Removed erroneous inclusion of extra GLBufferObjectManager qualifier that broke Windows build

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* -*-c++-*- OpenSceneGraph - Copyright (C) 1998-2006 Robert Osfield
2 *
3 * This library is open source and may be redistributed and/or modified under 
4 * the terms of the OpenSceneGraph Public License (OSGPL) version 0.0 or
5 * (at your option) any later version.  The full license is in LICENSE file
6 * included with this distribution, and on the openscenegraph.org website.
7 *
8 * This library is distributed in the hope that it will be useful,
9 * but WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 * OpenSceneGraph Public License for more details.
12*/
13#include <osgUtil/SceneView>
14#include <osgUtil/UpdateVisitor>
15#include <osgUtil/GLObjectsVisitor>
16
17#include <osg/Timer>
18#include <osg/GLExtensions>
19#include <osg/GLObjects>
20#include <osg/Notify>
21#include <osg/Texture>
22#include <osg/AlphaFunc>
23#include <osg/TexEnv>
24#include <osg/ColorMatrix>
25#include <osg/LightModel>
26#include <osg/CollectOccludersVisitor>
27
28#include <osg/GLU>
29
30using namespace osg;
31using namespace osgUtil;
32
33static const GLubyte patternVertEven[] = {
34    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
35    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
36    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
37    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
38    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
39    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
40    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
41    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
42    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
43    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
44    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
45    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
46    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
47    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
48    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55,
49    0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55, 0x55};
50
51static const GLubyte patternVertOdd[] = {
52    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
53    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
54    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
55    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
56    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
57    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
58    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
59    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
60    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
61    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
62    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
63    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
64    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
65    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
66    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA,
67    0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA, 0xAA};
68
69static const GLubyte patternHorzEven[] = {
70    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
71    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
72    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
73    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
74    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
75    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
76    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
77    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
78    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
79    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
80    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
81    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
82    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
83    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
84    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00,
85    0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00};
86
87// 32 x 32 bit array every row is a horizontal line of pixels
88//  and the (bitwise) columns a vertical line
89//  The following is a checkerboard pattern
90static const GLubyte patternCheckerboard[] = {
91    0x55, 0x55, 0x55, 0x55,
92    0xAA, 0xAA, 0xAA, 0xAA,
93    0x55, 0x55, 0x55, 0x55,
94    0xAA, 0xAA, 0xAA, 0xAA,
95    0x55, 0x55, 0x55, 0x55,
96    0xAA, 0xAA, 0xAA, 0xAA,
97    0x55, 0x55, 0x55, 0x55,
98    0xAA, 0xAA, 0xAA, 0xAA,
99    0x55, 0x55, 0x55, 0x55,
100    0xAA, 0xAA, 0xAA, 0xAA,
101    0x55, 0x55, 0x55, 0x55,
102    0xAA, 0xAA, 0xAA, 0xAA,
103    0x55, 0x55, 0x55, 0x55,
104    0xAA, 0xAA, 0xAA, 0xAA,
105    0x55, 0x55, 0x55, 0x55,
106    0xAA, 0xAA, 0xAA, 0xAA,
107    0x55, 0x55, 0x55, 0x55,
108    0xAA, 0xAA, 0xAA, 0xAA,
109    0x55, 0x55, 0x55, 0x55,
110    0xAA, 0xAA, 0xAA, 0xAA,
111    0x55, 0x55, 0x55, 0x55,
112    0xAA, 0xAA, 0xAA, 0xAA,
113    0x55, 0x55, 0x55, 0x55,
114    0xAA, 0xAA, 0xAA, 0xAA,
115    0x55, 0x55, 0x55, 0x55,
116    0xAA, 0xAA, 0xAA, 0xAA,
117    0x55, 0x55, 0x55, 0x55,
118    0xAA, 0xAA, 0xAA, 0xAA,
119    0x55, 0x55, 0x55, 0x55,
120    0xAA, 0xAA, 0xAA, 0xAA,
121    0x55, 0x55, 0x55, 0x55,
122    0xAA, 0xAA, 0xAA, 0xAA};
123
124SceneView::SceneView(DisplaySettings* ds)
125{
126    _displaySettings = ds;
127
128    _fusionDistanceMode = PROPORTIONAL_TO_SCREEN_DISTANCE;
129    _fusionDistanceValue = 1.0f;
130
131    _lightingMode=NO_SCENEVIEW_LIGHT;
132   
133    _prioritizeTextures = false;
134   
135    setCamera(new Camera);
136    _camera->setViewport(new Viewport);
137    _camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f));
138   
139    _initCalled = false;
140
141    _camera->setDrawBuffer(GL_BACK);
142
143    _requiresFlush = true;
144   
145    _activeUniforms = DEFAULT_UNIFORMS;
146   
147    _previousFrameTime = 0;
148    _previousSimulationTime = 0;
149   
150    _redrawInterlacedStereoStencilMask = true;
151    _interlacedStereoStencilWidth = 0;
152    _interlacedStereoStencilHeight = 0;
153
154    _dynamicObjectCount = 0;
155}
156
157SceneView::SceneView(const SceneView& rhs, const osg::CopyOp& copyop):
158    osg::Object(rhs,copyop),
159    osg::CullSettings(rhs)
160{
161    _displaySettings = rhs._displaySettings;
162
163    _fusionDistanceMode = rhs._fusionDistanceMode;
164    _fusionDistanceValue = rhs._fusionDistanceValue;
165
166    _lightingMode = rhs._lightingMode;
167   
168    _prioritizeTextures = rhs._prioritizeTextures;
169   
170    _camera = rhs._camera;
171    _cameraWithOwnership = rhs._cameraWithOwnership;
172   
173    _initCalled = false;
174
175    _requiresFlush = rhs._requiresFlush;
176   
177    _activeUniforms = rhs._activeUniforms;
178   
179    _previousFrameTime = 0;
180    _previousSimulationTime = 0;
181   
182    _redrawInterlacedStereoStencilMask = rhs._redrawInterlacedStereoStencilMask;
183    _interlacedStereoStencilWidth = rhs._interlacedStereoStencilWidth;
184    _interlacedStereoStencilHeight = rhs._interlacedStereoStencilHeight;
185
186    _dynamicObjectCount = 0;
187}
188
189SceneView::~SceneView()
190{
191}
192
193
194void SceneView::setDefaults(unsigned int options)
195{
196    osg::CullSettings::setDefaults();
197
198    _camera->getProjectionMatrix().makePerspective(50.0f,1.4f,1.0f,10000.0f);
199    _camera->getViewMatrix().makeIdentity();
200
201    if (!_globalStateSet) _globalStateSet = new osg::StateSet;
202    else _globalStateSet->clear();
203
204    if ((options & HEADLIGHT) || (options & SKY_LIGHT))
205    {
206        _lightingMode=(options&HEADLIGHT) ? HEADLIGHT : SKY_LIGHT;
207        _light = new osg::Light;
208        _light->setLightNum(0);
209        _light->setAmbient(Vec4(0.00f,0.0f,0.00f,1.0f));
210        _light->setDiffuse(Vec4(0.8f,0.8f,0.8f,1.0f));
211        _light->setSpecular(Vec4(1.0f,1.0f,1.0f,1.0f));
212
213        _globalStateSet->setAssociatedModes(_light.get(),osg::StateAttribute::ON);
214
215        osg::LightModel* lightmodel = new osg::LightModel;
216        lightmodel->setAmbientIntensity(osg::Vec4(0.1f,0.1f,0.1f,1.0f));
217        _globalStateSet->setAttributeAndModes(lightmodel, osg::StateAttribute::ON);
218
219        // enable lighting by default.
220        _globalStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
221
222    }
223    else
224    {
225        _lightingMode = NO_SCENEVIEW_LIGHT;
226    }
227 
228    _renderInfo.setState(new State);
229   
230    _stateGraph = new StateGraph;
231    _renderStage = new RenderStage;
232
233
234    if (options & COMPILE_GLOBJECTS_AT_INIT)
235    {
236        GLObjectsVisitor::Mode  dlvMode = GLObjectsVisitor::COMPILE_DISPLAY_LISTS |
237                                          GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES |
238                                          GLObjectsVisitor::CHECK_BLACK_LISTED_MODES;
239
240    #ifdef __sgi
241        dlvMode = GLObjectsVisitor::COMPILE_STATE_ATTRIBUTES;
242    #endif
243
244        // sgi's IR graphics has a problem with lighting and display lists, as it seems to store
245        // lighting state with the display list, and the display list visitor doesn't currently apply
246        // state before creating display lists. So will disable the init visitor default, this won't
247        // affect functionality since the display lists will be created as and when needed.
248        GLObjectsVisitor* dlv = new GLObjectsVisitor(dlvMode);
249        dlv->setNodeMaskOverride(0xffffffff);
250        _initVisitor = dlv;
251
252    }
253   
254    _updateVisitor = new UpdateVisitor;
255
256    _cullVisitor = CullVisitor::create();
257
258    _cullVisitor->setStateGraph(_stateGraph.get());
259    _cullVisitor->setRenderStage(_renderStage.get());
260
261    _globalStateSet->setGlobalDefaults();
262
263    // set up an texture environment by default to speed up blending operations.
264     osg::TexEnv* texenv = new osg::TexEnv;
265     texenv->setMode(osg::TexEnv::MODULATE);
266     _globalStateSet->setTextureAttributeAndModes(0,texenv, osg::StateAttribute::ON);
267
268    _camera->setClearColor(osg::Vec4(0.2f, 0.2f, 0.4f, 1.0f));
269}
270
271void SceneView::setCamera(osg::Camera* camera, bool assumeOwnershipOfCamera)
272{
273    if (camera)
274    {
275        _camera = camera;
276    }
277    else
278    {
279        osg::notify(osg::NOTICE)<<"Warning: attempt to assign a NULL camera to SceneView not permitted."<<std::endl;
280    }
281   
282    if (assumeOwnershipOfCamera)
283    {
284        _cameraWithOwnership = _camera.get();
285    }
286    else
287    {
288        _cameraWithOwnership = 0;
289    }
290}
291
292void SceneView::setSceneData(osg::Node* node)
293{
294    // take a temporary reference to node to prevent the possibility
295    // of it getting deleted when when we do the camera clear of children.
296    osg::ref_ptr<osg::Node> temporaryRefernce = node;
297   
298    // remove pre existing children
299    _camera->removeChildren(0, _camera->getNumChildren());
300   
301    // add the new one in.
302    _camera->addChild(node);
303}
304
305void SceneView::init()
306{
307    _initCalled = true;
308
309    // force the initialization of the OpenGL extension string
310    // to try and work around a Windows NVidia driver bug circa Oct 2006.
311    osg::isGLExtensionSupported(_renderInfo.getState()->getContextID(),"");
312
313    if (_camera.valid() && _initVisitor.valid())
314    {
315        _initVisitor->reset();
316        _initVisitor->setFrameStamp(_frameStamp.get());
317       
318        GLObjectsVisitor* dlv = dynamic_cast<GLObjectsVisitor*>(_initVisitor.get());
319        if (dlv) dlv->setState(_renderInfo.getState());
320       
321        if (_frameStamp.valid())
322        {
323             _initVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
324        }
325       
326        _camera->accept(*_initVisitor.get());
327       
328    }
329}
330
331void SceneView::update()
332{
333    if (_camera.valid() && _updateVisitor.valid())
334    {
335        _updateVisitor->reset();
336
337        _updateVisitor->setFrameStamp(_frameStamp.get());
338
339        // use the frame number for the traversal number.
340        if (_frameStamp.valid())
341        {
342             _updateVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
343        }
344       
345        _camera->accept(*_updateVisitor.get());
346       
347        // now force a recompute of the bounding volume while we are still in
348        // the read/write app phase, this should prevent the need to recompute
349        // the bounding volumes from within the cull traversal which may be
350        // multi-threaded.
351        _camera->getBound();
352    }
353}
354
355void SceneView::updateUniforms()
356{
357    if (!_localStateSet)
358    {
359        _localStateSet = new osg::StateSet;
360    }
361
362    if (!_localStateSet) return;
363   
364    if ((_activeUniforms & FRAME_NUMBER_UNIFORM) && _frameStamp.valid())
365    {
366        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameNumber",osg::Uniform::INT);
367        uniform->set(_frameStamp->getFrameNumber());       
368    }
369   
370    if ((_activeUniforms & FRAME_TIME_UNIFORM) && _frameStamp.valid())
371    {
372        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_FrameTime",osg::Uniform::FLOAT);
373        uniform->set(static_cast<float>(_frameStamp->getReferenceTime()));
374    }
375   
376    if ((_activeUniforms & DELTA_FRAME_TIME_UNIFORM) && _frameStamp.valid())
377    {
378        float delta_frame_time = (_previousFrameTime != 0.0) ? static_cast<float>(_frameStamp->getReferenceTime()-_previousFrameTime) : 0.0f;
379        _previousFrameTime = _frameStamp->getReferenceTime();
380       
381        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_DeltaFrameTime",osg::Uniform::FLOAT);
382        uniform->set(delta_frame_time);
383    }
384   
385    if ((_activeUniforms & SIMULATION_TIME_UNIFORM) && _frameStamp.valid())
386    {
387        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_SimulationTime",osg::Uniform::FLOAT);
388        uniform->set(static_cast<float>(_frameStamp->getSimulationTime()));
389    }
390   
391    if ((_activeUniforms & DELTA_SIMULATION_TIME_UNIFORM) && _frameStamp.valid())
392    {
393        float delta_simulation_time = (_previousSimulationTime != 0.0) ? static_cast<float>(_frameStamp->getSimulationTime()-_previousSimulationTime) : 0.0f;
394        _previousSimulationTime = _frameStamp->getSimulationTime();
395       
396        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_DeltaSimulationTime",osg::Uniform::FLOAT);
397        uniform->set(delta_simulation_time);
398    }
399   
400    if (_activeUniforms & VIEW_MATRIX_UNIFORM)
401    {
402        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_ViewMatrix",osg::Uniform::FLOAT_MAT4);
403        uniform->set(getViewMatrix());
404    }
405
406    if (_activeUniforms & VIEW_MATRIX_INVERSE_UNIFORM)
407    {
408        osg::Uniform* uniform = _localStateSet->getOrCreateUniform("osg_ViewMatrixInverse",osg::Uniform::FLOAT_MAT4);
409        uniform->set(osg::Matrix::inverse(getViewMatrix()));
410    }
411
412}
413
414osg::Matrixd SceneView::computeLeftEyeProjectionImplementation(const osg::Matrixd& projection) const
415{
416    double iod = _displaySettings->getEyeSeparation();
417    double sd = _displaySettings->getScreenDistance();
418    double scale_x = 1.0;
419    double scale_y = 1.0;
420
421    if (_displaySettings->getSplitStereoAutoAdjustAspectRatio())
422    {
423        switch(_displaySettings->getStereoMode())
424        {
425            case(osg::DisplaySettings::HORIZONTAL_SPLIT):
426                scale_x = 2.0;
427                break;
428            case(osg::DisplaySettings::VERTICAL_SPLIT):
429                scale_y = 2.0;
430                break;
431            default:
432                break;
433        }
434    }
435
436    if (_displaySettings->getDisplayType()==osg::DisplaySettings::HEAD_MOUNTED_DISPLAY)
437    {
438        // head mounted display has the same projection matrix for left and right eyes.
439        return osg::Matrixd::scale(scale_x,scale_y,1.0) *
440               projection;
441    }
442    else
443    {
444        // all other display types assume working like a projected power wall
445        // need to shjear projection matrix to account for asymetric frustum due to eye offset.
446        return osg::Matrixd(1.0,0.0,0.0,0.0,
447                           0.0,1.0,0.0,0.0,
448                           iod/(2.0*sd),0.0,1.0,0.0,
449                           0.0,0.0,0.0,1.0) *
450               osg::Matrixd::scale(scale_x,scale_y,1.0) *
451               projection;
452    }
453}
454
455osg::Matrixd SceneView::computeLeftEyeViewImplementation(const osg::Matrixd& view) const
456{
457    double fusionDistance = _displaySettings->getScreenDistance();
458    switch(_fusionDistanceMode)
459    {
460        case(USE_FUSION_DISTANCE_VALUE):
461            fusionDistance = _fusionDistanceValue;
462            break;
463        case(PROPORTIONAL_TO_SCREEN_DISTANCE):
464            fusionDistance *= _fusionDistanceValue;
465            break;
466    }
467
468    double iod = _displaySettings->getEyeSeparation();
469    double sd = _displaySettings->getScreenDistance();
470    double es = 0.5f*iod*(fusionDistance/sd);
471
472    return view *
473           osg::Matrixd(1.0,0.0,0.0,0.0,
474                       0.0,1.0,0.0,0.0,
475                       0.0,0.0,1.0,0.0,
476                       es,0.0,0.0,1.0);
477}
478
479osg::Matrixd SceneView::computeRightEyeProjectionImplementation(const osg::Matrixd& projection) const
480{
481    double iod = _displaySettings->getEyeSeparation();
482    double sd = _displaySettings->getScreenDistance();
483    double scale_x = 1.0;
484    double scale_y = 1.0;
485
486    if (_displaySettings->getSplitStereoAutoAdjustAspectRatio())
487    {
488        switch(_displaySettings->getStereoMode())
489        {
490            case(osg::DisplaySettings::HORIZONTAL_SPLIT):
491                scale_x = 2.0;
492                break;
493            case(osg::DisplaySettings::VERTICAL_SPLIT):
494                scale_y = 2.0;
495                break;
496            default:
497                break;
498        }
499    }
500
501    if (_displaySettings->getDisplayType()==osg::DisplaySettings::HEAD_MOUNTED_DISPLAY)
502    {
503        // head mounted display has the same projection matrix for left and right eyes.
504        return osg::Matrixd::scale(scale_x,scale_y,1.0) *
505               projection;
506    }
507    else
508    {
509        // all other display types assume working like a projected power wall
510        // need to shjear projection matrix to account for asymetric frustum due to eye offset.
511        return osg::Matrixd(1.0,0.0,0.0,0.0,
512                           0.0,1.0,0.0,0.0,
513                           -iod/(2.0*sd),0.0,1.0,0.0,
514                           0.0,0.0,0.0,1.0) *
515               osg::Matrixd::scale(scale_x,scale_y,1.0) *
516               projection;
517    }
518}
519
520osg::Matrixd SceneView::computeRightEyeViewImplementation(const osg::Matrixd& view) const
521{
522    float fusionDistance = _displaySettings->getScreenDistance();
523    switch(_fusionDistanceMode)
524    {
525        case(USE_FUSION_DISTANCE_VALUE):
526            fusionDistance = _fusionDistanceValue;
527            break;
528        case(PROPORTIONAL_TO_SCREEN_DISTANCE):
529            fusionDistance *= _fusionDistanceValue;
530            break;
531    }
532
533    double iod = _displaySettings->getEyeSeparation();
534    double sd = _displaySettings->getScreenDistance();
535    double es = 0.5*iod*(fusionDistance/sd);
536
537    return view *
538           osg::Matrixd(1.0,0.0,0.0,0.0,
539                       0.0,1.0,0.0,0.0,
540                       0.0,0.0,1.0,0.0,
541                       -es,0.0,0.0,1.0);
542}
543
544void SceneView::computeLeftEyeViewport(const osg::Viewport *viewport)
545{
546    if(!viewport) return;
547
548    if(!_viewportLeft.valid()) _viewportLeft = new osg::Viewport;
549
550    switch(_displaySettings->getStereoMode())
551    {
552
553        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
554        {
555            Viewport::value_type separation = _displaySettings->getSplitStereoHorizontalSeparation();
556
557            if (_displaySettings->getSplitStereoHorizontalEyeMapping()==osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT)
558            {
559                Viewport::value_type left_half_width = (viewport->width()-separation)/2;
560                _viewportLeft->setViewport(viewport->x(),viewport->y(),left_half_width,viewport->height());
561            }
562            else
563            {
564                Viewport::value_type right_half_begin = (viewport->width()+separation)/2;
565                Viewport::value_type right_half_width = viewport->width()-right_half_begin;
566                _viewportLeft->setViewport(viewport->x()+right_half_begin,viewport->y(),right_half_width,viewport->height());
567            }
568        }
569        break;
570
571        case(osg::DisplaySettings::VERTICAL_SPLIT):
572        {
573            Viewport::value_type separation = _displaySettings->getSplitStereoVerticalSeparation();
574
575            if (_displaySettings->getSplitStereoVerticalEyeMapping()==osg::DisplaySettings::LEFT_EYE_TOP_VIEWPORT)
576            {
577                Viewport::value_type top_half_begin = (viewport->height()+separation)/2;
578                Viewport::value_type top_half_height = viewport->height()-top_half_begin;
579                _viewportLeft->setViewport(viewport->x(),viewport->y()+top_half_begin,viewport->width(),top_half_height);
580            }
581            else
582            {
583                Viewport::value_type bottom_half_height = (viewport->height()-separation)/2;
584                _viewportLeft->setViewport(viewport->x(),viewport->y(),viewport->width(),bottom_half_height);
585            }
586        }
587        break;
588
589        default:
590            _viewportLeft->setViewport(viewport->x(),viewport->y(),viewport->width(),viewport->height());
591            break;
592    }
593}
594
595void SceneView::computeRightEyeViewport(const osg::Viewport *viewport)
596{
597    if(!viewport) return;
598
599    if(!_viewportRight.valid()) _viewportRight = new osg::Viewport;
600
601    switch(_displaySettings->getStereoMode())
602    {
603        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
604        {
605            Viewport::value_type separation = _displaySettings->getSplitStereoHorizontalSeparation();
606
607            if (_displaySettings->getSplitStereoHorizontalEyeMapping()!=osg::DisplaySettings::LEFT_EYE_LEFT_VIEWPORT)
608            {
609                Viewport::value_type left_half_width = (viewport->width()-separation)/2;
610                _viewportRight->setViewport(viewport->x(),viewport->y(),left_half_width,viewport->height());
611            }
612            else
613            {
614                Viewport::value_type right_half_begin = (viewport->width()+separation)/2;
615                Viewport::value_type right_half_width = viewport->width()-right_half_begin;
616                _viewportRight->setViewport(viewport->x()+right_half_begin,viewport->y(),right_half_width,viewport->height());
617            }
618        }
619        break;
620
621        case(osg::DisplaySettings::VERTICAL_SPLIT):
622        {
623            Viewport::value_type separation = _displaySettings->getSplitStereoVerticalSeparation();
624
625            if (_displaySettings->getSplitStereoVerticalEyeMapping()!=osg::DisplaySettings::LEFT_EYE_TOP_VIEWPORT)
626            {
627                Viewport::value_type top_half_begin = (viewport->height()+separation)/2;
628                Viewport::value_type top_half_height = viewport->height()-top_half_begin;
629                _viewportRight->setViewport(viewport->x(),viewport->y()+top_half_begin,viewport->width(),top_half_height);
630            }
631            else
632            {
633                Viewport::value_type bottom_half_height = (viewport->height()-separation)/2;
634                _viewportRight->setViewport(viewport->x(),viewport->y(),viewport->width(),bottom_half_height);
635            }
636        }
637        break;
638
639        default:
640            _viewportRight->setViewport(viewport->x(),viewport->y(),viewport->width(),viewport->height());
641            break;
642    }
643}
644
645void SceneView::setLightingMode(LightingMode mode)
646{
647    if (mode==_lightingMode) return;
648   
649    if (_lightingMode!=NO_SCENEVIEW_LIGHT)
650    {
651        // remove GL_LIGHTING mode
652        _globalStateSet->removeMode(GL_LIGHTING);
653
654        if (_light.valid())
655        {
656            _globalStateSet->removeAssociatedModes(_light.get());
657        }
658
659    }
660
661    _lightingMode = mode;
662
663    if (_lightingMode!=NO_SCENEVIEW_LIGHT)
664    {
665        // add GL_LIGHTING mode
666        _globalStateSet->setMode(GL_LIGHTING, osg::StateAttribute::ON);
667        if (_light.valid())
668        {
669            _globalStateSet->setAssociatedModes(_light.get(), osg::StateAttribute::ON);
670        }
671    }
672}
673
674void SceneView::inheritCullSettings(const osg::CullSettings& settings, unsigned int inheritanceMask)
675{
676    if (_camera.valid() && _camera->getView())
677    {
678        if (inheritanceMask & osg::CullSettings::LIGHTING_MODE)
679        {
680            LightingMode newLightingMode = _lightingMode;
681       
682            switch(_camera->getView()->getLightingMode())
683            {
684                case(osg::View::NO_LIGHT): newLightingMode = NO_SCENEVIEW_LIGHT; break;
685                case(osg::View::HEADLIGHT): newLightingMode = HEADLIGHT; break;
686                case(osg::View::SKY_LIGHT): newLightingMode = SKY_LIGHT; break;
687            }
688           
689            if (newLightingMode != _lightingMode)
690            {
691                setLightingMode(newLightingMode);
692            }
693        }
694               
695        if (inheritanceMask & osg::CullSettings::LIGHT)
696        {
697            setLight(_camera->getView()->getLight());
698        }
699    }
700   
701    osg::CullSettings::inheritCullSettings(settings, inheritanceMask);
702}
703
704
705void SceneView::cull()
706{
707    _dynamicObjectCount = 0;
708
709    if (_camera->getNodeMask()==0) return;
710
711    _renderInfo.setView(_camera->getView());
712
713    // update the active uniforms
714    updateUniforms();
715
716    if (!_renderInfo.getState())
717    {
718        osg::notify(osg::INFO) << "Warning: no valid osgUtil::SceneView::_state attached, creating a default state automatically."<< std::endl;
719
720        // note the constructor for osg::State will set ContextID to 0 which will be fine to single context graphics
721        // applications which is ok for most apps, but not multiple context/pipe applications.
722        _renderInfo.setState(new osg::State);
723    }
724   
725    osg::State* state = _renderInfo.getState();
726
727    if (!_localStateSet)
728    {
729        _localStateSet = new osg::StateSet;
730    }
731   
732    // we in theory should be able to be able to bypass reset, but we'll call it just incase.
733    //_state->reset();
734   
735    state->setFrameStamp(_frameStamp.get());
736    state->setDisplaySettings(_displaySettings.get());
737
738
739    if (!_cullVisitor)
740    {
741        osg::notify(osg::INFO) << "Warning: no valid osgUtil::SceneView:: attached, creating a default CullVisitor automatically."<< std::endl;
742        _cullVisitor = CullVisitor::create();
743    }
744    if (!_stateGraph)
745    {
746        osg::notify(osg::INFO) << "Warning: no valid osgUtil::SceneView:: attached, creating a global default StateGraph automatically."<< std::endl;
747        _stateGraph = new StateGraph;
748    }
749    if (!_renderStage)
750    {
751        osg::notify(osg::INFO) << "Warning: no valid osgUtil::SceneView::_renderStage attached, creating a default RenderStage automatically."<< std::endl;
752        _renderStage = new RenderStage;
753    }
754
755    if (_displaySettings.valid() && _displaySettings->getStereo())
756    {
757
758        if (_displaySettings->getStereoMode()==osg::DisplaySettings::LEFT_EYE)
759        {
760            // set up the left eye.
761            _cullVisitor->setTraversalMask(_cullMaskLeft);
762            computeLeftEyeViewport(getViewport());
763            bool computeNearFar = cullStage(computeLeftEyeProjection(getProjectionMatrix()),computeLeftEyeView(getViewMatrix()),_cullVisitor.get(),_stateGraph.get(),_renderStage.get(),_viewportLeft.get());
764
765            if (computeNearFar)
766            {
767                CullVisitor::value_type zNear = _cullVisitor->getCalculatedNearPlane();
768                CullVisitor::value_type zFar = _cullVisitor->getCalculatedFarPlane();
769                _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
770            }
771
772        }
773        else if (_displaySettings->getStereoMode()==osg::DisplaySettings::RIGHT_EYE)
774        {
775            // set up the right eye.
776            _cullVisitor->setTraversalMask(_cullMaskRight);
777            computeRightEyeViewport(getViewport());
778            bool computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),_cullVisitor.get(),_stateGraph.get(),_renderStage.get(),_viewportRight.get());
779
780            if (computeNearFar)
781            {
782                CullVisitor::value_type zNear = _cullVisitor->getCalculatedNearPlane();
783                CullVisitor::value_type zFar = _cullVisitor->getCalculatedFarPlane();
784                _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
785            }
786
787        }
788        else
789        {
790
791            if (!_cullVisitorLeft.valid()) _cullVisitorLeft = dynamic_cast<CullVisitor*>(_cullVisitor->clone());
792            if (!_stateGraphLeft.valid()) _stateGraphLeft = dynamic_cast<StateGraph*>(_stateGraph->cloneType());
793            if (!_renderStageLeft.valid()) _renderStageLeft = dynamic_cast<RenderStage*>(_renderStage->clone(osg::CopyOp::DEEP_COPY_ALL));
794
795            if (!_cullVisitorRight.valid()) _cullVisitorRight = dynamic_cast<CullVisitor*>(_cullVisitor->clone());
796            if (!_stateGraphRight.valid()) _stateGraphRight = dynamic_cast<StateGraph*>(_stateGraph->cloneType());
797            if (!_renderStageRight.valid()) _renderStageRight = dynamic_cast<RenderStage*>(_renderStage->clone(osg::CopyOp::DEEP_COPY_ALL));
798           
799            _cullVisitorLeft->setDatabaseRequestHandler(_cullVisitor->getDatabaseRequestHandler());
800            _cullVisitorLeft->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback());
801            _cullVisitorLeft->setTraversalMask(_cullMaskLeft);
802            computeLeftEyeViewport(getViewport());
803            bool computeNearFar = cullStage(computeLeftEyeProjection(getProjectionMatrix()),computeLeftEyeView(getViewMatrix()),_cullVisitorLeft.get(),_stateGraphLeft.get(),_renderStageLeft.get(),_viewportLeft.get());
804
805
806            // set up the right eye.
807            _cullVisitorRight->setDatabaseRequestHandler(_cullVisitor->getDatabaseRequestHandler());
808            _cullVisitorRight->setClampProjectionMatrixCallback(_cullVisitor->getClampProjectionMatrixCallback());
809            _cullVisitorRight->setTraversalMask(_cullMaskRight);
810            computeRightEyeViewport(getViewport());
811            computeNearFar = cullStage(computeRightEyeProjection(getProjectionMatrix()),computeRightEyeView(getViewMatrix()),_cullVisitorRight.get(),_stateGraphRight.get(),_renderStageRight.get(),_viewportRight.get());
812           
813            if (computeNearFar)
814            {
815                CullVisitor::value_type zNear = osg::minimum(_cullVisitorLeft->getCalculatedNearPlane(),_cullVisitorRight->getCalculatedNearPlane());
816                CullVisitor::value_type zFar =  osg::maximum(_cullVisitorLeft->getCalculatedFarPlane(),_cullVisitorRight->getCalculatedFarPlane());
817                _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
818            }
819
820        }
821
822    }
823    else
824    {
825
826        _cullVisitor->setTraversalMask(_cullMask);
827        bool computeNearFar = cullStage(getProjectionMatrix(),getViewMatrix(),_cullVisitor.get(),_stateGraph.get(),_renderStage.get(),getViewport());
828
829        if (computeNearFar)
830        {
831            CullVisitor::value_type zNear = _cullVisitor->getCalculatedNearPlane();
832            CullVisitor::value_type zFar = _cullVisitor->getCalculatedFarPlane();
833            _cullVisitor->clampProjectionMatrix(getProjectionMatrix(),zNear,zFar);
834        }
835    }
836   
837
838
839}
840
841bool SceneView::cullStage(const osg::Matrixd& projection,const osg::Matrixd& modelview,osgUtil::CullVisitor* cullVisitor, osgUtil::StateGraph* rendergraph, osgUtil::RenderStage* renderStage, osg::Viewport *viewport)
842{
843
844    if (!_camera || !viewport) return false;
845
846    osg::ref_ptr<RefMatrix> proj = new osg::RefMatrix(projection);
847    osg::ref_ptr<RefMatrix> mv = new osg::RefMatrix(modelview);
848
849    // collect any occluder in the view frustum.
850    if (_camera->containsOccluderNodes())
851    {
852        //std::cout << "Scene graph contains occluder nodes, searching for them"<<std::endl;
853       
854       
855        if (!_collectOccludersVisitor) _collectOccludersVisitor = new osg::CollectOccludersVisitor;
856       
857        _collectOccludersVisitor->inheritCullSettings(*this);
858       
859        _collectOccludersVisitor->reset();
860       
861        _collectOccludersVisitor->setFrameStamp(_frameStamp.get());
862
863        // use the frame number for the traversal number.
864        if (_frameStamp.valid())
865        {
866             _collectOccludersVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
867        }
868
869        _collectOccludersVisitor->pushViewport(viewport);
870        _collectOccludersVisitor->pushProjectionMatrix(proj.get());
871        _collectOccludersVisitor->pushModelViewMatrix(mv.get(),osg::Transform::ABSOLUTE_RF);
872
873        // traverse the scene graph to search for occluder in there new positions.
874        for(unsigned int i=0; i< _camera->getNumChildren(); ++i)
875        {
876            _camera->getChild(i)->accept(*_collectOccludersVisitor);
877        }
878
879        _collectOccludersVisitor->popModelViewMatrix();
880        _collectOccludersVisitor->popProjectionMatrix();
881        _collectOccludersVisitor->popViewport();
882       
883        // sort the occluder from largest occluder volume to smallest.
884        _collectOccludersVisitor->removeOccludedOccluders();
885       
886       
887        osg::notify(osg::DEBUG_INFO) << "finished searching for occluder - found "<<_collectOccludersVisitor->getCollectedOccluderSet().size()<<std::endl;
888           
889        cullVisitor->getOccluderList().clear();
890        std::copy(_collectOccludersVisitor->getCollectedOccluderSet().begin(),_collectOccludersVisitor->getCollectedOccluderSet().end(), std::back_insert_iterator<CullStack::OccluderList>(cullVisitor->getOccluderList()));
891    }
892   
893
894
895    cullVisitor->reset();
896
897    cullVisitor->setFrameStamp(_frameStamp.get());
898
899    // use the frame number for the traversal number.
900    if (_frameStamp.valid())
901    {
902         cullVisitor->setTraversalNumber(_frameStamp->getFrameNumber());
903    }
904
905    cullVisitor->inheritCullSettings(*this);
906
907    cullVisitor->setStateGraph(rendergraph);
908    cullVisitor->setRenderStage(renderStage);
909
910    cullVisitor->setRenderInfo( _renderInfo );
911
912    renderStage->reset();
913
914    // comment out reset of rendergraph since clean is more efficient.
915    //  rendergraph->reset();
916
917    // use clean of the rendergraph rather than reset, as it is able to
918    // reuse the structure on the rendergraph in the next frame. This
919    // achieves a certain amount of frame cohereancy of memory allocation.
920    rendergraph->clean();
921
922    renderStage->setViewport(viewport);
923    renderStage->setClearColor(_camera->getClearColor());
924    renderStage->setClearDepth(_camera->getClearDepth());
925    renderStage->setClearAccum(_camera->getClearAccum());
926    renderStage->setClearStencil(_camera->getClearStencil());
927    renderStage->setClearMask(_camera->getClearMask());
928   
929#if 1   
930    renderStage->setCamera(_camera.get());
931#endif
932
933    switch(_lightingMode)
934    {
935    case(HEADLIGHT):
936        if (_light.valid()) renderStage->addPositionedAttribute(NULL,_light.get());
937        else osg::notify(osg::WARN)<<"Warning: no osg::Light attached to ogUtil::SceneView to provide head light.*/"<<std::endl;
938        break;
939    case(SKY_LIGHT):
940        if (_light.valid()) renderStage->addPositionedAttribute(mv.get(),_light.get());
941        else osg::notify(osg::WARN)<<"Warning: no osg::Light attached to ogUtil::SceneView to provide sky light.*/"<<std::endl;
942        break;
943    default:
944        break;
945    }           
946
947    if (_globalStateSet.valid()) cullVisitor->pushStateSet(_globalStateSet.get());
948    if (_localStateSet.valid()) cullVisitor->pushStateSet(_localStateSet.get());
949
950
951    cullVisitor->pushViewport(viewport);
952    cullVisitor->pushProjectionMatrix(proj.get());
953    cullVisitor->pushModelViewMatrix(mv.get(),osg::Transform::ABSOLUTE_RF);
954   
955
956    // traverse the scene graph to generate the rendergraph.
957    for(unsigned int childNo=0;
958        childNo<_camera->getNumChildren();
959        ++childNo)
960    {
961        _camera->getChild(childNo)->accept(*cullVisitor);
962    }
963
964    cullVisitor->popModelViewMatrix();
965    cullVisitor->popProjectionMatrix();
966    cullVisitor->popViewport();
967
968    if (_localStateSet.valid()) cullVisitor->popStateSet();
969    if (_globalStateSet.valid()) cullVisitor->popStateSet();
970   
971
972    renderStage->sort();
973
974    // prune out any empty StateGraph children.
975    // note, this would be not required if the rendergraph had been
976    // reset at the start of each frame (see top of this method) but
977    // a clean has been used instead to try to minimize the amount of
978    // allocation and deleteing of the StateGraph nodes.
979    rendergraph->prune();
980   
981    // set the number of dynamic objects in the scene.   
982    _dynamicObjectCount += renderStage->computeNumberOfDynamicRenderLeaves();
983
984
985    bool computeNearFar = (cullVisitor->getComputeNearFarMode()!=osgUtil::CullVisitor::DO_NOT_COMPUTE_NEAR_FAR) && getSceneData()!=0;
986    return computeNearFar;
987}
988
989void SceneView::releaseAllGLObjects()
990{
991    if (!_camera) return;
992   
993    _camera->releaseGLObjects(_renderInfo.getState());
994   
995    // we need to reset State as it keeps handles to Program objects.
996    if (_renderInfo.getState()) _renderInfo.getState()->reset();
997}
998
999
1000void SceneView::flushAllDeletedGLObjects()
1001{
1002    _requiresFlush = false;
1003   
1004    osg::flushAllDeletedGLObjects(getState()->getContextID());
1005 }
1006
1007void SceneView::flushDeletedGLObjects(double& availableTime)
1008{
1009    osg::State* state = _renderInfo.getState();
1010
1011    _requiresFlush = false;
1012
1013    double currentTime = state->getFrameStamp()?state->getFrameStamp()->getReferenceTime():0.0;
1014
1015    osg::flushDeletedGLObjects(getState()->getContextID(), currentTime, availableTime);
1016}
1017
1018void SceneView::draw()
1019{
1020    if (_camera->getNodeMask()==0) return;
1021
1022    osg::State* state = _renderInfo.getState();
1023    state->initializeExtensionProcs();
1024
1025    osg::Texture::TextureObjectManager* tom = osg::Texture::getTextureObjectManager(state->getContextID());
1026    tom->newFrame(state->getFrameStamp());
1027
1028    osg::GLBufferObjectManager* bom = osg::GLBufferObjectManager::getGLBufferObjectManager(state->getContextID());
1029    bom->newFrame(state->getFrameStamp());
1030
1031    if (!_initCalled) init();
1032
1033    // note, to support multi-pipe systems the deletion of OpenGL display list
1034    // and texture objects is deferred until the OpenGL context is the correct
1035    // context for when the object were originally created.  Here we know what
1036    // context we are in so can flush the appropriate caches.
1037   
1038    if (_requiresFlush)
1039    {
1040        double availableTime = 0.005;
1041        flushDeletedGLObjects(availableTime);
1042    }
1043
1044    // assume the the draw which is about to happen could generate GL objects that need flushing in the next frame.
1045    _requiresFlush = true;
1046
1047    state->setInitialViewMatrix(new osg::RefMatrix(getViewMatrix()));
1048
1049    RenderLeaf* previous = NULL;
1050    if (_displaySettings.valid() && _displaySettings->getStereo())
1051    {
1052   
1053        switch(_displaySettings->getStereoMode())
1054        {
1055        case(osg::DisplaySettings::QUAD_BUFFER):
1056            {
1057
1058                _localStateSet->setAttribute(getViewport());
1059
1060                // ensure that all color planes are active.
1061                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1062                if (cmask)
1063                {
1064                    cmask->setMask(true,true,true,true);
1065                }
1066                else
1067                {
1068                    cmask = new osg::ColorMask(true,true,true,true);
1069                    _localStateSet->setAttribute(cmask);
1070                }
1071                _renderStageLeft->setColorMask(cmask);
1072                _renderStageRight->setColorMask(cmask);
1073
1074                _renderStageLeft->setDrawBuffer(GL_BACK_LEFT);
1075                _renderStageLeft->setReadBuffer(GL_BACK_LEFT);
1076                _renderStageRight->setDrawBuffer(GL_BACK_RIGHT);
1077                _renderStageRight->setReadBuffer(GL_BACK_RIGHT);
1078
1079                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1080                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1081
1082                _renderStageLeft->draw(_renderInfo,previous);
1083
1084                _renderStageRight->draw(_renderInfo,previous);
1085
1086            }
1087            break;
1088        case(osg::DisplaySettings::ANAGLYPHIC):
1089            {
1090                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) )
1091                {
1092                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1093                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1094
1095                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1096                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1097                }
1098               
1099                _localStateSet->setAttribute(getViewport());
1100
1101               
1102                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1103                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1104
1105
1106                // ensure that left eye color planes are active.
1107                osg::ColorMask* leftColorMask = _renderStageLeft->getColorMask();
1108                if (!leftColorMask)
1109                {
1110                    leftColorMask = new osg::ColorMask();
1111                    _renderStageLeft->setColorMask(leftColorMask);
1112                }
1113               
1114                // red
1115                leftColorMask->setMask(true,false,false,true);
1116
1117                // orange
1118                // leftColorMask->setMask(true,true,false,true);
1119
1120                _localStateSet->setAttribute(leftColorMask);
1121
1122                // draw left eye.
1123                _renderStageLeft->draw(_renderInfo,previous);
1124               
1125               
1126
1127                // ensure that right eye color planes are active.
1128                osg::ColorMask* rightColorMask = _renderStageRight->getColorMask();
1129                if (!rightColorMask)
1130                {
1131                    rightColorMask = new osg::ColorMask();
1132                    _renderStageRight->setColorMask(rightColorMask);
1133                }
1134
1135                // cyan
1136                rightColorMask->setMask(false,true,true,true);
1137               
1138                // blue
1139                // rightColorMask->setMask(false,false,true,true);
1140
1141                _localStateSet->setAttribute(rightColorMask);
1142
1143                // draw right eye.
1144                _renderStageRight->draw(_renderInfo,previous);
1145
1146            }
1147            break;
1148        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
1149            {
1150                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1151                {
1152                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1153                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1154
1155                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1156                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1157                }
1158
1159                // ensure that all color planes are active.
1160                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1161                if (cmask)
1162                {
1163                    cmask->setMask(true,true,true,true);
1164                }
1165                else
1166                {
1167                    cmask = new osg::ColorMask(true,true,true,true);
1168                    _localStateSet->setAttribute(cmask);
1169                }
1170                _renderStageLeft->setColorMask(cmask);
1171                _renderStageRight->setColorMask(cmask);
1172
1173                _localStateSet->setAttribute(_viewportLeft.get());
1174                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1175
1176                _localStateSet->setAttribute(_viewportRight.get());
1177                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1178
1179                double separation = _displaySettings->getSplitStereoHorizontalSeparation();
1180
1181                double  left_half_width = (getViewport()->width()-separation)/2.0;
1182
1183                clearArea(static_cast<int>(getViewport()->x()+left_half_width),
1184                          static_cast<int>(getViewport()->y()),
1185                          static_cast<int>(separation),
1186                          static_cast<int>(getViewport()->height()),_renderStageLeft->getClearColor());
1187
1188             
1189                _localStateSet->setAttribute(_viewportLeft.get());
1190                _renderStageLeft->draw(_renderInfo,previous);
1191
1192                _localStateSet->setAttribute(_viewportRight.get());
1193                _renderStageRight->draw(_renderInfo,previous);
1194
1195            }
1196            break;
1197        case(osg::DisplaySettings::VERTICAL_SPLIT):
1198            {
1199                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1200                {
1201                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1202                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1203
1204                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1205                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1206                }
1207
1208                // ensure that all color planes are active.
1209                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1210                if (cmask)
1211                {
1212                    cmask->setMask(true,true,true,true);
1213                }
1214                else
1215                {
1216                    cmask = new osg::ColorMask(true,true,true,true);
1217                    _localStateSet->setAttribute(cmask);
1218                }
1219
1220                _renderStageLeft->setColorMask(cmask);
1221                _renderStageRight->setColorMask(cmask);
1222
1223                _localStateSet->setAttribute(_viewportLeft.get());
1224                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1225
1226                _localStateSet->setAttribute(_viewportRight.get());
1227                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1228
1229                double separation = _displaySettings->getSplitStereoVerticalSeparation();
1230
1231                double bottom_half_height = (getViewport()->height()-separation)/2.0;
1232
1233                clearArea(static_cast<int>(getViewport()->x()),
1234                          static_cast<int>(getViewport()->y()+bottom_half_height),
1235                          static_cast<int>(getViewport()->width()),
1236                          static_cast<int>(separation),
1237                          _renderStageLeft->getClearColor());
1238
1239                _localStateSet->setAttribute(_viewportLeft.get());
1240                _renderStageLeft->draw(_renderInfo,previous);
1241
1242                _localStateSet->setAttribute(_viewportRight.get());
1243                _renderStageRight->draw(_renderInfo,previous);
1244            }
1245            break;
1246        case(osg::DisplaySettings::RIGHT_EYE):
1247        case(osg::DisplaySettings::LEFT_EYE):
1248            {
1249                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1250                {
1251                    _renderStage->setDrawBuffer(_camera->getDrawBuffer());
1252                    _renderStage->setReadBuffer(_camera->getDrawBuffer());
1253                }
1254
1255                // ensure that all color planes are active.
1256                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1257                if (cmask)
1258                {
1259                    cmask->setMask(true,true,true,true);
1260                }
1261                else
1262                {
1263                    cmask = new osg::ColorMask(true,true,true,true);
1264                    _localStateSet->setAttribute(cmask);
1265                }
1266                _renderStage->setColorMask(cmask);
1267                _renderStage->setColorMask(cmask);
1268
1269                _localStateSet->setAttribute(getViewport());
1270                _renderStage->drawPreRenderStages(_renderInfo,previous);
1271                _renderStage->draw(_renderInfo,previous);
1272            }
1273            break;
1274        case(osg::DisplaySettings::VERTICAL_INTERLACE):
1275            {
1276                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1277                {
1278                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1279                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1280                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1281                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1282                }
1283                _localStateSet->setAttribute(getViewport());
1284
1285                // ensure that all color planes are active.
1286                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1287                if (cmask)
1288                {
1289                    cmask->setMask(true,true,true,true);
1290                }
1291                else
1292                {
1293                    cmask = new osg::ColorMask(true,true,true,true);
1294                    _localStateSet->setAttribute(cmask);
1295                }
1296                _renderStageLeft->setColorMask(cmask);
1297                _renderStageRight->setColorMask(cmask);
1298
1299                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1300                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1301
1302                glEnable(GL_STENCIL_TEST);
1303
1304                if(_redrawInterlacedStereoStencilMask ||
1305                   _interlacedStereoStencilWidth != getViewport()->width() ||
1306                  _interlacedStereoStencilHeight != getViewport()->height() )
1307                {
1308                    getViewport()->apply(*state);
1309                    glMatrixMode(GL_PROJECTION);
1310                    glLoadIdentity();
1311                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1312                    glMatrixMode(GL_MODELVIEW);
1313                    glLoadIdentity();   
1314                    getState()->applyMode(GL_LIGHTING,false);
1315                    getState()->applyMode(GL_DEPTH_TEST,false);
1316                    glStencilMask(~0u);
1317                    glClear(GL_STENCIL_BUFFER_BIT);
1318                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1319                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1320                    glPolygonStipple(patternVertEven);
1321                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1322                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1323                   
1324                    glRecti(static_cast<GLint>(getViewport()->x()),
1325                            static_cast<GLint>(getViewport()->y()),
1326                            static_cast<GLint>(getViewport()->width()),
1327                            static_cast<GLint>(getViewport()->height()) );
1328                           
1329                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1330                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1331                    getState()->applyMode(GL_LIGHTING,true);
1332                    getState()->applyMode(GL_DEPTH_TEST,true);
1333                   
1334                    _redrawInterlacedStereoStencilMask = false;
1335                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1336                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1337                }
1338
1339                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1340                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1341
1342                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1343                glStencilFunc(GL_EQUAL, 0, ~0u);   
1344                _renderStageLeft->draw(_renderInfo,previous);
1345               
1346                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1347                _renderStageRight->draw(_renderInfo,previous);
1348                glDisable(GL_STENCIL_TEST);
1349            }
1350            break;
1351        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1352            {
1353                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1354                {
1355                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1356                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1357                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1358                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1359                }
1360                _localStateSet->setAttribute(getViewport());
1361
1362                // ensure that all color planes are active.
1363                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1364                if (cmask)
1365                {
1366                    cmask->setMask(true,true,true,true);
1367                }
1368                else
1369                {
1370                    cmask = new osg::ColorMask(true,true,true,true);
1371                    _localStateSet->setAttribute(cmask);
1372                }
1373                _renderStageLeft->setColorMask(cmask);
1374                _renderStageRight->setColorMask(cmask);
1375
1376                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1377                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1378
1379                glEnable(GL_STENCIL_TEST);
1380
1381                if(_redrawInterlacedStereoStencilMask ||
1382                   _interlacedStereoStencilWidth != getViewport()->width() ||
1383                  _interlacedStereoStencilHeight != getViewport()->height() )
1384                {
1385                    getViewport()->apply(*state);
1386                    glMatrixMode(GL_PROJECTION);
1387                    glLoadIdentity();
1388                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1389                    glMatrixMode(GL_MODELVIEW);
1390                    glLoadIdentity();
1391                    getState()->applyMode(GL_LIGHTING,false);
1392                    getState()->applyMode(GL_DEPTH_TEST,false);
1393                    glStencilMask(~0u);
1394                    glClear(GL_STENCIL_BUFFER_BIT);
1395                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1396                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1397                    glPolygonStipple(patternHorzEven);
1398                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1399                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1400
1401                    glRecti(static_cast<GLint>(getViewport()->x()),
1402                            static_cast<GLint>(getViewport()->y()),
1403                            static_cast<GLint>(getViewport()->width()),
1404                            static_cast<GLint>(getViewport()->height()) );
1405                           
1406                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1407                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1408                    getState()->applyMode(GL_LIGHTING,true);
1409                    getState()->applyMode(GL_DEPTH_TEST,true);
1410                   
1411                    _redrawInterlacedStereoStencilMask = false;
1412                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1413                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1414                }
1415
1416                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1417                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1418
1419                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1420                glStencilFunc(GL_EQUAL, 0, ~0u);   
1421                _renderStageLeft->draw(_renderInfo,previous);
1422               
1423                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1424                _renderStageRight->draw(_renderInfo,previous);
1425                glDisable(GL_STENCIL_TEST);
1426            }
1427            break;
1428        case(osg::DisplaySettings::CHECKERBOARD):
1429            {
1430                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1431                {
1432                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1433                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1434                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1435                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1436                }
1437                _localStateSet->setAttribute(getViewport());
1438
1439                // ensure that all color planes are active.
1440                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1441                if (cmask)
1442                {
1443                    cmask->setMask(true,true,true,true);
1444                }
1445                else
1446                {
1447                    cmask = new osg::ColorMask(true,true,true,true);
1448                    _localStateSet->setAttribute(cmask);
1449                }
1450                _renderStageLeft->setColorMask(cmask);
1451                _renderStageRight->setColorMask(cmask);
1452
1453                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1454                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1455
1456                glEnable(GL_STENCIL_TEST);
1457
1458                if(_redrawInterlacedStereoStencilMask ||
1459                   _interlacedStereoStencilWidth != getViewport()->width() ||
1460                  _interlacedStereoStencilHeight != getViewport()->height() )
1461                {
1462                    getViewport()->apply(*state);
1463                    glMatrixMode(GL_PROJECTION);
1464                    glLoadIdentity();
1465                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1466                    glMatrixMode(GL_MODELVIEW);
1467                    glLoadIdentity();
1468                    glDisable(GL_LIGHTING);
1469                    glDisable(GL_DEPTH_TEST);
1470                    glStencilMask(~0u);
1471                    glClear(GL_STENCIL_BUFFER_BIT);
1472                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1473                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1474                    glPolygonStipple(patternCheckerboard);
1475                    glEnable(GL_POLYGON_STIPPLE);
1476                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1477
1478                    glRecti(static_cast<GLint>(getViewport()->x()),
1479                            static_cast<GLint>(getViewport()->y()),
1480                            static_cast<GLint>(getViewport()->width()),
1481                            static_cast<GLint>(getViewport()->height()) );
1482                           
1483                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1484                    glDisable(GL_POLYGON_STIPPLE);
1485                    glEnable(GL_LIGHTING);
1486                    glEnable(GL_DEPTH_TEST);
1487                   
1488                    _redrawInterlacedStereoStencilMask = false;
1489                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1490                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1491                }
1492
1493                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1494                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1495
1496                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1497                glStencilFunc(GL_EQUAL, 0, ~0u);   
1498                _renderStageLeft->draw(_renderInfo,previous);
1499               
1500                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1501                _renderStageRight->draw(_renderInfo,previous);
1502                glDisable(GL_STENCIL_TEST);
1503            }
1504            break;
1505        default:
1506            {
1507                osg::notify(osg::NOTICE)<<"Warning: stereo mode not implemented yet."<< std::endl;
1508            }
1509            break;
1510        }
1511    }
1512    else
1513    {
1514
1515        // Need to restore draw buffer when toggling Stereo off.
1516        if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) )
1517        {
1518            _renderStage->setDrawBuffer(_camera->getDrawBuffer());
1519            _renderStage->setReadBuffer(_camera->getDrawBuffer());
1520        }
1521
1522        if( 0 == ( _camera->getInheritanceMask() & READ_BUFFER ) )
1523        {
1524            _renderStage->setReadBuffer(_camera->getReadBuffer());
1525        }
1526
1527        _localStateSet->setAttribute(getViewport());
1528
1529
1530        // ensure that all color planes are active.
1531        osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1532        if (cmask)
1533        {
1534            cmask->setMask(true,true,true,true);
1535        }
1536        else
1537        {
1538            cmask = new osg::ColorMask(true,true,true,true);
1539            _localStateSet->setAttribute(cmask);
1540        }
1541        _renderStage->setColorMask(cmask);
1542
1543        // bog standard draw.
1544        _renderStage->drawPreRenderStages(_renderInfo,previous);
1545        _renderStage->draw(_renderInfo,previous);
1546    }
1547   
1548    // re apply the defalt OGL state.
1549    state->popAllStateSets();
1550    state->apply();
1551
1552#if 0
1553    if (_camera->getPostDrawCallback())
1554    {
1555        (*(_camera->getPostDrawCallback()))(*_camera);
1556    }
1557#endif
1558
1559    if (state->getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
1560    {
1561        if (state->checkGLErrors("end of SceneView::draw()"))
1562        {
1563            // go into debug mode of OGL error in a fine grained way to help
1564            // track down OpenGL errors.
1565            state->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
1566        }
1567    }
1568
1569// #define REPORT_TEXTURE_MANAGER_STATS
1570#ifdef REPORT_TEXTURE_MANAGER_STATS
1571    tom->reportStats();
1572    bom->reportStats();
1573#endif
1574
1575    // osg::notify(osg::NOTICE)<<"SceneView  draw() DynamicObjectCount"<<getState()->getDynamicObjectCount()<<std::endl;
1576
1577}
1578
1579/** Calculate, via glUnProject, the object coordinates of a window point.
1580    Note, current implementation requires that SceneView::draw() has been previously called
1581    for projectWindowIntoObject to produce valid values.  As per OpenGL
1582    windows coordinates are calculated relative to the bottom left of the window.*/
1583bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& object) const
1584{
1585    osg::Matrix inverseMVPW;
1586    inverseMVPW.invert(computeMVPW());
1587   
1588    object = window*inverseMVPW;
1589   
1590    return true;
1591}
1592
1593
1594/** Calculate, via glUnProject, the object coordinates of a window x,y
1595    when projected onto the near and far planes.
1596    Note, current implementation requires that SceneView::draw() has been previously called
1597    for projectWindowIntoObject to produce valid values.  As per OpenGL
1598    windows coordinates are calculated relative to the bottom left of the window.*/
1599bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg::Vec3& far_point) const
1600{
1601    osg::Matrix inverseMVPW;
1602    inverseMVPW.invert(computeMVPW());
1603   
1604    near_point = osg::Vec3(x,y,0.0f)*inverseMVPW;
1605    far_point = osg::Vec3(x,y,1.0f)*inverseMVPW;
1606       
1607    return true;
1608}
1609
1610
1611/** Calculate, via glProject, the object coordinates of a window.
1612    Note, current implementation requires that SceneView::draw() has been previously called
1613    for projectWindowIntoObject to produce valid values.  As per OpenGL
1614    windows coordinates are calculated relative to the bottom left of the window.*/
1615bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const
1616{
1617    window = object*computeMVPW();
1618    return true;
1619}
1620
1621const osg::Matrix SceneView::computeMVPW() const
1622{
1623    osg::Matrix matrix( getViewMatrix() * getProjectionMatrix());
1624       
1625    if (getViewport())
1626        matrix.postMult(getViewport()->computeWindowMatrix());
1627    else
1628        osg::notify(osg::WARN)<<"osg::Matrix SceneView::computeMVPW() - error no viewport attached to SceneView, coords will be computed inccorectly."<<std::endl;
1629
1630    return matrix;
1631}
1632
1633void SceneView::clearArea(int x,int y,int width,int height,const osg::Vec4& color)
1634{
1635    osg::ref_ptr<osg::Viewport> viewport = new osg::Viewport;
1636    viewport->setViewport(x,y,width,height);
1637
1638    _renderInfo.getState()->applyAttribute(viewport.get());
1639   
1640    glScissor( x, y, width, height );
1641    glEnable( GL_SCISSOR_TEST );
1642    glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1643    glClearColor( color[0], color[1], color[2], color[3]);
1644    glClear( GL_COLOR_BUFFER_BIT);
1645    glDisable( GL_SCISSOR_TEST );
1646}
1647
1648void SceneView::setProjectionMatrixAsOrtho(double left, double right,
1649                                           double bottom, double top,
1650                                           double zNear, double zFar)
1651{
1652    setProjectionMatrix(osg::Matrixd::ortho(left, right,
1653                                           bottom, top,
1654                                           zNear, zFar));
1655}                                           
1656
1657void SceneView::setProjectionMatrixAsOrtho2D(double left, double right,
1658                                             double bottom, double top)
1659{
1660    setProjectionMatrix(osg::Matrixd::ortho2D(left, right,
1661                                             bottom, top));
1662}
1663
1664void SceneView::setProjectionMatrixAsFrustum(double left, double right,
1665                                             double bottom, double top,
1666                                             double zNear, double zFar)
1667{
1668    setProjectionMatrix(osg::Matrixd::frustum(left, right,
1669                                             bottom, top,
1670                                             zNear, zFar));
1671}
1672
1673void SceneView::setProjectionMatrixAsPerspective(double fovy,double aspectRatio,
1674                                                 double zNear, double zFar)
1675{
1676    setProjectionMatrix(osg::Matrixd::perspective(fovy,aspectRatio,
1677                                                 zNear, zFar));
1678}                                     
1679
1680bool SceneView::getProjectionMatrixAsOrtho(double& left, double& right,
1681                                           double& bottom, double& top,
1682                                           double& zNear, double& zFar) const
1683{
1684    return getProjectionMatrix().getOrtho(left, right,
1685                                       bottom, top,
1686                                       zNear, zFar);
1687}
1688
1689bool SceneView::getProjectionMatrixAsFrustum(double& left, double& right,
1690                                             double& bottom, double& top,
1691                                             double& zNear, double& zFar) const
1692{
1693    return getProjectionMatrix().getFrustum(left, right,
1694                                         bottom, top,
1695                                         zNear, zFar);
1696}                                 
1697
1698bool SceneView::getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio,
1699                                                 double& zNear, double& zFar) const
1700{
1701    return getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1702}                                                 
1703
1704void SceneView::setViewMatrixAsLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
1705{
1706    setViewMatrix(osg::Matrixd::lookAt(eye,center,up));
1707}
1708
1709void SceneView::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance) const
1710{
1711    getViewMatrix().getLookAt(eye,center,up,lookDistance);
1712}
1713
1714bool SceneView::getStats(Statistics& stats)
1715{
1716    if (_displaySettings.valid() && _displaySettings->getStereo())
1717    {
1718        switch(_displaySettings->getStereoMode())
1719        {
1720        case(osg::DisplaySettings::QUAD_BUFFER):
1721        case(osg::DisplaySettings::ANAGLYPHIC):
1722        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
1723        case(osg::DisplaySettings::VERTICAL_SPLIT):
1724        case(osg::DisplaySettings::VERTICAL_INTERLACE):
1725        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1726        {
1727            bool resultLeft = _renderStageLeft->getStats(stats);
1728            bool resultRight = _renderStageRight->getStats(stats);
1729            return resultLeft && resultRight;
1730        }
1731        case(osg::DisplaySettings::RIGHT_EYE):
1732        case(osg::DisplaySettings::LEFT_EYE):
1733        default:
1734            return _renderStage->getStats(stats);
1735        }
1736    }
1737    else
1738    {
1739        return _renderStage->getStats(stats);
1740    }
1741}
1742
1743void SceneView::collateReferencesToDependentCameras()
1744{
1745    if (_renderStage.valid()) _renderStage->collateReferencesToDependentCameras();
1746    if (_renderStageLeft.valid()) _renderStageLeft->collateReferencesToDependentCameras();
1747    if (_renderStageRight.valid()) _renderStageRight->collateReferencesToDependentCameras();
1748}
1749
1750void SceneView::clearReferencesToDependentCameras()
1751{
1752    if (_renderStage.valid()) _renderStage->clearReferencesToDependentCameras();
1753    if (_renderStageLeft.valid()) _renderStageLeft->clearReferencesToDependentCameras();
1754    if (_renderStageRight.valid()) _renderStageRight->clearReferencesToDependentCameras();
1755}
Note: See TracBrowser for help on using the browser.