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

Revision 10710, 68.3 kB (checked in by robert, 5 years ago)

From Paul Martz, changes for compiling against OpenGL 3.x

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