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

Revision 10915, 60.9 kB (checked in by robert, 4 years ago)

Added support for call root Camera CullCallbacks?

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