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