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

Revision 10595, 66.5 kB (checked in by robert, 5 years ago)

Improved the computation of the TextureProfile? _size value, fixed the computation up of the miplevels

  • 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    if (!_initCalled) init();
1029
1030    // note, to support multi-pipe systems the deletion of OpenGL display list
1031    // and texture objects is deferred until the OpenGL context is the correct
1032    // context for when the object were originally created.  Here we know what
1033    // context we are in so can flush the appropriate caches.
1034   
1035    if (_requiresFlush)
1036    {
1037        double availableTime = 0.005;
1038        flushDeletedGLObjects(availableTime);
1039    }
1040
1041    // assume the the draw which is about to happen could generate GL objects that need flushing in the next frame.
1042    _requiresFlush = true;
1043
1044    state->setInitialViewMatrix(new osg::RefMatrix(getViewMatrix()));
1045
1046    RenderLeaf* previous = NULL;
1047    if (_displaySettings.valid() && _displaySettings->getStereo())
1048    {
1049   
1050        switch(_displaySettings->getStereoMode())
1051        {
1052        case(osg::DisplaySettings::QUAD_BUFFER):
1053            {
1054
1055                _localStateSet->setAttribute(getViewport());
1056
1057                // ensure that all color planes are active.
1058                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1059                if (cmask)
1060                {
1061                    cmask->setMask(true,true,true,true);
1062                }
1063                else
1064                {
1065                    cmask = new osg::ColorMask(true,true,true,true);
1066                    _localStateSet->setAttribute(cmask);
1067                }
1068                _renderStageLeft->setColorMask(cmask);
1069                _renderStageRight->setColorMask(cmask);
1070
1071                _renderStageLeft->setDrawBuffer(GL_BACK_LEFT);
1072                _renderStageLeft->setReadBuffer(GL_BACK_LEFT);
1073                _renderStageRight->setDrawBuffer(GL_BACK_RIGHT);
1074                _renderStageRight->setReadBuffer(GL_BACK_RIGHT);
1075
1076                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1077                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1078
1079                _renderStageLeft->draw(_renderInfo,previous);
1080
1081                _renderStageRight->draw(_renderInfo,previous);
1082
1083            }
1084            break;
1085        case(osg::DisplaySettings::ANAGLYPHIC):
1086            {
1087                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) )
1088                {
1089                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1090                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1091
1092                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1093                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1094                }
1095               
1096                _localStateSet->setAttribute(getViewport());
1097
1098               
1099                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1100                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1101
1102
1103                // ensure that left eye color planes are active.
1104                osg::ColorMask* leftColorMask = _renderStageLeft->getColorMask();
1105                if (!leftColorMask)
1106                {
1107                    leftColorMask = new osg::ColorMask();
1108                    _renderStageLeft->setColorMask(leftColorMask);
1109                }
1110               
1111                // red
1112                leftColorMask->setMask(true,false,false,true);
1113
1114                // orange
1115                // leftColorMask->setMask(true,true,false,true);
1116
1117                _localStateSet->setAttribute(leftColorMask);
1118
1119                // draw left eye.
1120                _renderStageLeft->draw(_renderInfo,previous);
1121               
1122               
1123
1124                // ensure that right eye color planes are active.
1125                osg::ColorMask* rightColorMask = _renderStageRight->getColorMask();
1126                if (!rightColorMask)
1127                {
1128                    rightColorMask = new osg::ColorMask();
1129                    _renderStageRight->setColorMask(rightColorMask);
1130                }
1131
1132                // cyan
1133                rightColorMask->setMask(false,true,true,true);
1134               
1135                // blue
1136                // rightColorMask->setMask(false,false,true,true);
1137
1138                _localStateSet->setAttribute(rightColorMask);
1139
1140                // draw right eye.
1141                _renderStageRight->draw(_renderInfo,previous);
1142
1143            }
1144            break;
1145        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
1146            {
1147                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1148                {
1149                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1150                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1151
1152                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1153                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1154                }
1155
1156                // ensure that all color planes are active.
1157                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1158                if (cmask)
1159                {
1160                    cmask->setMask(true,true,true,true);
1161                }
1162                else
1163                {
1164                    cmask = new osg::ColorMask(true,true,true,true);
1165                    _localStateSet->setAttribute(cmask);
1166                }
1167                _renderStageLeft->setColorMask(cmask);
1168                _renderStageRight->setColorMask(cmask);
1169
1170                _localStateSet->setAttribute(_viewportLeft.get());
1171                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1172
1173                _localStateSet->setAttribute(_viewportRight.get());
1174                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1175
1176                double separation = _displaySettings->getSplitStereoHorizontalSeparation();
1177
1178                double  left_half_width = (getViewport()->width()-separation)/2.0;
1179
1180                clearArea(static_cast<int>(getViewport()->x()+left_half_width),
1181                          static_cast<int>(getViewport()->y()),
1182                          static_cast<int>(separation),
1183                          static_cast<int>(getViewport()->height()),_renderStageLeft->getClearColor());
1184
1185             
1186                _localStateSet->setAttribute(_viewportLeft.get());
1187                _renderStageLeft->draw(_renderInfo,previous);
1188
1189                _localStateSet->setAttribute(_viewportRight.get());
1190                _renderStageRight->draw(_renderInfo,previous);
1191
1192            }
1193            break;
1194        case(osg::DisplaySettings::VERTICAL_SPLIT):
1195            {
1196                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1197                {
1198                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1199                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1200
1201                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1202                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1203                }
1204
1205                // ensure that all color planes are active.
1206                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1207                if (cmask)
1208                {
1209                    cmask->setMask(true,true,true,true);
1210                }
1211                else
1212                {
1213                    cmask = new osg::ColorMask(true,true,true,true);
1214                    _localStateSet->setAttribute(cmask);
1215                }
1216
1217                _renderStageLeft->setColorMask(cmask);
1218                _renderStageRight->setColorMask(cmask);
1219
1220                _localStateSet->setAttribute(_viewportLeft.get());
1221                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1222
1223                _localStateSet->setAttribute(_viewportRight.get());
1224                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1225
1226                double separation = _displaySettings->getSplitStereoVerticalSeparation();
1227
1228                double bottom_half_height = (getViewport()->height()-separation)/2.0;
1229
1230                clearArea(static_cast<int>(getViewport()->x()),
1231                          static_cast<int>(getViewport()->y()+bottom_half_height),
1232                          static_cast<int>(getViewport()->width()),
1233                          static_cast<int>(separation),
1234                          _renderStageLeft->getClearColor());
1235
1236                _localStateSet->setAttribute(_viewportLeft.get());
1237                _renderStageLeft->draw(_renderInfo,previous);
1238
1239                _localStateSet->setAttribute(_viewportRight.get());
1240                _renderStageRight->draw(_renderInfo,previous);
1241            }
1242            break;
1243        case(osg::DisplaySettings::RIGHT_EYE):
1244        case(osg::DisplaySettings::LEFT_EYE):
1245            {
1246                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1247                {
1248                    _renderStage->setDrawBuffer(_camera->getDrawBuffer());
1249                    _renderStage->setReadBuffer(_camera->getDrawBuffer());
1250                }
1251
1252                // ensure that all color planes are active.
1253                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1254                if (cmask)
1255                {
1256                    cmask->setMask(true,true,true,true);
1257                }
1258                else
1259                {
1260                    cmask = new osg::ColorMask(true,true,true,true);
1261                    _localStateSet->setAttribute(cmask);
1262                }
1263                _renderStage->setColorMask(cmask);
1264                _renderStage->setColorMask(cmask);
1265
1266                _localStateSet->setAttribute(getViewport());
1267                _renderStage->drawPreRenderStages(_renderInfo,previous);
1268                _renderStage->draw(_renderInfo,previous);
1269            }
1270            break;
1271        case(osg::DisplaySettings::VERTICAL_INTERLACE):
1272            {
1273                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1274                {
1275                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1276                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1277                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1278                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1279                }
1280                _localStateSet->setAttribute(getViewport());
1281
1282                // ensure that all color planes are active.
1283                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1284                if (cmask)
1285                {
1286                    cmask->setMask(true,true,true,true);
1287                }
1288                else
1289                {
1290                    cmask = new osg::ColorMask(true,true,true,true);
1291                    _localStateSet->setAttribute(cmask);
1292                }
1293                _renderStageLeft->setColorMask(cmask);
1294                _renderStageRight->setColorMask(cmask);
1295
1296                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1297                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1298
1299                glEnable(GL_STENCIL_TEST);
1300
1301                if(_redrawInterlacedStereoStencilMask ||
1302                   _interlacedStereoStencilWidth != getViewport()->width() ||
1303                  _interlacedStereoStencilHeight != getViewport()->height() )
1304                {
1305                    getViewport()->apply(*state);
1306                    glMatrixMode(GL_PROJECTION);
1307                    glLoadIdentity();
1308                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1309                    glMatrixMode(GL_MODELVIEW);
1310                    glLoadIdentity();   
1311                    getState()->applyMode(GL_LIGHTING,false);
1312                    getState()->applyMode(GL_DEPTH_TEST,false);
1313                    glStencilMask(~0u);
1314                    glClear(GL_STENCIL_BUFFER_BIT);
1315                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1316                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1317                    glPolygonStipple(patternVertEven);
1318                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1319                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1320                   
1321                    glRecti(static_cast<GLint>(getViewport()->x()),
1322                            static_cast<GLint>(getViewport()->y()),
1323                            static_cast<GLint>(getViewport()->width()),
1324                            static_cast<GLint>(getViewport()->height()) );
1325                           
1326                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1327                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1328                    getState()->applyMode(GL_LIGHTING,true);
1329                    getState()->applyMode(GL_DEPTH_TEST,true);
1330                   
1331                    _redrawInterlacedStereoStencilMask = false;
1332                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1333                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1334                }
1335
1336                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1337                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1338
1339                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1340                glStencilFunc(GL_EQUAL, 0, ~0u);   
1341                _renderStageLeft->draw(_renderInfo,previous);
1342               
1343                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1344                _renderStageRight->draw(_renderInfo,previous);
1345                glDisable(GL_STENCIL_TEST);
1346            }
1347            break;
1348        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1349            {
1350                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1351                {
1352                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1353                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1354                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1355                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1356                }
1357                _localStateSet->setAttribute(getViewport());
1358
1359                // ensure that all color planes are active.
1360                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1361                if (cmask)
1362                {
1363                    cmask->setMask(true,true,true,true);
1364                }
1365                else
1366                {
1367                    cmask = new osg::ColorMask(true,true,true,true);
1368                    _localStateSet->setAttribute(cmask);
1369                }
1370                _renderStageLeft->setColorMask(cmask);
1371                _renderStageRight->setColorMask(cmask);
1372
1373                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1374                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1375
1376                glEnable(GL_STENCIL_TEST);
1377
1378                if(_redrawInterlacedStereoStencilMask ||
1379                   _interlacedStereoStencilWidth != getViewport()->width() ||
1380                  _interlacedStereoStencilHeight != getViewport()->height() )
1381                {
1382                    getViewport()->apply(*state);
1383                    glMatrixMode(GL_PROJECTION);
1384                    glLoadIdentity();
1385                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1386                    glMatrixMode(GL_MODELVIEW);
1387                    glLoadIdentity();
1388                    getState()->applyMode(GL_LIGHTING,false);
1389                    getState()->applyMode(GL_DEPTH_TEST,false);
1390                    glStencilMask(~0u);
1391                    glClear(GL_STENCIL_BUFFER_BIT);
1392                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1393                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1394                    glPolygonStipple(patternHorzEven);
1395                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1396                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1397
1398                    glRecti(static_cast<GLint>(getViewport()->x()),
1399                            static_cast<GLint>(getViewport()->y()),
1400                            static_cast<GLint>(getViewport()->width()),
1401                            static_cast<GLint>(getViewport()->height()) );
1402                           
1403                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1404                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1405                    getState()->applyMode(GL_LIGHTING,true);
1406                    getState()->applyMode(GL_DEPTH_TEST,true);
1407                   
1408                    _redrawInterlacedStereoStencilMask = false;
1409                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1410                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1411                }
1412
1413                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1414                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1415
1416                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1417                glStencilFunc(GL_EQUAL, 0, ~0u);   
1418                _renderStageLeft->draw(_renderInfo,previous);
1419               
1420                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1421                _renderStageRight->draw(_renderInfo,previous);
1422                glDisable(GL_STENCIL_TEST);
1423            }
1424            break;
1425        case(osg::DisplaySettings::CHECKERBOARD):
1426            {
1427                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1428                {
1429                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1430                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1431                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1432                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1433                }
1434                _localStateSet->setAttribute(getViewport());
1435
1436                // ensure that all color planes are active.
1437                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1438                if (cmask)
1439                {
1440                    cmask->setMask(true,true,true,true);
1441                }
1442                else
1443                {
1444                    cmask = new osg::ColorMask(true,true,true,true);
1445                    _localStateSet->setAttribute(cmask);
1446                }
1447                _renderStageLeft->setColorMask(cmask);
1448                _renderStageRight->setColorMask(cmask);
1449
1450                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1451                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1452
1453                glEnable(GL_STENCIL_TEST);
1454
1455                if(_redrawInterlacedStereoStencilMask ||
1456                   _interlacedStereoStencilWidth != getViewport()->width() ||
1457                  _interlacedStereoStencilHeight != getViewport()->height() )
1458                {
1459                    getViewport()->apply(*state);
1460                    glMatrixMode(GL_PROJECTION);
1461                    glLoadIdentity();
1462                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1463                    glMatrixMode(GL_MODELVIEW);
1464                    glLoadIdentity();
1465                    glDisable(GL_LIGHTING);
1466                    glDisable(GL_DEPTH_TEST);
1467                    glStencilMask(~0u);
1468                    glClear(GL_STENCIL_BUFFER_BIT);
1469                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1470                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1471                    glPolygonStipple(patternCheckerboard);
1472                    glEnable(GL_POLYGON_STIPPLE);
1473                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1474
1475                    glRecti(static_cast<GLint>(getViewport()->x()),
1476                            static_cast<GLint>(getViewport()->y()),
1477                            static_cast<GLint>(getViewport()->width()),
1478                            static_cast<GLint>(getViewport()->height()) );
1479                           
1480                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1481                    glDisable(GL_POLYGON_STIPPLE);
1482                    glEnable(GL_LIGHTING);
1483                    glEnable(GL_DEPTH_TEST);
1484                   
1485                    _redrawInterlacedStereoStencilMask = false;
1486                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1487                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1488                }
1489
1490                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1491                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1492
1493                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1494                glStencilFunc(GL_EQUAL, 0, ~0u);   
1495                _renderStageLeft->draw(_renderInfo,previous);
1496               
1497                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1498                _renderStageRight->draw(_renderInfo,previous);
1499                glDisable(GL_STENCIL_TEST);
1500            }
1501            break;
1502        default:
1503            {
1504                osg::notify(osg::NOTICE)<<"Warning: stereo mode not implemented yet."<< std::endl;
1505            }
1506            break;
1507        }
1508    }
1509    else
1510    {
1511
1512        // Need to restore draw buffer when toggling Stereo off.
1513        if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) )
1514        {
1515            _renderStage->setDrawBuffer(_camera->getDrawBuffer());
1516            _renderStage->setReadBuffer(_camera->getDrawBuffer());
1517        }
1518
1519        if( 0 == ( _camera->getInheritanceMask() & READ_BUFFER ) )
1520        {
1521            _renderStage->setReadBuffer(_camera->getReadBuffer());
1522        }
1523
1524        _localStateSet->setAttribute(getViewport());
1525
1526
1527        // ensure that all color planes are active.
1528        osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1529        if (cmask)
1530        {
1531            cmask->setMask(true,true,true,true);
1532        }
1533        else
1534        {
1535            cmask = new osg::ColorMask(true,true,true,true);
1536            _localStateSet->setAttribute(cmask);
1537        }
1538        _renderStage->setColorMask(cmask);
1539
1540        // bog standard draw.
1541        _renderStage->drawPreRenderStages(_renderInfo,previous);
1542        _renderStage->draw(_renderInfo,previous);
1543    }
1544   
1545    // re apply the defalt OGL state.
1546    state->popAllStateSets();
1547    state->apply();
1548
1549#if 0
1550    if (_camera->getPostDrawCallback())
1551    {
1552        (*(_camera->getPostDrawCallback()))(*_camera);
1553    }
1554#endif
1555
1556    if (state->getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
1557    {
1558        if (state->checkGLErrors("end of SceneView::draw()"))
1559        {
1560            // go into debug mode of OGL error in a fine grained way to help
1561            // track down OpenGL errors.
1562            state->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
1563        }
1564    }
1565
1566// #define REPORT_TEXTURE_MANAGER_STATS
1567#ifdef REPORT_TEXTURE_MANAGER_STATS
1568    tom->reportStats();
1569#endif
1570
1571    // osg::notify(osg::NOTICE)<<"SceneView  draw() DynamicObjectCount"<<getState()->getDynamicObjectCount()<<std::endl;
1572
1573}
1574
1575/** Calculate, via glUnProject, the object coordinates of a window point.
1576    Note, current implementation requires that SceneView::draw() has been previously called
1577    for projectWindowIntoObject to produce valid values.  As per OpenGL
1578    windows coordinates are calculated relative to the bottom left of the window.*/
1579bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& object) const
1580{
1581    osg::Matrix inverseMVPW;
1582    inverseMVPW.invert(computeMVPW());
1583   
1584    object = window*inverseMVPW;
1585   
1586    return true;
1587}
1588
1589
1590/** Calculate, via glUnProject, the object coordinates of a window x,y
1591    when projected onto the near and far planes.
1592    Note, current implementation requires that SceneView::draw() has been previously called
1593    for projectWindowIntoObject to produce valid values.  As per OpenGL
1594    windows coordinates are calculated relative to the bottom left of the window.*/
1595bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg::Vec3& far_point) const
1596{
1597    osg::Matrix inverseMVPW;
1598    inverseMVPW.invert(computeMVPW());
1599   
1600    near_point = osg::Vec3(x,y,0.0f)*inverseMVPW;
1601    far_point = osg::Vec3(x,y,1.0f)*inverseMVPW;
1602       
1603    return true;
1604}
1605
1606
1607/** Calculate, via glProject, the object coordinates of a window.
1608    Note, current implementation requires that SceneView::draw() has been previously called
1609    for projectWindowIntoObject to produce valid values.  As per OpenGL
1610    windows coordinates are calculated relative to the bottom left of the window.*/
1611bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const
1612{
1613    window = object*computeMVPW();
1614    return true;
1615}
1616
1617const osg::Matrix SceneView::computeMVPW() const
1618{
1619    osg::Matrix matrix( getViewMatrix() * getProjectionMatrix());
1620       
1621    if (getViewport())
1622        matrix.postMult(getViewport()->computeWindowMatrix());
1623    else
1624        osg::notify(osg::WARN)<<"osg::Matrix SceneView::computeMVPW() - error no viewport attached to SceneView, coords will be computed inccorectly."<<std::endl;
1625
1626    return matrix;
1627}
1628
1629void SceneView::clearArea(int x,int y,int width,int height,const osg::Vec4& color)
1630{
1631    osg::ref_ptr<osg::Viewport> viewport = new osg::Viewport;
1632    viewport->setViewport(x,y,width,height);
1633
1634    _renderInfo.getState()->applyAttribute(viewport.get());
1635   
1636    glScissor( x, y, width, height );
1637    glEnable( GL_SCISSOR_TEST );
1638    glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1639    glClearColor( color[0], color[1], color[2], color[3]);
1640    glClear( GL_COLOR_BUFFER_BIT);
1641    glDisable( GL_SCISSOR_TEST );
1642}
1643
1644void SceneView::setProjectionMatrixAsOrtho(double left, double right,
1645                                           double bottom, double top,
1646                                           double zNear, double zFar)
1647{
1648    setProjectionMatrix(osg::Matrixd::ortho(left, right,
1649                                           bottom, top,
1650                                           zNear, zFar));
1651}                                           
1652
1653void SceneView::setProjectionMatrixAsOrtho2D(double left, double right,
1654                                             double bottom, double top)
1655{
1656    setProjectionMatrix(osg::Matrixd::ortho2D(left, right,
1657                                             bottom, top));
1658}
1659
1660void SceneView::setProjectionMatrixAsFrustum(double left, double right,
1661                                             double bottom, double top,
1662                                             double zNear, double zFar)
1663{
1664    setProjectionMatrix(osg::Matrixd::frustum(left, right,
1665                                             bottom, top,
1666                                             zNear, zFar));
1667}
1668
1669void SceneView::setProjectionMatrixAsPerspective(double fovy,double aspectRatio,
1670                                                 double zNear, double zFar)
1671{
1672    setProjectionMatrix(osg::Matrixd::perspective(fovy,aspectRatio,
1673                                                 zNear, zFar));
1674}                                     
1675
1676bool SceneView::getProjectionMatrixAsOrtho(double& left, double& right,
1677                                           double& bottom, double& top,
1678                                           double& zNear, double& zFar) const
1679{
1680    return getProjectionMatrix().getOrtho(left, right,
1681                                       bottom, top,
1682                                       zNear, zFar);
1683}
1684
1685bool SceneView::getProjectionMatrixAsFrustum(double& left, double& right,
1686                                             double& bottom, double& top,
1687                                             double& zNear, double& zFar) const
1688{
1689    return getProjectionMatrix().getFrustum(left, right,
1690                                         bottom, top,
1691                                         zNear, zFar);
1692}                                 
1693
1694bool SceneView::getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio,
1695                                                 double& zNear, double& zFar) const
1696{
1697    return getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1698}                                                 
1699
1700void SceneView::setViewMatrixAsLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
1701{
1702    setViewMatrix(osg::Matrixd::lookAt(eye,center,up));
1703}
1704
1705void SceneView::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance) const
1706{
1707    getViewMatrix().getLookAt(eye,center,up,lookDistance);
1708}
1709
1710bool SceneView::getStats(Statistics& stats)
1711{
1712    if (_displaySettings.valid() && _displaySettings->getStereo())
1713    {
1714        switch(_displaySettings->getStereoMode())
1715        {
1716        case(osg::DisplaySettings::QUAD_BUFFER):
1717        case(osg::DisplaySettings::ANAGLYPHIC):
1718        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
1719        case(osg::DisplaySettings::VERTICAL_SPLIT):
1720        case(osg::DisplaySettings::VERTICAL_INTERLACE):
1721        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1722        {
1723            bool resultLeft = _renderStageLeft->getStats(stats);
1724            bool resultRight = _renderStageRight->getStats(stats);
1725            return resultLeft && resultRight;
1726        }
1727        case(osg::DisplaySettings::RIGHT_EYE):
1728        case(osg::DisplaySettings::LEFT_EYE):
1729        default:
1730            return _renderStage->getStats(stats);
1731        }
1732    }
1733    else
1734    {
1735        return _renderStage->getStats(stats);
1736    }
1737}
1738
1739void SceneView::collateReferencesToDependentCameras()
1740{
1741    if (_renderStage.valid()) _renderStage->collateReferencesToDependentCameras();
1742    if (_renderStageLeft.valid()) _renderStageLeft->collateReferencesToDependentCameras();
1743    if (_renderStageRight.valid()) _renderStageRight->collateReferencesToDependentCameras();
1744}
1745
1746void SceneView::clearReferencesToDependentCameras()
1747{
1748    if (_renderStage.valid()) _renderStage->clearReferencesToDependentCameras();
1749    if (_renderStageLeft.valid()) _renderStageLeft->clearReferencesToDependentCameras();
1750    if (_renderStageRight.valid()) _renderStageRight->clearReferencesToDependentCameras();
1751}
Note: See TracBrowser for help on using the browser.