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