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

Revision 10765, 68.5 kB (checked in by robert, 5 years ago)

Moved across to use OSG_FIXED_FUNCTION_AVAILABLE

  • 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            {
1294            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
1295                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1296                {
1297                    _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1298                    _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1299                    _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1300                    _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1301                }
1302                _localStateSet->setAttribute(getViewport());
1303
1304                // ensure that all color planes are active.
1305                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1306                if (cmask)
1307                {
1308                    cmask->setMask(true,true,true,true);
1309                }
1310                else
1311                {
1312                    cmask = new osg::ColorMask(true,true,true,true);
1313                    _localStateSet->setAttribute(cmask);
1314                }
1315                _renderStageLeft->setColorMask(cmask);
1316                _renderStageRight->setColorMask(cmask);
1317
1318                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1319                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1320
1321                glEnable(GL_STENCIL_TEST);
1322
1323                if(_redrawInterlacedStereoStencilMask ||
1324                   _interlacedStereoStencilWidth != getViewport()->width() ||
1325                  _interlacedStereoStencilHeight != getViewport()->height() )
1326                {
1327                    state->applyProjectionMatrix(0);
1328                    glMatrixMode(GL_PROJECTION);
1329                    glLoadIdentity();
1330                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1331                    glMatrixMode(GL_MODELVIEW);
1332                    glLoadIdentity();   
1333                   
1334                    getViewport()->apply(*state);
1335                    getState()->applyMode(GL_LIGHTING,false);
1336                    getState()->applyMode(GL_DEPTH_TEST,false);
1337                    glStencilMask(~0u);
1338                    glClear(GL_STENCIL_BUFFER_BIT);
1339                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1340                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1341                    glPolygonStipple(patternVertEven);
1342                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1343                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1344                   
1345                    glRecti(static_cast<GLint>(getViewport()->x()),
1346                            static_cast<GLint>(getViewport()->y()),
1347                            static_cast<GLint>(getViewport()->width()),
1348                            static_cast<GLint>(getViewport()->height()) );
1349                           
1350                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1351                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1352                    getState()->applyMode(GL_LIGHTING,true);
1353                    getState()->applyMode(GL_DEPTH_TEST,true);
1354                   
1355                    _redrawInterlacedStereoStencilMask = false;
1356                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1357                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1358                }
1359
1360                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1361                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1362
1363                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1364                glStencilFunc(GL_EQUAL, 0, ~0u);   
1365                _renderStageLeft->draw(_renderInfo,previous);
1366               
1367                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1368                _renderStageRight->draw(_renderInfo,previous);
1369                glDisable(GL_STENCIL_TEST);
1370            #else
1371                osg::notify(osg::NOTICE)<<"Warning: SceneView::draw() - VERTICAL_INTERLACE stereo not supported."<<std::endl;
1372            #endif
1373            }
1374            break;
1375        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1376            {
1377            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
1378                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1379                {
1380                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1381                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1382                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1383                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1384                }
1385                _localStateSet->setAttribute(getViewport());
1386
1387                // ensure that all color planes are active.
1388                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1389                if (cmask)
1390                {
1391                    cmask->setMask(true,true,true,true);
1392                }
1393                else
1394                {
1395                    cmask = new osg::ColorMask(true,true,true,true);
1396                    _localStateSet->setAttribute(cmask);
1397                }
1398                _renderStageLeft->setColorMask(cmask);
1399                _renderStageRight->setColorMask(cmask);
1400
1401                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1402                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1403
1404                glEnable(GL_STENCIL_TEST);
1405
1406                if(_redrawInterlacedStereoStencilMask ||
1407                   _interlacedStereoStencilWidth != getViewport()->width() ||
1408                  _interlacedStereoStencilHeight != getViewport()->height() )
1409                {
1410                    glMatrixMode(GL_PROJECTION);
1411                    glLoadIdentity();
1412                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1413                    glMatrixMode(GL_MODELVIEW);
1414                    glLoadIdentity();
1415                   
1416                    getViewport()->apply(*state);
1417                    getState()->applyMode(GL_LIGHTING,false);
1418                    getState()->applyMode(GL_DEPTH_TEST,false);
1419                    glStencilMask(~0u);
1420                    glClear(GL_STENCIL_BUFFER_BIT);
1421                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1422                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1423                    glPolygonStipple(patternHorzEven);
1424                    getState()->applyMode(GL_POLYGON_STIPPLE,true);
1425                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1426
1427                    glRecti(static_cast<GLint>(getViewport()->x()),
1428                            static_cast<GLint>(getViewport()->y()),
1429                            static_cast<GLint>(getViewport()->width()),
1430                            static_cast<GLint>(getViewport()->height()) );
1431                           
1432                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1433                    getState()->applyMode(GL_POLYGON_STIPPLE,false);
1434                    getState()->applyMode(GL_LIGHTING,true);
1435                    getState()->applyMode(GL_DEPTH_TEST,true);
1436                   
1437                    _redrawInterlacedStereoStencilMask = false;
1438                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1439                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1440                }
1441
1442                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1443                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1444
1445                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1446                glStencilFunc(GL_EQUAL, 0, ~0u);   
1447                _renderStageLeft->draw(_renderInfo,previous);
1448               
1449                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1450                _renderStageRight->draw(_renderInfo,previous);
1451                glDisable(GL_STENCIL_TEST);
1452            #else
1453                osg::notify(osg::NOTICE)<<"Warning: SceneView::draw() - HORIZONTAL_INTERLACE stereo not supported."<<std::endl;
1454            #endif
1455            }
1456            break;
1457        case(osg::DisplaySettings::CHECKERBOARD):
1458            {
1459            #if !defined(OSG_GLES1_AVAILABLE) && !defined(OSG_GLES2_AVAILABLE) && !defined(OSG_GL3_AVAILABLE)
1460                if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER) )
1461                {
1462                _renderStageLeft->setDrawBuffer(_camera->getDrawBuffer());
1463                _renderStageLeft->setReadBuffer(_camera->getDrawBuffer());
1464                _renderStageRight->setDrawBuffer(_camera->getDrawBuffer());
1465                _renderStageRight->setReadBuffer(_camera->getDrawBuffer());
1466                }
1467                _localStateSet->setAttribute(getViewport());
1468
1469                // ensure that all color planes are active.
1470                osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1471                if (cmask)
1472                {
1473                    cmask->setMask(true,true,true,true);
1474                }
1475                else
1476                {
1477                    cmask = new osg::ColorMask(true,true,true,true);
1478                    _localStateSet->setAttribute(cmask);
1479                }
1480                _renderStageLeft->setColorMask(cmask);
1481                _renderStageRight->setColorMask(cmask);
1482
1483                _renderStageLeft->drawPreRenderStages(_renderInfo,previous);
1484                _renderStageRight->drawPreRenderStages(_renderInfo,previous);
1485
1486                glEnable(GL_STENCIL_TEST);
1487
1488                if(_redrawInterlacedStereoStencilMask ||
1489                   _interlacedStereoStencilWidth != getViewport()->width() ||
1490                  _interlacedStereoStencilHeight != getViewport()->height() )
1491                {
1492
1493                    glMatrixMode(GL_PROJECTION);
1494                    glLoadIdentity();
1495                    glOrtho(getViewport()->x(), getViewport()->width(), getViewport()->y(), getViewport()->height(), -1.0, 1.0);
1496                    glMatrixMode(GL_MODELVIEW);
1497                    glLoadIdentity();
1498                   
1499                   
1500                    getViewport()->apply(*state);
1501                    glDisable(GL_LIGHTING);
1502                    glDisable(GL_DEPTH_TEST);
1503                    glStencilMask(~0u);
1504                    glClear(GL_STENCIL_BUFFER_BIT);
1505                    glStencilOp(GL_REPLACE, GL_REPLACE, GL_REPLACE);
1506                    glStencilFunc(GL_ALWAYS, 1, ~0u);
1507                    glPolygonStipple(patternCheckerboard);
1508                    glEnable(GL_POLYGON_STIPPLE);
1509                    glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE);
1510
1511                    glRecti(static_cast<GLint>(getViewport()->x()),
1512                            static_cast<GLint>(getViewport()->y()),
1513                            static_cast<GLint>(getViewport()->width()),
1514                            static_cast<GLint>(getViewport()->height()) );
1515                           
1516                    glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
1517                    glDisable(GL_POLYGON_STIPPLE);
1518                    glEnable(GL_LIGHTING);
1519                    glEnable(GL_DEPTH_TEST);
1520                   
1521                    _redrawInterlacedStereoStencilMask = false;
1522                    _interlacedStereoStencilWidth = static_cast<int>(getViewport()->width());
1523                    _interlacedStereoStencilHeight = static_cast<int>(getViewport()->height());
1524                }
1525
1526                _renderStageLeft->setClearMask(_renderStageLeft->getClearMask() & ~(GL_STENCIL_BUFFER_BIT));
1527                _renderStageRight->setClearMask(_renderStageRight->getClearMask() & ~(GL_STENCIL_BUFFER_BIT|GL_COLOR_BUFFER_BIT));
1528
1529                glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
1530                glStencilFunc(GL_EQUAL, 0, ~0u);   
1531                _renderStageLeft->draw(_renderInfo,previous);
1532               
1533                glStencilFunc(GL_NOTEQUAL, 0, ~0u);
1534                _renderStageRight->draw(_renderInfo,previous);
1535                glDisable(GL_STENCIL_TEST);
1536            #else
1537                osg::notify(osg::NOTICE)<<"Warning: SceneView::draw() - CHECKERBOARD stereo not supported."<<std::endl;
1538            #endif
1539            }
1540            break;
1541        default:
1542            {
1543                osg::notify(osg::NOTICE)<<"Warning: stereo mode not implemented yet."<< std::endl;
1544            }
1545            break;
1546        }
1547    }
1548    else
1549    {
1550
1551        // Need to restore draw buffer when toggling Stereo off.
1552        if( 0 == ( _camera->getInheritanceMask() & DRAW_BUFFER ) )
1553        {
1554            _renderStage->setDrawBuffer(_camera->getDrawBuffer());
1555            _renderStage->setReadBuffer(_camera->getDrawBuffer());
1556        }
1557
1558        if( 0 == ( _camera->getInheritanceMask() & READ_BUFFER ) )
1559        {
1560            _renderStage->setReadBuffer(_camera->getReadBuffer());
1561        }
1562
1563        _localStateSet->setAttribute(getViewport());
1564
1565
1566        // ensure that all color planes are active.
1567        osg::ColorMask* cmask = static_cast<osg::ColorMask*>(_localStateSet->getAttribute(osg::StateAttribute::COLORMASK));
1568        if (cmask)
1569        {
1570            cmask->setMask(true,true,true,true);
1571        }
1572        else
1573        {
1574            cmask = new osg::ColorMask(true,true,true,true);
1575            _localStateSet->setAttribute(cmask);
1576        }
1577        _renderStage->setColorMask(cmask);
1578
1579        // bog standard draw.
1580        _renderStage->drawPreRenderStages(_renderInfo,previous);
1581        _renderStage->draw(_renderInfo,previous);
1582    }
1583   
1584    // re apply the defalt OGL state.
1585    state->popAllStateSets();
1586    state->apply();
1587
1588#if 0
1589    if (_camera->getPostDrawCallback())
1590    {
1591        (*(_camera->getPostDrawCallback()))(*_camera);
1592    }
1593#endif
1594
1595    if (state->getCheckForGLErrors()!=osg::State::NEVER_CHECK_GL_ERRORS)
1596    {
1597        if (state->checkGLErrors("end of SceneView::draw()"))
1598        {
1599            // go into debug mode of OGL error in a fine grained way to help
1600            // track down OpenGL errors.
1601            state->setCheckForGLErrors(osg::State::ONCE_PER_ATTRIBUTE);
1602        }
1603    }
1604
1605// #define REPORT_TEXTURE_MANAGER_STATS
1606#ifdef REPORT_TEXTURE_MANAGER_STATS
1607    tom->reportStats();
1608    bom->reportStats();
1609#endif
1610
1611    // osg::notify(osg::NOTICE)<<"SceneView  draw() DynamicObjectCount"<<getState()->getDynamicObjectCount()<<std::endl;
1612
1613}
1614
1615/** Calculate, via glUnProject, the object coordinates of a window point.
1616    Note, current implementation requires that SceneView::draw() has been previously called
1617    for projectWindowIntoObject to produce valid values.  As per OpenGL
1618    windows coordinates are calculated relative to the bottom left of the window.*/
1619bool SceneView::projectWindowIntoObject(const osg::Vec3& window,osg::Vec3& object) const
1620{
1621    osg::Matrix inverseMVPW;
1622    inverseMVPW.invert(computeMVPW());
1623   
1624    object = window*inverseMVPW;
1625   
1626    return true;
1627}
1628
1629
1630/** Calculate, via glUnProject, the object coordinates of a window x,y
1631    when projected onto the near and far planes.
1632    Note, current implementation requires that SceneView::draw() has been previously called
1633    for projectWindowIntoObject to produce valid values.  As per OpenGL
1634    windows coordinates are calculated relative to the bottom left of the window.*/
1635bool SceneView::projectWindowXYIntoObject(int x,int y,osg::Vec3& near_point,osg::Vec3& far_point) const
1636{
1637    osg::Matrix inverseMVPW;
1638    inverseMVPW.invert(computeMVPW());
1639   
1640    near_point = osg::Vec3(x,y,0.0f)*inverseMVPW;
1641    far_point = osg::Vec3(x,y,1.0f)*inverseMVPW;
1642       
1643    return true;
1644}
1645
1646
1647/** Calculate, via glProject, the object coordinates of a window.
1648    Note, current implementation requires that SceneView::draw() has been previously called
1649    for projectWindowIntoObject to produce valid values.  As per OpenGL
1650    windows coordinates are calculated relative to the bottom left of the window.*/
1651bool SceneView::projectObjectIntoWindow(const osg::Vec3& object,osg::Vec3& window) const
1652{
1653    window = object*computeMVPW();
1654    return true;
1655}
1656
1657const osg::Matrix SceneView::computeMVPW() const
1658{
1659    osg::Matrix matrix( getViewMatrix() * getProjectionMatrix());
1660       
1661    if (getViewport())
1662        matrix.postMult(getViewport()->computeWindowMatrix());
1663    else
1664        osg::notify(osg::WARN)<<"osg::Matrix SceneView::computeMVPW() - error no viewport attached to SceneView, coords will be computed inccorectly."<<std::endl;
1665
1666    return matrix;
1667}
1668
1669void SceneView::clearArea(int x,int y,int width,int height,const osg::Vec4& color)
1670{
1671    osg::ref_ptr<osg::Viewport> viewport = new osg::Viewport;
1672    viewport->setViewport(x,y,width,height);
1673
1674    _renderInfo.getState()->applyAttribute(viewport.get());
1675   
1676    glScissor( x, y, width, height );
1677    glEnable( GL_SCISSOR_TEST );
1678    glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
1679    glClearColor( color[0], color[1], color[2], color[3]);
1680    glClear( GL_COLOR_BUFFER_BIT);
1681    glDisable( GL_SCISSOR_TEST );
1682}
1683
1684void SceneView::setProjectionMatrixAsOrtho(double left, double right,
1685                                           double bottom, double top,
1686                                           double zNear, double zFar)
1687{
1688    setProjectionMatrix(osg::Matrixd::ortho(left, right,
1689                                           bottom, top,
1690                                           zNear, zFar));
1691}                                           
1692
1693void SceneView::setProjectionMatrixAsOrtho2D(double left, double right,
1694                                             double bottom, double top)
1695{
1696    setProjectionMatrix(osg::Matrixd::ortho2D(left, right,
1697                                             bottom, top));
1698}
1699
1700void SceneView::setProjectionMatrixAsFrustum(double left, double right,
1701                                             double bottom, double top,
1702                                             double zNear, double zFar)
1703{
1704    setProjectionMatrix(osg::Matrixd::frustum(left, right,
1705                                             bottom, top,
1706                                             zNear, zFar));
1707}
1708
1709void SceneView::setProjectionMatrixAsPerspective(double fovy,double aspectRatio,
1710                                                 double zNear, double zFar)
1711{
1712    setProjectionMatrix(osg::Matrixd::perspective(fovy,aspectRatio,
1713                                                 zNear, zFar));
1714}                                     
1715
1716bool SceneView::getProjectionMatrixAsOrtho(double& left, double& right,
1717                                           double& bottom, double& top,
1718                                           double& zNear, double& zFar) const
1719{
1720    return getProjectionMatrix().getOrtho(left, right,
1721                                       bottom, top,
1722                                       zNear, zFar);
1723}
1724
1725bool SceneView::getProjectionMatrixAsFrustum(double& left, double& right,
1726                                             double& bottom, double& top,
1727                                             double& zNear, double& zFar) const
1728{
1729    return getProjectionMatrix().getFrustum(left, right,
1730                                         bottom, top,
1731                                         zNear, zFar);
1732}                                 
1733
1734bool SceneView::getProjectionMatrixAsPerspective(double& fovy,double& aspectRatio,
1735                                                 double& zNear, double& zFar) const
1736{
1737    return getProjectionMatrix().getPerspective(fovy, aspectRatio, zNear, zFar);
1738}                                                 
1739
1740void SceneView::setViewMatrixAsLookAt(const Vec3& eye,const Vec3& center,const Vec3& up)
1741{
1742    setViewMatrix(osg::Matrixd::lookAt(eye,center,up));
1743}
1744
1745void SceneView::getViewMatrixAsLookAt(Vec3& eye,Vec3& center,Vec3& up,float lookDistance) const
1746{
1747    getViewMatrix().getLookAt(eye,center,up,lookDistance);
1748}
1749
1750bool SceneView::getStats(Statistics& stats)
1751{
1752    if (_displaySettings.valid() && _displaySettings->getStereo())
1753    {
1754        switch(_displaySettings->getStereoMode())
1755        {
1756        case(osg::DisplaySettings::QUAD_BUFFER):
1757        case(osg::DisplaySettings::ANAGLYPHIC):
1758        case(osg::DisplaySettings::HORIZONTAL_SPLIT):
1759        case(osg::DisplaySettings::VERTICAL_SPLIT):
1760        case(osg::DisplaySettings::VERTICAL_INTERLACE):
1761        case(osg::DisplaySettings::HORIZONTAL_INTERLACE):
1762        {
1763            bool resultLeft = _renderStageLeft->getStats(stats);
1764            bool resultRight = _renderStageRight->getStats(stats);
1765            return resultLeft && resultRight;
1766        }
1767        case(osg::DisplaySettings::RIGHT_EYE):
1768        case(osg::DisplaySettings::LEFT_EYE):
1769        default:
1770            return _renderStage->getStats(stats);
1771        }
1772    }
1773    else
1774    {
1775        return _renderStage->getStats(stats);
1776    }
1777}
1778
1779void SceneView::collateReferencesToDependentCameras()
1780{
1781    if (_renderStage.valid()) _renderStage->collateReferencesToDependentCameras();
1782    if (_renderStageLeft.valid()) _renderStageLeft->collateReferencesToDependentCameras();
1783    if (_renderStageRight.valid()) _renderStageRight->collateReferencesToDependentCameras();
1784}
1785
1786void SceneView::clearReferencesToDependentCameras()
1787{
1788    if (_renderStage.valid()) _renderStage->clearReferencesToDependentCameras();
1789    if (_renderStageLeft.valid()) _renderStageLeft->clearReferencesToDependentCameras();
1790    if (_renderStageRight.valid()) _renderStageRight->clearReferencesToDependentCameras();
1791}
Note: See TracBrowser for help on using the browser.