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