2001-09-20 05:08:56 +08:00
# include <osgUtil/SceneView>
2001-09-22 10:42:08 +08:00
# include <osgUtil/AppVisitor>
2001-10-21 04:26:36 +08:00
# include <osgUtil/DisplayListVisitor>
2001-09-20 05:08:56 +08:00
# include <osg/Notify>
# include <osg/Texture>
# include <osg/AlphaFunc>
# include <osg/TexEnv>
2001-12-19 08:38:23 +08:00
# include <osg/ColorMatrix>
2002-03-04 06:31:46 +08:00
# include <osg/LightModel>
2001-09-20 05:08:56 +08:00
2001-10-04 05:44:07 +08:00
# include <osg/GLU>
2001-01-11 00:32:10 +08:00
using namespace osg ;
using namespace osgUtil ;
2001-12-22 06:48:19 +08:00
SceneView : : SceneView ( DisplaySettings * ds )
2001-01-11 00:32:10 +08:00
{
2001-12-22 06:48:19 +08:00
_displaySettings = ds ;
2001-01-11 00:32:10 +08:00
_calc_nearfar = true ;
_backgroundColor . set ( 0.2f , 0.2f , 0.4f , 1.0f ) ;
_near_plane = 1.0f ;
_far_plane = 1.0f ;
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
_lodBias = 1.0f ;
_lightingMode = HEADLIGHT ;
2001-09-20 05:08:56 +08:00
_prioritizeTextures = false ;
2002-03-27 07:52:52 +08:00
_viewport = osgNew Viewport ;
2001-09-20 05:08:56 +08:00
2001-10-21 04:26:36 +08:00
_initCalled = false ;
2002-03-04 06:31:46 +08:00
_cullMask = 0xffffffff ;
_cullMaskLeft = 0xffffffff ;
2002-03-21 19:57:16 +08:00
_cullMaskRight = 0xffffffff ;
2002-03-04 06:31:46 +08:00
2001-01-11 00:32:10 +08:00
}
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
SceneView : : ~ SceneView ( )
{
}
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
void SceneView : : setDefaults ( )
{
2002-03-27 07:52:52 +08:00
_globalState = osgNew osg : : StateSet ;
2001-01-11 00:32:10 +08:00
_lightingMode = HEADLIGHT ;
2002-03-27 07:52:52 +08:00
_light = osgNew osg : : Light ;
2001-12-25 05:34:40 +08:00
_light - > setLightNum ( 0 ) ;
2001-12-03 06:20:46 +08:00
_light - > setAmbient ( Vec4 ( 0.00f , 0.0f , 0.00f , 1.0f ) ) ;
2001-09-20 05:08:56 +08:00
_light - > setDiffuse ( Vec4 ( 0.8f , 0.8f , 0.8f , 1.0f ) ) ;
2001-12-03 06:20:46 +08:00
_light - > setSpecular ( Vec4 ( 1.0f , 1.0f , 1.0f , 1.0f ) ) ;
2001-01-11 00:32:10 +08:00
2002-03-27 07:52:52 +08:00
_state = osgNew State ;
2001-09-20 05:08:56 +08:00
2002-03-27 07:52:52 +08:00
_camera = osgNew Camera ( _displaySettings . get ( ) ) ;
2001-12-03 06:20:46 +08:00
2002-03-27 07:52:52 +08:00
_rendergraph = osgNew RenderGraph ;
_renderStage = osgNew RenderStage ;
2001-09-22 10:42:08 +08:00
2002-03-29 07:06:20 +08:00
# ifndef __sgi
2002-02-11 01:16:43 +08:00
// sgi's IR graphics has a problem with lighting and display lists, as it seems to store
// lighting state with the display list, and the display list visitor doesn't currently apply
// state before creating display lists. So will disable the init visitor default, this won't
// affect functionality since the display lists will be created as and when needed.
2002-03-27 07:52:52 +08:00
DisplayListVisitor * dlv = osgNew DisplayListVisitor ( ) ;
2001-10-21 04:26:36 +08:00
dlv - > setState ( _state . get ( ) ) ;
2002-03-15 01:34:08 +08:00
dlv - > setNodeMaskOverride ( 0xffffffff ) ;
2001-10-21 04:26:36 +08:00
_initVisitor = dlv ;
2002-03-29 07:06:20 +08:00
# endif
2001-10-21 04:26:36 +08:00
2002-03-27 07:52:52 +08:00
_appVisitor = osgNew AppVisitor ;
2001-10-21 04:26:36 +08:00
2002-03-27 07:52:52 +08:00
_cullVisitor = osgNew CullVisitor ;
2001-09-20 05:08:56 +08:00
_cullVisitor - > setRenderGraph ( _rendergraph . get ( ) ) ;
_cullVisitor - > setRenderStage ( _renderStage . get ( ) ) ;
2001-01-11 00:32:10 +08:00
_globalState - > setGlobalDefaults ( ) ;
2001-09-20 05:08:56 +08:00
// enable lighting by default.
_globalState - > setMode ( GL_LIGHTING , osg : : StateAttribute : : ON ) ;
2001-12-25 05:34:40 +08:00
_light - > setStateSetModes ( * _globalState , osg : : StateAttribute : : ON ) ;
2001-09-20 05:08:56 +08:00
// enable depth testing by default.
_globalState - > setMode ( GL_DEPTH_TEST , osg : : StateAttribute : : ON ) ;
// set up an alphafunc by default to speed up blending operations.
2002-03-27 07:52:52 +08:00
osg : : AlphaFunc * alphafunc = osgNew osg : : AlphaFunc ;
2001-09-20 05:08:56 +08:00
alphafunc - > setFunction ( osg : : AlphaFunc : : GREATER , 0.0f ) ;
_globalState - > setAttributeAndModes ( alphafunc , osg : : StateAttribute : : ON ) ;
// set up an alphafunc by default to speed up blending operations.
2002-03-27 07:52:52 +08:00
osg : : TexEnv * texenv = osgNew osg : : TexEnv ;
2001-09-20 05:08:56 +08:00
texenv - > setMode ( osg : : TexEnv : : MODULATE ) ;
_globalState - > setAttributeAndModes ( texenv , osg : : StateAttribute : : ON ) ;
2001-01-11 00:32:10 +08:00
2002-03-27 07:52:52 +08:00
osg : : LightModel * lightmodel = osgNew osg : : LightModel ;
2002-03-04 06:31:46 +08:00
lightmodel - > setAmbientIntensity ( osg : : Vec4 ( 0.0f , 0.0f , 0.0f , 1.0f ) ) ;
_globalState - > setAttributeAndModes ( lightmodel , osg : : StateAttribute : : ON ) ;
2001-01-11 00:32:10 +08:00
_backgroundColor . set ( 0.2f , 0.2f , 0.4f , 1.0f ) ;
2002-03-04 06:31:46 +08:00
_cullMask = 0xffffffff ;
_cullMaskLeft = 0xffffffff ;
2002-04-19 07:30:06 +08:00
_cullMaskRight = 0xffffffff ;
2001-01-11 00:32:10 +08:00
}
2001-10-21 04:26:36 +08:00
void SceneView : : init ( )
{
_initCalled = true ;
if ( _sceneData . valid ( ) & & _initVisitor . valid ( ) )
{
_initVisitor - > reset ( ) ;
_initVisitor - > setFrameStamp ( _frameStamp . get ( ) ) ;
if ( _frameStamp . valid ( ) )
{
_initVisitor - > setTraversalNumber ( _frameStamp - > getFrameNumber ( ) ) ;
}
_sceneData - > accept ( * _initVisitor . get ( ) ) ;
}
}
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
void SceneView : : app ( )
2001-01-11 00:32:10 +08:00
{
2001-10-21 04:26:36 +08:00
if ( ! _initCalled ) init ( ) ;
2001-09-20 05:08:56 +08:00
if ( _sceneData . valid ( ) & & _appVisitor . valid ( ) )
{
_appVisitor - > reset ( ) ;
2001-09-22 10:42:08 +08:00
_appVisitor - > setFrameStamp ( _frameStamp . get ( ) ) ;
// use the frame number for the traversal number.
if ( _frameStamp . valid ( ) )
{
_appVisitor - > setTraversalNumber ( _frameStamp - > getFrameNumber ( ) ) ;
}
2001-09-20 05:08:56 +08:00
_sceneData - > accept ( * _appVisitor . get ( ) ) ;
2001-01-11 00:32:10 +08:00
}
2001-09-22 10:42:08 +08:00
2001-01-11 00:32:10 +08:00
}
2001-09-20 05:08:56 +08:00
void SceneView : : cull ( )
2002-02-14 21:26:37 +08:00
{
2002-02-19 07:01:09 +08:00
2002-04-22 06:05:26 +08:00
if ( ! _state )
{
osg : : notify ( osg : : INFO ) < < " Warning: no valid osgUtil::SceneView::_state attached, creating a default state automatically. " < < std : : endl ;
// note the constructor for osg::State will set ContextID to 0 which will be fine to single context graphics
// applications which is ok for most apps, but not multiple context/pipe applications.
_state = osgNew osg : : State ;
}
if ( ! _globalState )
{
osg : : notify ( osg : : INFO ) < < " Warning: no valid osgUtil::SceneView::_globalState attached, creating a default global stateset automatically. " < < std : : endl ;
_globalState = osgNew osg : : StateSet ;
_globalState - > setGlobalDefaults ( ) ;
}
// we in theory should be able to be able to bypass reset, but we'll call it just incase.
2002-03-30 01:26:40 +08:00
_state - > reset ( ) ;
2002-04-13 02:06:13 +08:00
2002-04-22 06:05:26 +08:00
_state - > setFrameStamp ( _frameStamp . get ( ) ) ;
_state - > setDisplaySettings ( _displaySettings . get ( ) ) ;
2002-04-13 02:06:13 +08:00
osg : : ref_ptr < osg : : Matrix > projection = _projectionMatrix . get ( ) ;
osg : : ref_ptr < osg : : Matrix > modelview = _modelviewMatrix . get ( ) ;
2002-03-30 01:26:40 +08:00
2002-04-13 02:06:13 +08:00
if ( _camera . valid ( ) )
{
_camera - > adjustAspectRatio ( _viewport - > aspectRatio ( ) ) ;
2002-04-14 20:53:36 +08:00
if ( _displaySettings . valid ( ) )
_camera - > setScreenDistance ( _displaySettings - > getScreenDistance ( ) ) ;
2002-04-13 02:06:13 +08:00
if ( ! projection ) projection = osgNew osg : : Matrix ( _camera - > getProjectionMatrix ( ) ) ;
if ( ! modelview ) modelview = osgNew osg : : Matrix ( _camera - > getModelViewMatrix ( ) ) ;
}
if ( ! projection ) projection = osgNew osg : : Matrix ( ) ;
if ( ! modelview ) modelview = osgNew osg : : Matrix ( ) ;
2002-03-30 01:26:40 +08:00
2002-02-14 21:26:37 +08:00
if ( _displaySettings . valid ( ) & & _displaySettings - > getStereo ( ) )
{
2002-04-13 02:06:13 +08:00
float fusionDistance = _displaySettings - > getScreenDistance ( ) ;
2002-02-14 21:26:37 +08:00
2002-04-13 02:06:13 +08:00
if ( _camera . valid ( ) )
{
fusionDistance = _camera - > getFusionDistance ( ) ;
}
2002-02-14 21:26:37 +08:00
float iod = _displaySettings - > getEyeSeperation ( ) ;
2002-04-13 02:06:13 +08:00
float sd = _displaySettings - > getScreenDistance ( ) ;
float es = 0.5f * iod * ( fusionDistance / sd ) ;
2002-02-14 21:26:37 +08:00
2002-02-19 07:01:09 +08:00
if ( ! _cullVisitorLeft . valid ( ) ) _cullVisitorLeft = dynamic_cast < CullVisitor * > ( _cullVisitor - > cloneType ( ) ) ;
if ( ! _rendergraphLeft . valid ( ) ) _rendergraphLeft = dynamic_cast < RenderGraph * > ( _rendergraph - > cloneType ( ) ) ;
2002-02-14 21:26:37 +08:00
if ( ! _renderStageLeft . valid ( ) ) _renderStageLeft = dynamic_cast < RenderStage * > ( _renderStage - > cloneType ( ) ) ;
2002-02-19 07:01:09 +08:00
if ( ! _cullVisitorRight . valid ( ) ) _cullVisitorRight = dynamic_cast < CullVisitor * > ( _cullVisitor - > cloneType ( ) ) ;
if ( ! _rendergraphRight . valid ( ) ) _rendergraphRight = dynamic_cast < RenderGraph * > ( _rendergraph - > cloneType ( ) ) ;
2002-02-14 21:26:37 +08:00
if ( ! _renderStageRight . valid ( ) ) _renderStageRight = dynamic_cast < RenderStage * > ( _renderStage - > cloneType ( ) ) ;
2002-04-13 02:06:13 +08:00
// set up the left eye.
osg : : ref_ptr < osg : : Matrix > projectionLeft = osgNew osg : : Matrix ( osg : : Matrix ( 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
iod / ( 2.0f * sd ) , 0.0f , 1.0f , 0.0f ,
0.0f , 0.0f , 0.0f , 1.0f ) *
( * projection ) ) ;
osg : : ref_ptr < osg : : Matrix > modelviewLeft = osgNew osg : : Matrix ( ( * modelview ) *
osg : : Matrix ( 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
0.0f , 0.0f , 1.0f , 0.0f ,
es , 0.0f , 0.0f , 1.0f ) ) ;
2002-03-04 06:31:46 +08:00
_cullVisitorLeft - > setTraversalMask ( _cullMaskLeft ) ;
2002-04-13 02:06:13 +08:00
cullStage ( projectionLeft . get ( ) , modelviewLeft . get ( ) , _cullVisitorLeft . get ( ) , _rendergraphLeft . get ( ) , _renderStageLeft . get ( ) ) ;
// set up the right eye.
osg : : ref_ptr < osg : : Matrix > projectionRight = osgNew osg : : Matrix ( osg : : Matrix ( 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
- iod / ( 2.0f * sd ) , 0.0f , 1.0f , 0.0f ,
0.0f , 0.0f , 0.0f , 1.0f ) *
( * projection ) ) ;
osg : : ref_ptr < osg : : Matrix > modelviewRight = osgNew osg : : Matrix ( ( * modelview ) *
osg : : Matrix ( 1.0f , 0.0f , 0.0f , 0.0f ,
0.0f , 1.0f , 0.0f , 0.0f ,
0.0f , 0.0f , 1.0f , 0.0f ,
- es , 0.0f , 0.0f , 1.0f ) ) ;
2002-03-04 06:31:46 +08:00
_cullVisitorRight - > setTraversalMask ( _cullMaskRight ) ;
2002-04-13 02:06:13 +08:00
cullStage ( projectionRight . get ( ) , modelviewRight . get ( ) , _cullVisitorRight . get ( ) , _rendergraphRight . get ( ) , _renderStageRight . get ( ) ) ;
2002-02-14 21:26:37 +08:00
}
else
{
2002-04-22 06:05:26 +08:00
if ( ! _cullVisitor )
{
osg : : notify ( osg : : INFO ) < < " Warning: no valid osgUtil::SceneView:: attached, creating a default CullVisitor automatically. " < < std : : endl ;
_cullVisitor = osgNew CullVisitor ;
}
if ( ! _rendergraph )
{
osg : : notify ( osg : : INFO ) < < " Warning: no valid osgUtil::SceneView:: attached, creating a global default RenderGraph automatically. " < < std : : endl ;
_rendergraph = osgNew RenderGraph ;
}
if ( ! _renderStage )
{
osg : : notify ( osg : : INFO ) < < " Warning: no valid osgUtil::SceneView::_renderStage attached, creating a default RenderStage automatically. " < < std : : endl ;
_renderStage = osgNew RenderStage ;
}
2002-03-04 06:31:46 +08:00
_cullVisitor - > setTraversalMask ( _cullMask ) ;
2002-04-13 02:06:13 +08:00
cullStage ( projection . get ( ) , modelview . get ( ) , _cullVisitor . get ( ) , _rendergraph . get ( ) , _renderStage . get ( ) ) ;
2002-02-14 21:26:37 +08:00
}
2002-02-19 07:01:09 +08:00
2002-04-15 16:09:02 +08:00
if ( _camera . valid ( ) & & _calc_nearfar )
2002-04-13 02:06:13 +08:00
{
_camera - > setNearFar ( _near_plane , _far_plane ) ;
}
2002-02-14 21:26:37 +08:00
}
2002-04-13 02:06:13 +08:00
void SceneView : : cullStage ( osg : : Matrix * projection , osg : : Matrix * modelview , osgUtil : : CullVisitor * cullVisitor , osgUtil : : RenderGraph * rendergraph , osgUtil : : RenderStage * renderStage )
2001-01-11 00:32:10 +08:00
{
2001-10-21 04:26:36 +08:00
2001-12-19 08:38:23 +08:00
if ( ! _sceneData | | ! _viewport - > valid ( ) ) return ;
2001-01-11 00:32:10 +08:00
2001-10-21 04:26:36 +08:00
if ( ! _initCalled ) init ( ) ;
2002-03-30 01:26:40 +08:00
2001-09-20 05:08:56 +08:00
2002-02-19 07:01:09 +08:00
cullVisitor - > reset ( ) ;
2001-01-11 00:32:10 +08:00
2002-02-19 07:01:09 +08:00
cullVisitor - > setFrameStamp ( _frameStamp . get ( ) ) ;
2001-09-22 10:42:08 +08:00
// use the frame number for the traversal number.
if ( _frameStamp . valid ( ) )
{
2002-02-19 07:01:09 +08:00
cullVisitor - > setTraversalNumber ( _frameStamp - > getFrameNumber ( ) ) ;
2001-09-22 10:42:08 +08:00
}
2002-02-19 07:01:09 +08:00
cullVisitor - > setLODBias ( _lodBias ) ;
cullVisitor - > setEarthSky ( NULL ) ; // reset earth sky on each frame.
cullVisitor - > setRenderGraph ( rendergraph ) ;
cullVisitor - > setRenderStage ( renderStage ) ;
2001-01-11 00:32:10 +08:00
2002-04-01 00:40:44 +08:00
// // SandB
// //now make it compute "clipping directions" needed for detailed culling
// if(cullVisitor->getDetailedCulling())
// cullVisitor->calcClippingDirections();//only once pre frame
2001-12-17 06:20:26 +08:00
2002-02-14 21:26:37 +08:00
renderStage - > reset ( ) ;
2001-01-11 00:32:10 +08:00
2002-02-19 07:01:09 +08:00
// comment out reset of rendergraph since clean is more efficient.
// rendergraph->reset();
// use clean of the rendergraph rather than reset, as it is able to
// reuse the structure on the rendergraph in the next frame. This
// achieves a certain amount of frame cohereancy of memory allocation.
rendergraph - > clean ( ) ;
2002-02-14 21:26:37 +08:00
renderStage - > setViewport ( _viewport . get ( ) ) ;
renderStage - > setClearColor ( _backgroundColor ) ;
2001-01-11 00:32:10 +08:00
2001-09-20 05:08:56 +08:00
switch ( _lightingMode )
2001-01-11 00:32:10 +08:00
{
2001-09-20 05:08:56 +08:00
case ( HEADLIGHT ) :
2002-02-14 21:26:37 +08:00
renderStage - > addLight ( _light . get ( ) , NULL ) ;
2001-09-20 05:08:56 +08:00
break ;
case ( SKY_LIGHT ) :
2002-02-14 21:26:37 +08:00
renderStage - > addLight ( _light . get ( ) , modelview ) ;
2001-09-20 05:08:56 +08:00
break ;
case ( NO_SCENEVIEW_LIGHT ) :
break ;
}
2001-01-11 00:32:10 +08:00
2002-02-19 07:01:09 +08:00
if ( _globalState . valid ( ) ) cullVisitor - > pushStateSet ( _globalState . get ( ) ) ;
2001-09-20 05:08:56 +08:00
2002-04-10 00:09:19 +08:00
cullVisitor - > pushViewport ( _viewport . get ( ) ) ;
cullVisitor - > pushProjectionMatrix ( projection ) ;
cullVisitor - > pushModelViewMatrix ( modelview ) ;
2002-02-12 03:51:24 +08:00
2001-09-20 05:08:56 +08:00
// traverse the scene graph to generate the rendergraph.
2002-02-19 07:01:09 +08:00
_sceneData - > accept ( * cullVisitor ) ;
2001-09-20 05:08:56 +08:00
2002-02-19 07:01:09 +08:00
if ( _globalState . valid ( ) ) cullVisitor - > popStateSet ( ) ;
2002-02-12 03:51:24 +08:00
2002-04-10 00:09:19 +08:00
cullVisitor - > popModelViewMatrix ( ) ;
cullVisitor - > popProjectionMatrix ( ) ;
cullVisitor - > popViewport ( ) ;
2001-01-11 00:32:10 +08:00
2002-02-19 07:01:09 +08:00
const osg : : EarthSky * earthSky = cullVisitor - > getEarthSky ( ) ;
2001-10-02 19:36:14 +08:00
if ( earthSky )
{
if ( earthSky - > getRequiresClear ( ) )
{
2002-02-14 21:26:37 +08:00
renderStage - > setClearColor ( earthSky - > getClearColor ( ) ) ;
renderStage - > setClearMask ( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT ) ;
2001-10-02 19:36:14 +08:00
// really should set clear mask here, but what to? Need
// to consider the stencil and accumulation buffers..
// will defer to later. Robert Osfield. October 2001.
}
else
{
// we have an earth sky implementation to do the work for use
// so we don't need to clear.
2002-02-14 21:26:37 +08:00
renderStage - > setClearMask ( 0 ) ;
2001-10-02 19:36:14 +08:00
}
}
2001-09-20 05:08:56 +08:00
if ( _calc_nearfar )
{
2002-02-19 07:01:09 +08:00
_near_plane = cullVisitor - > getCalculatedNearPlane ( ) ;
_far_plane = cullVisitor - > getCalculatedFarPlane ( ) ;
2001-09-20 05:08:56 +08:00
if ( _near_plane < = _far_plane )
{
// shift the far plane slight further away from the eye point.
// and shift the near plane slightly near the eye point, this
// will give a little space betwenn the near and far planes
// and the model, crucial when the naer and far planes are
// coincedent.
_far_plane * = 1.05 ;
_near_plane * = 0.95 ;
2002-04-01 00:40:44 +08:00
// // if required clamp the near plane to prevent negative or near zero
// // near planes.
// if(!cullVisitor->getDetailedCulling())
// {
2002-02-14 21:26:37 +08:00
float min_near_plane = _far_plane * 0.0005f ;
if ( _near_plane < min_near_plane ) _near_plane = min_near_plane ;
2002-04-01 00:40:44 +08:00
// }
2001-09-20 05:08:56 +08:00
}
else
{
_near_plane = 1.0f ;
_far_plane = 1000.0f ;
}
}
2001-01-11 00:32:10 +08:00
2002-02-19 07:01:09 +08:00
// prune out any empty RenderGraph children.
// note, this would be not required if the rendergraph had been
// reset at the start of each frame (see top of this method) but
// a clean has been used instead to try to minimize the amount of
// allocation and deleteing of the RenderGraph nodes.
rendergraph - > prune ( ) ;
2001-09-20 05:08:56 +08:00
}
2001-01-11 00:32:10 +08:00
2002-04-13 02:06:13 +08:00
2001-09-20 05:08:56 +08:00
void SceneView : : draw ( )
{
2002-03-30 01:26:40 +08:00
2001-12-22 06:48:19 +08:00
if ( _displaySettings . valid ( ) & & _displaySettings - > getStereo ( ) )
2001-12-03 06:20:46 +08:00
{
2001-12-19 08:38:23 +08:00
2001-12-22 06:48:19 +08:00
switch ( _displaySettings - > getStereoMode ( ) )
2001-12-03 06:20:46 +08:00
{
2001-12-22 06:48:19 +08:00
case ( osg : : DisplaySettings : : QUAD_BUFFER ) :
2001-12-19 08:38:23 +08:00
{
glDrawBuffer ( GL_BACK_LEFT ) ;
2002-02-14 21:26:37 +08:00
drawStage ( _renderStageLeft . get ( ) ) ;
2001-12-19 08:38:23 +08:00
glDrawBuffer ( GL_BACK_RIGHT ) ;
2002-02-14 21:26:37 +08:00
drawStage ( _renderStageRight . get ( ) ) ;
2001-12-19 08:38:23 +08:00
}
break ;
2001-12-22 06:48:19 +08:00
case ( osg : : DisplaySettings : : ANAGLYPHIC ) :
2001-12-19 08:38:23 +08:00
{
2001-12-19 23:20:29 +08:00
// draw left eye.
2002-03-27 18:52:40 +08:00
osg : : ref_ptr < osg : : ColorMask > red = osgNew osg : : ColorMask ;
red - > setMask ( true , false , false , true ) ;
2002-02-14 21:26:37 +08:00
_globalState - > setAttribute ( red . get ( ) ) ;
_renderStageLeft - > setColorMask ( red . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
// draw right eye.
2002-03-27 18:52:40 +08:00
osg : : ref_ptr < osg : : ColorMask > green = osgNew osg : : ColorMask ;
green - > setMask ( false , true , true , true ) ;
2002-02-14 21:26:37 +08:00
_globalState - > setAttribute ( green . get ( ) ) ;
_renderStageRight - > setColorMask ( green . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
2001-12-19 08:38:23 +08:00
2002-03-27 18:52:40 +08:00
}
break ;
case ( osg : : DisplaySettings : : HORIZONTAL_SPLIT ) :
{
2002-04-15 06:21:59 +08:00
int seperation = _displaySettings - > getSplitStereoHorizontalSeperation ( ) ;
int left_half_width = ( _viewport - > width ( ) - seperation ) / 2 ;
int right_half_begin = ( _viewport - > width ( ) + seperation ) / 2 ;
int right_half_width = _viewport - > width ( ) - right_half_begin ;
2002-03-27 18:52:40 +08:00
osg : : ref_ptr < osg : : Viewport > viewportLeft = osgNew osg : : Viewport ;
2002-04-15 06:21:59 +08:00
viewportLeft - > setViewport ( _viewport - > x ( ) , _viewport - > y ( ) , left_half_width , _viewport - > height ( ) ) ;
2002-03-27 18:52:40 +08:00
osg : : ref_ptr < osg : : Viewport > viewportRight = osgNew osg : : Viewport ;
2002-04-15 06:21:59 +08:00
viewportRight - > setViewport ( _viewport - > x ( ) + right_half_begin , _viewport - > y ( ) , right_half_width , _viewport - > height ( ) ) ;
2002-04-16 23:31:46 +08:00
clearArea ( _viewport - > x ( ) + left_half_width , _viewport - > y ( ) , seperation , _viewport - > height ( ) , _renderStageLeft - > getClearColor ( ) ) ;
2002-04-15 06:21:59 +08:00
if ( _displaySettings - > getSplitStereoHorizontalEyeMapping ( ) = = osg : : DisplaySettings : : LEFT_EYE_LEFT_VIEWPORT )
{
_renderStageLeft - > setViewport ( viewportLeft . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
_renderStageRight - > setViewport ( viewportRight . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
else
{
_renderStageLeft - > setViewport ( viewportRight . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
_renderStageRight - > setViewport ( viewportLeft . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
2002-03-27 18:52:40 +08:00
}
break ;
case ( osg : : DisplaySettings : : VERTICAL_SPLIT ) :
{
2002-04-15 06:21:59 +08:00
int seperation = _displaySettings - > getSplitStereoVerticalSeperation ( ) ;
2002-03-27 18:52:40 +08:00
2002-04-15 06:21:59 +08:00
int bottom_half_height = ( _viewport - > height ( ) - seperation ) / 2 ;
int top_half_begin = ( _viewport - > height ( ) + seperation ) / 2 ;
int top_half_height = _viewport - > height ( ) - top_half_begin ;
osg : : ref_ptr < osg : : Viewport > viewportTop = osgNew osg : : Viewport ;
viewportTop - > setViewport ( _viewport - > x ( ) , _viewport - > y ( ) + top_half_begin , _viewport - > width ( ) , top_half_height ) ;
osg : : ref_ptr < osg : : Viewport > viewportBottom = osgNew osg : : Viewport ;
viewportBottom - > setViewport ( _viewport - > x ( ) , _viewport - > y ( ) , _viewport - > width ( ) , bottom_half_height ) ;
2002-04-16 23:31:46 +08:00
clearArea ( _viewport - > x ( ) , _viewport - > y ( ) + bottom_half_height , _viewport - > width ( ) , seperation , _renderStageLeft - > getClearColor ( ) ) ;
2002-04-15 06:21:59 +08:00
if ( _displaySettings - > getSplitStereoVerticalEyeMapping ( ) = = osg : : DisplaySettings : : LEFT_EYE_TOP_VIEWPORT )
{
_renderStageLeft - > setViewport ( viewportTop . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
_renderStageRight - > setViewport ( viewportBottom . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
else
{
_renderStageLeft - > setViewport ( viewportBottom . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
2002-03-27 18:52:40 +08:00
2002-04-15 06:21:59 +08:00
_renderStageRight - > setViewport ( viewportTop . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
2001-12-19 08:38:23 +08:00
}
break ;
default :
{
osg : : notify ( osg : : NOTICE ) < < " Warning: stereo camera mode not implemented yet. " < < std : : endl ;
2002-02-14 21:26:37 +08:00
drawStage ( _renderStageLeft . get ( ) ) ;
2001-12-19 08:38:23 +08:00
}
break ;
2001-12-03 06:20:46 +08:00
}
}
2001-12-19 08:38:23 +08:00
else
{
// bog standard draw.
2002-02-14 21:26:37 +08:00
drawStage ( _renderStage . get ( ) ) ;
2001-12-19 08:38:23 +08:00
}
2002-02-14 21:26:37 +08:00
}
void SceneView : : drawStage ( osgUtil : : RenderStage * renderStage )
{
if ( ! _sceneData | | ! _viewport - > valid ( ) ) return ;
// note, to support multi-pipe systems the deletion of OpenGL display list
// and texture objects is deferred until the OpenGL context is the correct
// context for when the object were originally created. Here we know what
// context we are in so can flush the appropriate caches.
osg : : Drawable : : flushDeletedDisplayLists ( _state - > getContextID ( ) ) ;
osg : : Texture : : flushDeletedTextureObjects ( _state - > getContextID ( ) ) ;
RenderLeaf * previous = NULL ;
renderStage - > draw ( * _state , previous ) ;
2001-12-19 08:38:23 +08:00
2001-09-20 05:08:56 +08:00
GLenum errorNo = glGetError ( ) ;
if ( errorNo ! = GL_NO_ERROR )
{
2001-12-15 18:00:43 +08:00
osg : : notify ( WARN ) < < " Warning: detected OpenGL error ' " < < gluErrorString ( errorNo ) < < " ' " < < std : : endl ;
2001-09-20 05:08:56 +08:00
}
2001-01-11 00:32:10 +08:00
}
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
/** Calculate, via glUnProject, the object coordinates of a window point.
Note , current implementation requires that SceneView : : draw ( ) has been previously called
for projectWindowIntoObject to produce valid values . As per OpenGL
windows coordinates are calculated relative to the bottom left of the window . */
bool SceneView : : projectWindowIntoObject ( const osg : : Vec3 & window , osg : : Vec3 & object ) const
{
2002-04-16 19:41:32 +08:00
osg : : Matrix inverseMVPW ;
inverseMVPW . invert ( computeMVPW ( ) ) ;
object = window * inverseMVPW ;
return true ;
2001-01-11 00:32:10 +08:00
}
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
/** Calculate, via glUnProject, the object coordinates of a window x,y
when projected onto the near and far planes .
Note , current implementation requires that SceneView : : draw ( ) has been previously called
for projectWindowIntoObject to produce valid values . As per OpenGL
windows coordinates are calculated relative to the bottom left of the window . */
bool SceneView : : projectWindowXYIntoObject ( int x , int y , osg : : Vec3 & near_point , osg : : Vec3 & far_point ) const
{
2002-04-16 19:41:32 +08:00
osg : : Matrix inverseMVPW ;
inverseMVPW . invert ( computeMVPW ( ) ) ;
near_point = osg : : Vec3 ( x , y , 0.0f ) * inverseMVPW ;
far_point = osg : : Vec3 ( x , y , 1.0f ) * inverseMVPW ;
return true ;
2001-01-11 00:32:10 +08:00
}
2001-09-20 05:08:56 +08:00
2001-01-11 00:32:10 +08:00
/** Calculate, via glProject, the object coordinates of a window.
Note , current implementation requires that SceneView : : draw ( ) has been previously called
for projectWindowIntoObject to produce valid values . As per OpenGL
windows coordinates are calculated relative to the bottom left of the window . */
bool SceneView : : projectObjectIntoWindow ( const osg : : Vec3 & object , osg : : Vec3 & window ) const
{
2002-04-16 19:41:32 +08:00
window = object * computeMVPW ( ) ;
return true ;
}
const osg : : Matrix SceneView : : computeMVPW ( ) const
{
osg : : Matrix matrix ;
if ( _modelviewMatrix . valid ( ) )
matrix = ( * _modelviewMatrix ) ;
else if ( _camera . valid ( ) )
matrix = _camera - > getModelViewMatrix ( ) ;
if ( _projectionMatrix . valid ( ) )
matrix . postMult ( * _projectionMatrix ) ;
else if ( _camera . valid ( ) )
matrix . postMult ( _camera - > getProjectionMatrix ( ) ) ;
if ( _viewport . valid ( ) )
matrix . postMult ( _viewport - > computeWindowMatrix ( ) ) ;
else
osg : : notify ( osg : : WARN ) < < " osg::Matrix SceneView::computeMVPW() - error no viewport attached to SceneView, coords will be computed inccorectly. " < < std : : endl ;
return matrix ;
2001-01-11 00:32:10 +08:00
}
2002-04-16 23:31:46 +08:00
void SceneView : : clearArea ( int x , int y , int width , int height , const osg : : Vec4 & color )
{
osg : : ref_ptr < osg : : Viewport > viewport = osgNew osg : : Viewport ;
viewport - > setViewport ( x , y , width , height ) ;
viewport - > apply ( * _state ) ;
glScissor ( x , y , width , height ) ;
glEnable ( GL_SCISSOR_TEST ) ;
glColorMask ( GL_TRUE , GL_TRUE , GL_TRUE , GL_TRUE ) ;
glClearColor ( color [ 0 ] , color [ 1 ] , color [ 2 ] , color [ 3 ] ) ;
glClear ( GL_COLOR_BUFFER_BIT ) ;
glDisable ( GL_SCISSOR_TEST ) ;
}