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

Revision 13041, 60.9 kB (checked in by robert, 3 years ago)

Ran script to remove trailing spaces and tabs

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