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

Revision 7074, 57.8 kB (checked in by robert, 7 years ago)

Added include/osg/GLObjects + .cpp which provide osg::flush*DeletedGLObjects() methods.

Added and cleaned up DeleteHandler? calls in osgViewer to help avoid crashes on exit.

Changed DatabasePager? across to dynamically checcking osg::getCompileContext(..)

Updated wrappers.

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