Harald JOHSEN:

Changes
=======

- shadowvolume.cxx, renderer.cxx :
  - reduced the polygon offset a bit to eliminate some artifact ;
  - changed again the cleanup code for objects inside a tile because it could crash on rare occasion ;
  - the culling of shadow casters has been rewritten to traverse the scene graph, it should be
    a bit faster when there is a lot of objects ;
  - the range selector was not correctly handled, sometimes the wrong LOD was casting shadows.
  - added the option to display aircraft's transparent objects after the shadows, this will
    reduce the problem of shadows being hidden by the transparent object (propeller disk,
    rotor, etc). A side effect is that aircraft's transparent objects won't receive shadows
    anymore. This is usually a good thing except when the aircraft use a 'transparent'
    texture where it should not. A transparent texture in the plib context is a texture
    with an alpha channel or a material with alpha <= 0.99.

- model.cxx, animation.cxx, shadowvolume.cxx :
  - added an optional <condition> under the <noshadow> animation

- tower.cxx
  - correct a rare bug where all occurences of the aircraft are not deleted from the
  departure list causing a crash in FGTower::CheckDepartureList function.
This commit is contained in:
ehofman
2005-07-18 16:57:20 +00:00
parent 73cb6ff00d
commit f93ea20d5e
5 changed files with 179 additions and 103 deletions
+22 -2
View File
@@ -1506,15 +1506,35 @@ void SGDistScaleAnimation::distScaleCallback( sgMat4 r, sgFrustum *f, sgMat4 m )
// Implementation of SGShadowAnimation // Implementation of SGShadowAnimation
//////////////////////////////////////////////////////////////////////// ////////////////////////////////////////////////////////////////////////
SGShadowAnimation::SGShadowAnimation (SGPropertyNode_ptr props) SGShadowAnimation::SGShadowAnimation ( SGPropertyNode *prop_root,
: SGAnimation(props, new ssgBranch) SGPropertyNode_ptr props )
: SGAnimation(props, new ssgBranch),
_condition(0),
_condition_value(true)
{ {
animation_type = 1; animation_type = 1;
SGPropertyNode_ptr node = props->getChild("condition");
if (node != 0) {
_condition = sgReadCondition(prop_root, node);
_condition_value = false;
}
} }
SGShadowAnimation::~SGShadowAnimation () SGShadowAnimation::~SGShadowAnimation ()
{ {
delete _condition;
} }
int
SGShadowAnimation::update()
{
if (_condition)
_condition_value = _condition->test();
return 2;
}
bool SGShadowAnimation::get_condition_value(void) {
return _condition_value;
}
// end of animation.cxx // end of animation.cxx
+7 -1
View File
@@ -589,8 +589,14 @@ private:
class SGShadowAnimation : public SGAnimation class SGShadowAnimation : public SGAnimation
{ {
public: public:
SGShadowAnimation (SGPropertyNode_ptr props); SGShadowAnimation ( SGPropertyNode *prop_root,
SGPropertyNode_ptr props );
virtual ~SGShadowAnimation (); virtual ~SGShadowAnimation ();
virtual int update();
bool get_condition_value(void);
private:
SGCondition * _condition;
bool _condition_value;
}; };
+1 -1
View File
@@ -166,7 +166,7 @@ sgMakeAnimation( ssgBranch * model,
} else if (!strcmp("dist-scale", type)) { } else if (!strcmp("dist-scale", type)) {
animation = new SGDistScaleAnimation(node); animation = new SGDistScaleAnimation(node);
} else if (!strcmp("noshadow", type)) { } else if (!strcmp("noshadow", type)) {
animation = new SGShadowAnimation(node); animation = new SGShadowAnimation(prop_root, node);
} else { } else {
animation = new SGNullAnimation(node); animation = new SGNullAnimation(node);
SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type); SG_LOG(SG_INPUT, SG_WARN, "Unknown animation type " << type);
+141 -88
View File
@@ -27,6 +27,7 @@
#include <simgear/screen/extensions.hxx> #include <simgear/screen/extensions.hxx>
#include <simgear/scene/model/animation.hxx> #include <simgear/scene/model/animation.hxx>
#include <simgear/scene/model/model.hxx> #include <simgear/scene/model/model.hxx>
#include <simgear/environment/visual_enviro.hxx>
#include SG_GLU_H #include SG_GLU_H
#include "shadowvolume.hxx" #include "shadowvolume.hxx"
@@ -116,10 +117,15 @@ SGShadowVolume::ShadowCaster::ShadowCaster( int _num_tri, ssgBranch * _geometry_
ssgBranch *branch = (ssgBranch *) _geometry_leaf; ssgBranch *branch = (ssgBranch *) _geometry_leaf;
while( branch && branch->getNumParents() > 0 ) { while( branch && branch->getNumParents() > 0 ) {
if( !first_select && branch->isA(ssgTypeSelector())) { if( branch->isAKindOf(ssgTypeSelector())) {
first_select = branch; first_select = branch;
break; break;
} }
if( sgCheckAnimationBranch( (ssgEntity *) branch ) )
if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1) {
first_select = branch;
break;
}
branch = branch->getParent(0); branch = branch->getParent(0);
} }
} }
@@ -150,6 +156,7 @@ void SGShadowVolume::ShadowCaster::addLeaf( int & tri_idx, int & ind_idx, ssgLea
} }
if( num_tri == 0 ) if( num_tri == 0 )
return; return;
isTranslucent |= geometry_leaf->isTranslucent() ? true : false;
int num_ind = geometry_leaf->getNumVertices(); int num_ind = geometry_leaf->getNumVertices();
ind_idx += num_ind; ind_idx += num_ind;
} }
@@ -302,7 +309,7 @@ void SGShadowVolume::ShadowCaster::DrawInfiniteShadowVolume(sgVec3 lightPosition
glDrawElements ( GL_TRIANGLES, lastSilhouetteIndicesCount, GL_UNSIGNED_SHORT, silhouetteEdgeIndices ) ; glDrawElements ( GL_TRIANGLES, lastSilhouetteIndicesCount, GL_UNSIGNED_SHORT, silhouetteEdgeIndices ) ;
//Draw caps if required //Draw caps if required
if(drawCaps) if(drawCaps)
{ {
glBegin(GL_TRIANGLES); glBegin(GL_TRIANGLES);
{ {
@@ -344,8 +351,19 @@ void SGShadowVolume::ShadowCaster::getNetTransform ( ssgBranch * branch, sgMat4
// check the value of <select> and <range> animation // check the value of <select> and <range> animation
// wich have been computed during the rendering // wich have been computed during the rendering
bool SGShadowVolume::ShadowCaster::isSelected ( ssgBranch * branch ) { bool SGShadowVolume::ShadowCaster::isSelected ( ssgBranch * branch, float dist ) {
while( branch && branch != lib_object) { while( branch && branch != lib_object) {
if( sgCheckAnimationBranch( (ssgEntity *) branch ) ) {
if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1)
if( ((SGShadowAnimation *) branch->getUserData())->get_condition_value() )
return false;
}
// recompute range check since the value in the branch is shared by multiple objects
// we can only have the last value
if( branch->isA(ssgTypeRangeSelector()) )
if( dist >= ((ssgRangeSelector *) branch)->getRange(1) ||
dist < ((ssgRangeSelector *) branch)->getRange(0))
return false;
if( branch->isA(ssgTypeSelector()) ) if( branch->isA(ssgTypeSelector()) )
if( !((ssgSelector *) branch)->isSelected(0) ) if( !((ssgSelector *) branch)->isSelected(0) )
return false; return false;
@@ -366,8 +384,12 @@ void SGShadowVolume::ShadowCaster::computeShadows(sgMat4 rotation, sgMat4 rotati
// check the select and range ssgSelector node // check the select and range ssgSelector node
// object can't cast shadow if it is not visible // object can't cast shadow if it is not visible
sgVec4 trans;
sgCopyVec4( trans, rotation_translation[3] );
sgAddVec4( trans, states->CameraViewM[3] );
float dist = sgLengthVec3( trans );
if( first_select && ! isSelected( first_select) ) if( first_select && ! isSelected( first_select, dist) )
return; return;
// get the transformations : this comes from animation code for example // get the transformations : this comes from animation code for example
@@ -481,7 +503,7 @@ void SGShadowVolume::ShadowCaster::computeShadows(sgMat4 rotation, sgMat4 rotati
} }
glCullFace(GL_BACK); glCullFace(GL_BACK);
DrawInfiniteShadowVolume( lightPos, false); DrawInfiniteShadowVolume( lightPos, states->shadowsAC_transp_enabled & isTranslucent);
//Decrement stencil buffer for back face depth pass //Decrement stencil buffer for back face depth pass
if( states->use_alpha ) { if( states->use_alpha ) {
@@ -493,43 +515,16 @@ void SGShadowVolume::ShadowCaster::computeShadows(sgMat4 rotation, sgMat4 rotati
} }
glCullFace(GL_FRONT); glCullFace(GL_FRONT);
DrawInfiniteShadowVolume( lightPos, false); DrawInfiniteShadowVolume( lightPos, states->shadowsAC_transp_enabled & isTranslucent);
} }
} }
void SGShadowVolume::SceneryObject::computeShadows(void) { void SGShadowVolume::SceneryObject::computeShadows(void) {
bool intersect = true;
// compute intersection with view frustum // compute intersection with view frustum
// use pending_object (pointer on obj transform) & tile transform // use pending_object (pointer on obj transform) & tile transform
// to get position // to get position
sgMat4 position, CamXpos;
sgFrustum *f = ssgGetFrustum();
pending_object->getParent(0)->getNetTransform( position );
sgCopyMat4 ( CamXpos, states->CameraViewM ) ;
sgPreMultMat4 ( CamXpos, position ) ;
sgSphere tmp = *(pending_object->getBSphere()) ;
if ( tmp.isEmpty () )
intersect = false;
else {
// 7000
float max_dist = 5000.0f;
tmp . orthoXform ( CamXpos ) ;
// cull if too far
if ( -tmp.center[2] - tmp.radius > max_dist )
intersect = false;
else if( tmp.center[2] == 0.0 )
intersect = true;
// cull if too small on screen
else if ( tmp.radius / sgAbs(tmp.center[2]) < 1.0 / 40.0 )
intersect = false;
else
intersect = SSG_OUTSIDE != (ssgCullResult) f -> contains ( &tmp );
}
if( intersect ) {
if( !scenery_object ) { if( !scenery_object ) {
if( states->frameNumber - states->lastTraverseTreeFrame > 5 ) { if( states->frameNumber - states->lastTraverseTreeFrame > 5 ) {
find_trans(); find_trans();
@@ -552,6 +547,74 @@ void SGShadowVolume::SceneryObject::computeShadows(void) {
for(iShadowCaster = parts.begin() ; iShadowCaster != parts.end() ; iShadowCaster ++ ) { for(iShadowCaster = parts.begin() ; iShadowCaster != parts.end() ; iShadowCaster ++ ) {
(*iShadowCaster)->computeShadows(rotation, rotation_translation, occluder_type); (*iShadowCaster)->computeShadows(rotation, rotation_translation, occluder_type);
} }
}
static ssgCullResult cull_test ( ssgEntity *e, sgFrustum *f, sgMat4 m, int test_needed )
{
if ( ! test_needed )
return SSG_INSIDE ;
sgSphere tmp = *(e->getBSphere()) ;
if ( tmp.isEmpty () )
return SSG_OUTSIDE ;
tmp . orthoXform ( m ) ;
if( tmp.center[2] == 0.0 )
return SSG_STRADDLE;
// cull if too small on screen
if ( tmp.radius / sgAbs(tmp.center[2]) < 1.0 / 40.0 )
return SSG_OUTSIDE ;
return (ssgCullResult) f -> contains ( &tmp ) ;
}
void SGShadowVolume::cull ( ssgBranch *b, sgFrustum *f, sgMat4 m, int test_needed )
{
int cull_result = cull_test ( (ssgEntity *) b, f, m, test_needed ) ;
if ( cull_result == SSG_OUTSIDE )
return ;
if( b->isA( ssgTypeTransform() ) ) {
SceneryObject_map::iterator iSceneryObject = sceneryObjects.find( b );
if( iSceneryObject != sceneryObjects.end() ) {
SceneryObject *an_occluder = iSceneryObject->second;
if( shadowsTO_enabled && (an_occluder->occluder_type == occluderTypeTileObject) ||
shadowsAI_enabled && (an_occluder->occluder_type == occluderTypeAI ) ||
shadowsAC_enabled && (an_occluder->occluder_type == occluderTypeAircraft ) )
an_occluder->computeShadows();
return;
}
sgMat4 tmp, transform ;
sgCopyMat4 ( tmp, m ) ;
((ssgTransform *)b)->getTransform( transform );
sgPreMultMat4 ( tmp, transform ) ;
glPushMatrix () ;
glLoadMatrixf ( (float *) tmp ) ;
for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid() )
cull ( (ssgBranch *) e, f, tmp, cull_result != SSG_INSIDE ) ;
glPopMatrix () ;
} else if( b->isAKindOf( ssgTypeSelector() ) ) {
int s = ((ssgSelector *) b)->getSelect() ;
if( b->isA( ssgTypeRangeSelector() ) ) {
float range = sgLengthVec3 ( m [ 3 ] ) ;
s = (range < ((ssgRangeSelector *) b)->getRange(1) &&
range >= ((ssgRangeSelector *) b)->getRange(0) ) ? 1 : 0;
}
for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid(), s >>= 1 )
if ( s & 1 )
cull ( (ssgBranch *) e, f, m, cull_result != SSG_INSIDE ) ;
} else if( b->isAKindOf( ssgTypeBranch() ) ) {
char *name = b->getName();
// quick exit for the hundreds of ground leafs
if( name && !strcmp(name, "LocalTerrain") )
return;
for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid() )
if( ! e->isAKindOf( ssgTypeLeaf() ) )
cull ( (ssgBranch *) e, f, m, cull_result != SSG_INSIDE ) ;
} }
} }
@@ -567,7 +630,11 @@ void SGShadowVolume::SceneryObject::computeShadows(void) {
overhead for matrix computation) and at the end this will reduce the number of overhead for matrix computation) and at the end this will reduce the number of
silouhette edge by a lot too. silouhette edge by a lot too.
*/ */
static bool filterName(const char *leaf_name) { static bool filterLeaf(ssgLeaf *this_kid) {
const char *leaf_name = this_kid->getName();
/* ssgSimpleState *sst = (ssgSimpleState *) this_kid->getState();
if( sst && sst->isTranslucent() )
return false;*/
if( ! leaf_name ) if( ! leaf_name )
return true; return true;
char lname[20]; char lname[20];
@@ -586,13 +653,14 @@ void SGShadowVolume::SceneryObject::traverseTree(ssgBranch *branch) {
if( sgCheckAnimationBranch( (ssgEntity *) branch ) ) { if( sgCheckAnimationBranch( (ssgEntity *) branch ) ) {
if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1) if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1)
return; if( ((SGShadowAnimation *) branch->getUserData())->get_condition_value() )
return;
} }
for(int i = 0 ; i < branch->getNumKids() ; i++) { for(int i = 0 ; i < branch->getNumKids() ; i++) {
ssgEntity *this_kid = branch->getKid( i ); ssgEntity *this_kid = branch->getKid( i );
if( this_kid->isAKindOf(ssgTypeLeaf()) ) { if( this_kid->isAKindOf(ssgTypeLeaf()) ) {
if( filterName( this_kid->getName()) ) { if( filterLeaf( (ssgLeaf *) this_kid ) ) {
num_tri += ((ssgLeaf *) this_kid)->getNumTriangles(); num_tri += ((ssgLeaf *) this_kid)->getNumTriangles();
num_leaf ++; num_leaf ++;
} }
@@ -605,13 +673,17 @@ void SGShadowVolume::SceneryObject::traverseTree(ssgBranch *branch) {
ShadowCaster *new_part = new ShadowCaster( num_tri, branch); ShadowCaster *new_part = new ShadowCaster( num_tri, branch);
new_part->scenery_object = scenery_object; new_part->scenery_object = scenery_object;
new_part->lib_object = lib_object; new_part->lib_object = lib_object;
new_part->isTranslucent = false;
for(int i = 0 ; i < branch->getNumKids() ; i++) { for(int i = 0 ; i < branch->getNumKids() ; i++) {
ssgEntity *this_kid = branch->getKid( i ); ssgEntity *this_kid = branch->getKid( i );
if( this_kid->isAKindOf(ssgTypeLeaf()) ) { if( this_kid->isAKindOf(ssgTypeLeaf()) ) {
if( filterName( this_kid->getName()) ) if( filterLeaf( (ssgLeaf *) this_kid ) )
new_part->addLeaf( tri_idx, ind_idx, (ssgLeaf *) this_kid ); new_part->addLeaf( tri_idx, ind_idx, (ssgLeaf *) this_kid );
} }
} }
// only do that for aircraft
if( occluder_type != SGShadowVolume::occluderTypeAircraft )
new_part->isTranslucent = false;
new_part->SetConnectivity(); new_part->SetConnectivity();
parts.push_back( new_part ); parts.push_back( new_part );
} }
@@ -619,10 +691,8 @@ void SGShadowVolume::SceneryObject::traverseTree(ssgBranch *branch) {
void SGShadowVolume::SceneryObject::find_trans(void) { void SGShadowVolume::SceneryObject::find_trans(void) {
ssgBranch *branch = pending_object; ssgBranch *branch = pending_object;
ssgBranch *prev_branch = pending_object;
// check the existence of the root node // check the existence of the root node
while( branch && branch->getNumParents() > 0 ) { while( branch && branch->getNumParents() > 0 ) {
prev_branch = branch;
branch = branch->getParent(0); branch = branch->getParent(0);
} }
// check if we are connected to the scene graph // check if we are connected to the scene graph
@@ -688,8 +758,8 @@ void SGShadowVolume::computeShadows(void) {
glDisable( GL_FOG ); glDisable( GL_FOG );
glEnable( GL_CULL_FACE ); glEnable( GL_CULL_FACE );
// glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); // glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
// glPolygonOffset(0.0,5.0); glPolygonOffset(0.0,2.0);
glPolygonOffset(0.0,30.0); // glPolygonOffset(0.0,30.0);
glEnable(GL_POLYGON_OFFSET_FILL); glEnable(GL_POLYGON_OFFSET_FILL);
glShadeModel(GL_FLAT); glShadeModel(GL_FLAT);
@@ -698,14 +768,15 @@ void SGShadowVolume::computeShadows(void) {
glEnable( GL_DEPTH_TEST ); glEnable( GL_DEPTH_TEST );
glDepthFunc(GL_LESS); glDepthFunc(GL_LESS);
SceneryObject_map::iterator iSceneryObject; {
// compute shadows for each objects float w, h;
for(iSceneryObject = sceneryObjects.begin() ; iSceneryObject != sceneryObjects.end(); iSceneryObject++ ) { sgFrustum frustum;
SceneryObject *an_occluder = iSceneryObject->second; sgEnviro.getFOV( w, h );
if( shadowsTO_enabled && (an_occluder->occluder_type == occluderTypeTileObject) || frustum.setFOV( w, h );
shadowsAI_enabled && (an_occluder->occluder_type == occluderTypeAI ) || frustum.setNearFar(0.1f, 5000.0f);
shadowsAC_enabled && (an_occluder->occluder_type == occluderTypeAircraft ) ) sgMat4 m;
an_occluder->computeShadows(); ssgGetModelviewMatrix( m );
cull( ssg_root, &frustum, m, true);
} }
@@ -779,11 +850,12 @@ void SGShadowVolume::computeShadows(void) {
glPopAttrib(); glPopAttrib();
} }
SGShadowVolume::SGShadowVolume() : SGShadowVolume::SGShadowVolume( ssgBranch *root ) :
init_done( false ),
shadows_enabled( false ), shadows_enabled( false ),
frameNumber( 0 ), frameNumber( 0 ),
lastTraverseTreeFrame ( 0 ) lastTraverseTreeFrame ( 0 ),
ssg_root( root ),
shadows_rendered( false )
{ {
states = this; states = this;
} }
@@ -797,7 +869,6 @@ SGShadowVolume::~SGShadowVolume() {
} }
void SGShadowVolume::init(SGPropertyNode *sim_rendering_options) { void SGShadowVolume::init(SGPropertyNode *sim_rendering_options) {
init_done = true;
shadows_enabled = true; shadows_enabled = true;
sim_rendering = sim_rendering_options; sim_rendering = sim_rendering_options;
int stencilBits = 0, alphaBits = 0; int stencilBits = 0, alphaBits = 0;
@@ -819,15 +890,13 @@ void SGShadowVolume::init(SGPropertyNode *sim_rendering_options) {
void SGShadowVolume::startOfFrame(void) { void SGShadowVolume::startOfFrame(void) {
} }
void SGShadowVolume::deleteOccluderFromTile(ssgBranch *tile) { void SGShadowVolume::deleteOccluderFromTile(ssgBranch *tile) {
SceneryObject_map::iterator iSceneryObject, iPrevious; SceneryObject_map::iterator iSceneryObject;
iPrevious = sceneryObjects.begin(); for(iSceneryObject = sceneryObjects.begin() ; iSceneryObject != sceneryObjects.end(); ) {
for(iSceneryObject = sceneryObjects.begin() ; iSceneryObject != sceneryObjects.end(); iSceneryObject++ ) { SceneryObject_map::iterator iCurrent = iSceneryObject ++;
if( iSceneryObject->second->tile == tile ) { if( iCurrent->second->tile == tile ) {
delete iSceneryObject->second; delete iCurrent->second;
sceneryObjects.erase( iSceneryObject ); sceneryObjects.erase( iCurrent );
iSceneryObject = iPrevious;
} }
iPrevious = iSceneryObject;
} }
} }
@@ -868,10 +937,10 @@ void SGShadowVolume::setupShadows( double lon, double lat,
double gst, double SunRightAscension, double SunDeclination, double sunAngle) { double gst, double SunRightAscension, double SunDeclination, double sunAngle) {
shadowsAC_enabled = sim_rendering->getBoolValue("shadows-ac", false); shadowsAC_enabled = sim_rendering->getBoolValue("shadows-ac", false);
shadowsAC_transp_enabled = sim_rendering->getBoolValue("shadows-ac-transp", false);
shadowsAI_enabled = sim_rendering->getBoolValue("shadows-ai", false); shadowsAI_enabled = sim_rendering->getBoolValue("shadows-ai", false);
shadowsTO_enabled = sim_rendering->getBoolValue("shadows-to", false); shadowsTO_enabled = sim_rendering->getBoolValue("shadows-to", false);
shadowsDebug_enabled = sim_rendering->getBoolValue("shadows-debug", false); shadowsDebug_enabled = sim_rendering->getBoolValue("shadows-debug", false);
// shadows_enabled = sim_rendering->getBoolValue("shadows", false);
shadows_enabled = shadowsAC_enabled || shadowsAI_enabled || shadowsTO_enabled; shadows_enabled = shadowsAC_enabled || shadowsAI_enabled || shadowsTO_enabled;
shadows_enabled &= canDoAlpha || canDoStencil; shadows_enabled &= canDoAlpha || canDoStencil;
use_alpha = ((!canDoStencil) || sim_rendering->getBoolValue("shadows-alpha", false)) && use_alpha = ((!canDoStencil) || sim_rendering->getBoolValue("shadows-alpha", false)) &&
@@ -880,29 +949,8 @@ void SGShadowVolume::setupShadows( double lon, double lat,
if( ! shadows_enabled ) if( ! shadows_enabled )
return; return;
sgMat4 view_angle; shadows_rendered = false;
sun_angle = sunAngle; sun_angle = sunAngle;
{
sgMat4 LON, LAT;
sgVec3 axis;
sgSetVec3( axis, 0.0, 0.0, 1.0 );
sgMakeRotMat4( LON, lon, axis );
sgSetVec3( axis, 0.0, 1.0, 0.0 );
sgMakeRotMat4( LAT, 90.0 - lat, axis );
sgMat4 TRANSFORM;
sgMakeIdentMat4 ( TRANSFORM );
sgPreMultMat4( TRANSFORM, LON );
sgPreMultMat4( TRANSFORM, LAT );
sgCoord pos;
sgSetCoord( &pos, TRANSFORM );
sgMakeCoordMat4( view_angle, &pos );
}
{ {
sgMat4 GST, RA, DEC; sgMat4 GST, RA, DEC;
sgVec3 axis; sgVec3 axis;
@@ -917,8 +965,6 @@ void SGShadowVolume::setupShadows( double lon, double lat,
sgSetVec3( axis, 1.0, 0.0, 0.0 ); sgSetVec3( axis, 1.0, 0.0, 0.0 );
sgMakeRotMat4( DEC, SunDeclination * SGD_RADIANS_TO_DEGREES, axis ); sgMakeRotMat4( DEC, SunDeclination * SGD_RADIANS_TO_DEGREES, axis );
sgInvertMat4( invViewAngle, view_angle);
sgMat4 TRANSFORM; sgMat4 TRANSFORM;
sgMakeIdentMat4( TRANSFORM ); sgMakeIdentMat4( TRANSFORM );
sgPreMultMat4( TRANSFORM, GST ); sgPreMultMat4( TRANSFORM, GST );
@@ -935,13 +981,20 @@ void SGShadowVolume::setupShadows( double lon, double lat,
void SGShadowVolume::endOfFrame(void) { void SGShadowVolume::endOfFrame(void) {
if( ! shadows_enabled ) if( ! shadows_enabled )
return; return;
if( shadows_rendered )
return;
glBindTexture(GL_TEXTURE_2D, 0); glBindTexture(GL_TEXTURE_2D, 0);
glBindTexture(GL_TEXTURE_1D, 0); glBindTexture(GL_TEXTURE_1D, 0);
glMatrixMode(GL_MODELVIEW); glMatrixMode(GL_MODELVIEW);
computeShadows(); computeShadows();
frameNumber ++; frameNumber ++;
shadows_rendered = true;
}
int SGShadowVolume::ACpostTravCB( ssgEntity *entity, int traversal_mask ) {
if( states->shadowsAC_transp_enabled && (SSGTRAV_CULL & traversal_mask) )
states->endOfFrame();
return 0;
} }
+8 -11
View File
@@ -41,7 +41,7 @@ class SGPropertyNode;
class SGShadowVolume { class SGShadowVolume {
public: public:
SGShadowVolume(); SGShadowVolume( ssgBranch *root );
~SGShadowVolume(); ~SGShadowVolume();
typedef enum { typedef enum {
@@ -58,7 +58,7 @@ public:
void setupShadows(double lon, double lat, void setupShadows(double lon, double lat,
double gst, double SunRightAscension, double SunDeclination, double sunAngle ); double gst, double SunRightAscension, double SunDeclination, double sunAngle );
void endOfFrame(void); void endOfFrame(void);
static int ACpostTravCB( ssgEntity *entity, int traversal_mask );
private: private:
@@ -87,7 +87,7 @@ private:
sgVec4 * vertices; sgVec4 * vertices;
GLushort *silhouetteEdgeIndices; GLushort *silhouetteEdgeIndices;
int lastSilhouetteIndicesCount; int lastSilhouetteIndicesCount;
bool isTranslucent;
ShadowCaster( int _num_tri, ssgBranch * _geometry_leaf ); ShadowCaster( int _num_tri, ssgBranch * _geometry_leaf );
~ShadowCaster(); ~ShadowCaster();
@@ -97,7 +97,7 @@ private:
void DrawInfiniteShadowVolume(sgVec3 lightPosition, bool drawCaps); void DrawInfiniteShadowVolume(sgVec3 lightPosition, bool drawCaps);
void computeShadows(sgMat4 rotation, sgMat4 rotation_translation, OccluderType occluder_type); void computeShadows(sgMat4 rotation, sgMat4 rotation_translation, OccluderType occluder_type);
void getNetTransform ( ssgBranch * branch, sgMat4 xform ); void getNetTransform ( ssgBranch * branch, sgMat4 xform );
bool isSelected ( ssgBranch * branch ); bool isSelected ( ssgBranch * branch, float dist);
bool sameVertex(int edge1, int edge2); bool sameVertex(int edge1, int edge2);
}; };
@@ -123,10 +123,11 @@ private:
private: private:
void update_light_view(void); void update_light_view(void);
void computeShadows(void); void computeShadows(void);
void cull ( ssgBranch *b, sgFrustum *f, sgMat4 m, int test_needed );
bool init_done;
bool shadows_enabled; bool shadows_enabled;
bool shadowsAC_enabled, shadowsAI_enabled, shadowsTO_enabled, shadowsDebug_enabled; bool shadowsAC_enabled, shadowsAI_enabled, shadowsTO_enabled, shadowsDebug_enabled;
bool shadowsAC_transp_enabled;
bool use_alpha; bool use_alpha;
bool canDoAlpha, canDoStencil; bool canDoAlpha, canDoStencil;
SGPropertyNode *sim_rendering; SGPropertyNode *sim_rendering;
@@ -135,14 +136,10 @@ private:
int frameNumber; int frameNumber;
int lastTraverseTreeFrame; int lastTraverseTreeFrame;
sgMat4 CameraViewM; sgMat4 CameraViewM;
sgMat4 invViewAngle;
double sun_angle; double sun_angle;
SceneryObject_map sceneryObjects; SceneryObject_map sceneryObjects;
/** this sphere contains the visible scene and is used to cull shadow casters */ ssgBranch *ssg_root;
sgSphere frustumSphere; bool shadows_rendered;
/** this sphere contains the near clip plane and is used to check the need of a zfail */
sgSphere nearClipSphere;
}; };
#endif // _SHADOWVOLUME_HXX #endif // _SHADOWVOLUME_HXX