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

Revision 7062, 59.8 kB (checked in by robert, 7 years ago)

Changed the way that computeNearFar is computed to avoid inconsistencies when in stereo mode

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