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

Revision 10895, 60.9 kB (checked in by robert, 4 years ago)

Fixed warning

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