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