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>
2002-08-28 23:28:11 +08:00
# include <osg/Texture>
2001-09-20 05:08:56 +08:00
# 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>
2002-06-10 21:50:25 +08:00
# include <osg/CollectOccludersVisitor>
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
_backgroundColor . set ( 0.2f , 0.2f , 0.4f , 1.0f ) ;
2002-07-03 03:53:18 +08:00
_computeNearFar = CullVisitor : : COMPUTE_NEAR_FAR_USING_BOUNDING_VOLUMES ;
2001-09-20 05:08:56 +08:00
2002-07-03 03:53:18 +08:00
_cullingMode = osg : : CullStack : : ENABLE_ALL_CULLING ;
_LODBias = 1.0f ;
2002-07-07 22:40:41 +08:00
_smallFeatureCullingPixelSize = 3.0f ;
2001-01-11 00:32:10 +08:00
2002-09-04 18:49:17 +08:00
_fusionDistanceMode = USE_CAMERA_FUSION_DISTANCE ;
_fusionDistanceValue = 1.0f ;
2001-01-11 00:32:10 +08:00
_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 ) ;
2002-07-09 17:35:42 +08:00
_globalState - > setAssociatedModes ( _light . get ( ) , 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 ) ;
2002-07-09 17:35:42 +08:00
// set up an texture environment by default to speed up blending operations.
osg : : TexEnv * texenv = osgNew osg : : TexEnv ;
texenv - > setMode ( osg : : TexEnv : : MODULATE ) ;
_globalState - > setTextureAttributeAndModes ( 0 , 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-07-15 21:20:41 +08:00
lightmodel - > setAmbientIntensity ( osg : : Vec4 ( 0.1f , 0.1f , 0.1f , 1.0f ) ) ;
2002-03-04 06:31:46 +08:00
_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 ( )
{
2002-07-21 18:04:33 +08:00
2001-10-21 04:26:36 +08:00
_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 ( ) ;
2002-06-17 17:10:26 +08:00
2002-07-21 18:04:33 +08:00
# ifdef OSG_USE_MEMORY_MANAGER
m_validateAllAllocUnits ( ) ;
# endif
2002-06-17 17:10:26 +08:00
//std::cout<<std::endl;
//std::cout<<std::endl;
//std::cout<<"*************************** New frame ************"<<std::endl;
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 ( ) ) ;
2002-06-03 23:39:41 +08:00
//cout <<"fovx="<<_camera->calc_fovx()<<endl;
2002-04-13 02:06:13 +08:00
}
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-09-04 18:49:17 +08:00
switch ( _fusionDistanceMode )
2002-04-13 02:06:13 +08:00
{
2002-09-04 18:49:17 +08:00
case ( USE_CAMERA_FUSION_DISTANCE ) :
if ( _camera . valid ( ) )
{
fusionDistance = _camera - > getFusionDistance ( ) ;
}
break ;
case ( USE_FUSION_DISTANCE_VALUE ) :
fusionDistance = _fusionDistanceValue ;
break ;
case ( PROPORTIONAL_TO_SCREEN_DISTANCE ) :
fusionDistance * = _fusionDistanceValue ;
break ;
2002-04-13 02:06:13 +08:00
}
2002-09-04 18:49:17 +08:00
2002-08-29 11:22:27 +08:00
float iod = _displaySettings - > getEyeSeparation ( ) ;
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-09-17 23:47:23 +08:00
if ( ! _renderStageLeft . valid ( ) ) _renderStageLeft = dynamic_cast < RenderStage * > ( _renderStage - > clone ( osg : : CopyOp : : DEEP_COPY_ALL ) ) ;
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-09-17 23:47:23 +08:00
if ( ! _renderStageRight . valid ( ) ) _renderStageRight = dynamic_cast < RenderStage * > ( _renderStage - > clone ( osg : : CopyOp : : DEEP_COPY_ALL ) ) ;
2002-02-14 21:26:37 +08:00
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
2002-07-12 21:00:09 +08:00
if ( _camera . valid ( ) & & _computeNearFar ! = CullVisitor : : DO_NOT_COMPUTE_NEAR_FAR )
2002-06-14 16:45:28 +08:00
{
// clamp the camera to the near/far computed in cull traversal.
_camera - > setNearFar ( _cullVisitorRight - > getCalculatedNearPlane ( ) , _cullVisitorRight - > getCalculatedFarPlane ( ) ) ;
}
2002-05-09 18:31:03 +08:00
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-05-09 18:31:03 +08:00
2002-07-12 21:00:09 +08:00
if ( _camera . valid ( ) & & _computeNearFar ! = CullVisitor : : DO_NOT_COMPUTE_NEAR_FAR )
2002-06-14 07:46:02 +08:00
{
// clamp the camera to the near/far computed in cull traversal.
_camera - > setNearFar ( _cullVisitor - > getCalculatedNearPlane ( ) , _cullVisitor - > getCalculatedFarPlane ( ) ) ;
}
2002-02-14 21:26:37 +08:00
}
2002-04-13 02:06:13 +08:00
2002-05-09 18:31:03 +08:00
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
2002-07-03 03:53:18 +08:00
2002-06-10 21:50:25 +08:00
// collect any occluder in the view frustum.
if ( _sceneData - > containsOccluderNodes ( ) )
{
2002-06-14 00:21:00 +08:00
//std::cout << "Scene graph contains occluder nodes, searching for them"<<std::endl;
2002-06-10 21:50:25 +08:00
osg : : CollectOccludersVisitor cov ;
cov . setFrameStamp ( _frameStamp . get ( ) ) ;
// use the frame number for the traversal number.
if ( _frameStamp . valid ( ) )
{
cov . setTraversalNumber ( _frameStamp - > getFrameNumber ( ) ) ;
}
cov . pushViewport ( _viewport . get ( ) ) ;
cov . pushProjectionMatrix ( projection ) ;
cov . pushModelViewMatrix ( modelview ) ;
// traverse the scene graph to search for occluder in there new positions.
_sceneData - > accept ( cov ) ;
cov . popModelViewMatrix ( ) ;
cov . popProjectionMatrix ( ) ;
cov . popViewport ( ) ;
2002-06-14 00:21:00 +08:00
2002-06-19 06:35:48 +08:00
// sort the occluder from largest occluder volume to smallest.
cov . removeOccludedOccluders ( ) ;
2002-06-14 00:21:00 +08:00
2002-06-19 18:19:10 +08:00
//std::cout << "finished searching for occluder - found "<<cov.getCollectedOccluderSet().size()<<std::endl;
2002-06-19 06:35:48 +08:00
cullVisitor - > getOccluderList ( ) . clear ( ) ;
std : : copy ( cov . getCollectedOccluderSet ( ) . begin ( ) , cov . getCollectedOccluderSet ( ) . end ( ) , std : : back_insert_iterator < CullStack : : OccluderList > ( cullVisitor - > getOccluderList ( ) ) ) ;
2002-06-10 21:50:25 +08:00
}
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-08-13 21:22:46 +08:00
cullVisitor - > setCullingMode ( _cullingMode ) ;
2002-07-03 03:53:18 +08:00
cullVisitor - > setComputeNearFarMode ( _computeNearFar ) ;
cullVisitor - > setLODBias ( _LODBias ) ;
cullVisitor - > setSmallFeatureCullingPixelSize ( _smallFeatureCullingPixelSize ) ;
2002-08-19 19:42:37 +08:00
cullVisitor - > setClearNode ( NULL ) ; // reset earth sky on each frame.
2002-02-19 07:01:09 +08:00
cullVisitor - > setRenderGraph ( rendergraph ) ;
cullVisitor - > setRenderStage ( renderStage ) ;
2001-01-11 00:32:10 +08:00
2002-07-02 14:22:28 +08:00
cullVisitor - > setState ( _state . get ( ) ) ;
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-06-12 02:41:57 +08:00
if ( _light . valid ( ) ) renderStage - > addPositionedAttribute ( NULL , _light . get ( ) ) ;
else osg : : notify ( osg : : WARN ) < < " Warning: no osg::Light attached to ogUtil::SceneView to provide head light.*/ " < < std : : endl ;
2001-09-20 05:08:56 +08:00
break ;
case ( SKY_LIGHT ) :
2002-06-12 02:41:57 +08:00
if ( _light . valid ( ) ) renderStage - > addPositionedAttribute ( modelview , _light . get ( ) ) ;
else osg : : notify ( osg : : WARN ) < < " Warning: no osg::Light attached to ogUtil::SceneView to provide sky light.*/ " < < std : : endl ;
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-04-10 00:09:19 +08:00
cullVisitor - > popModelViewMatrix ( ) ;
cullVisitor - > popProjectionMatrix ( ) ;
cullVisitor - > popViewport ( ) ;
2001-01-11 00:32:10 +08:00
2002-05-22 20:01:12 +08:00
if ( _globalState . valid ( ) ) cullVisitor - > popStateSet ( ) ;
2001-01-11 00:32:10 +08:00
2002-08-19 19:42:37 +08:00
const osg : : ClearNode * clearNode = cullVisitor - > getClearNode ( ) ;
if ( clearNode )
2001-10-02 19:36:14 +08:00
{
2002-08-19 19:42:37 +08:00
if ( clearNode - > getRequiresClear ( ) )
2001-10-02 19:36:14 +08:00
{
2002-08-19 19:42:37 +08:00
renderStage - > setClearColor ( clearNode - > getClearColor ( ) ) ;
2002-02-14 21:26:37 +08:00
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
}
}
2002-09-17 23:47:23 +08:00
renderStage - > sort ( ) ;
2001-09-20 05:08:56 +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
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( _viewport . get ( ) ) ;
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
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( _viewport . get ( ) ) ;
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-08-29 11:22:27 +08:00
int separation = _displaySettings - > getSplitStereoHorizontalSeparation ( ) ;
2002-04-15 06:21:59 +08:00
2002-08-29 11:22:27 +08:00
int left_half_width = ( _viewport - > width ( ) - separation ) / 2 ;
int right_half_begin = ( _viewport - > width ( ) + separation ) / 2 ;
2002-04-15 06:21:59 +08:00
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
2002-08-29 11:22:27 +08:00
clearArea ( _viewport - > x ( ) + left_half_width , _viewport - > y ( ) , separation , _viewport - > height ( ) , _renderStageLeft - > getClearColor ( ) ) ;
2002-04-16 23:31:46 +08:00
2002-04-15 06:21:59 +08:00
if ( _displaySettings - > getSplitStereoHorizontalEyeMapping ( ) = = osg : : DisplaySettings : : LEFT_EYE_LEFT_VIEWPORT )
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportLeft . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageLeft - > setViewport ( viewportLeft . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportRight . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageRight - > setViewport ( viewportRight . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
else
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportRight . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageLeft - > setViewport ( viewportRight . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportLeft . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageRight - > setViewport ( viewportLeft . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
2002-03-27 18:52:40 +08:00
}
break ;
case ( osg : : DisplaySettings : : VERTICAL_SPLIT ) :
{
2002-08-29 11:22:27 +08:00
int separation = _displaySettings - > getSplitStereoVerticalSeparation ( ) ;
2002-03-27 18:52:40 +08:00
2002-08-29 11:22:27 +08:00
int bottom_half_height = ( _viewport - > height ( ) - separation ) / 2 ;
int top_half_begin = ( _viewport - > height ( ) + separation ) / 2 ;
2002-04-15 06:21:59 +08:00
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-08-29 11:22:27 +08:00
clearArea ( _viewport - > x ( ) , _viewport - > y ( ) + bottom_half_height , _viewport - > width ( ) , separation , _renderStageLeft - > getClearColor ( ) ) ;
2002-04-16 23:31:46 +08:00
2002-04-15 06:21:59 +08:00
if ( _displaySettings - > getSplitStereoVerticalEyeMapping ( ) = = osg : : DisplaySettings : : LEFT_EYE_TOP_VIEWPORT )
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportTop . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageLeft - > setViewport ( viewportTop . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportBottom . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageRight - > setViewport ( viewportBottom . get ( ) ) ;
drawStage ( _renderStageRight . get ( ) ) ;
}
else
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportBottom . get ( ) ) ;
2002-04-15 06:21:59 +08:00
_renderStageLeft - > setViewport ( viewportBottom . get ( ) ) ;
drawStage ( _renderStageLeft . get ( ) ) ;
2002-03-27 18:52:40 +08:00
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( viewportTop . get ( ) ) ;
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-05-22 20:01:12 +08:00
_globalState - > setAttribute ( _viewport . get ( ) ) ;
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
{
2002-04-22 17:37:17 +08:00
_globalState - > setAttribute ( _viewport . get ( ) ) ;
2002-09-04 09:15:07 +08:00
osg : : ref_ptr < osg : : ColorMask > cmask = osgNew osg : : ColorMask ;
cmask - > setMask ( true , true , true , true ) ;
_globalState - > setAttribute ( cmask . get ( ) ) ;
2002-04-22 17:37:17 +08:00
2001-12-19 08:38:23 +08:00
// 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
2002-08-04 00:37:13 +08:00
// const osg::Polytope& polytope = _state->getViewFrustum();
// const osg::Polytope::PlaneList& pl = polytope.getPlaneList();
// std::cout <<"draw frustum"<<std::endl;
// for(osg::Polytope::PlaneList::const_iterator pl_itr=pl.begin();
// pl_itr!=pl.end();
// ++pl_itr)
// {
// std::cout << " plane "<<*pl_itr<<std::endl;
// }
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 ( ) ) ;
2002-08-28 23:28:11 +08:00
osg : : Texture : : flushDeletedTextureObjects ( _state - > getContextID ( ) ) ;
2002-02-14 21:26:37 +08:00
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 ) ;
2002-04-22 17:37:17 +08:00
_state - > applyAttribute ( viewport . get ( ) ) ;
2002-04-16 23:31:46 +08:00
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 ) ;
}