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:
@@ -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
|
||||||
|
|||||||
@@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -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);
|
||||||
|
|||||||
@@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user