00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifdef HAVE_CONFIG_H
00024 # include <simgear_config.h>
00025 #endif
00026
00027 #include <plib/sg.h>
00028 #include <simgear/debug/logstream.hxx>
00029 #include <simgear/screen/extensions.hxx>
00030 #include <simgear/scene/model/animation.hxx>
00031 #include <simgear/scene/model/model.hxx>
00032 #include <simgear/environment/visual_enviro.hxx>
00033 #include <osg/GLU>
00034
00035 #include "shadowvolume.hxx"
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090 static int statSilhouette=0;
00091 static int statGeom=0;
00092 static int statObj=0;
00093
00094 static SGShadowVolume *states;
00095 static glBlendEquationProc glBlendEquationPtr = NULL;
00096 #define GL_MIN_EXT 0x8007
00097 #define GL_MAX_EXT 0x8008
00098
00099
00100 SGShadowVolume::ShadowCaster::ShadowCaster( int _num_tri, ssgBranch * _geometry_leaf ) :
00101 geometry_leaf ( _geometry_leaf ),
00102 scenery_object ( 0 ),
00103 first_select ( 0 ),
00104 frameNumber ( 0 ),
00105 indices ( 0 ),
00106 numTriangles ( 0 ),
00107 vertices ( 0 ),
00108 lastSilhouetteIndicesCount ( 0 )
00109 {
00110 int num_tri = _num_tri;
00111 numTriangles = num_tri;
00112 triangles = new triData[ num_tri ];
00113 indices = new int[1 + num_tri * 3];
00114 vertices = new sgVec4[1 + num_tri * 3];
00115 silhouetteEdgeIndices = new GLushort[(1+num_tri) * 3*3];
00116 indices [ num_tri * 3 ] = num_tri * 3;
00117 sgSetVec3(last_lightpos, 0.0, 0.0, 0.0);
00118 statGeom ++;
00119
00120 ssgBranch *branch = (ssgBranch *) _geometry_leaf;
00121 while( branch && branch->getNumParents() > 0 ) {
00122 if( branch->isAKindOf(ssgTypeSelector())) {
00123 first_select = branch;
00124 break;
00125 }
00126 if( sgCheckAnimationBranch( (ssgEntity *) branch ) )
00127 if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1) {
00128 first_select = branch;
00129 break;
00130 }
00131 branch = branch->getParent(0);
00132 }
00133 }
00134
00135 void SGShadowVolume::ShadowCaster::addLeaf( int & tri_idx, int & ind_idx, ssgLeaf *geometry_leaf ) {
00136 int num_tri = geometry_leaf->getNumTriangles();
00137 for(int i = 0; i < num_tri ; i ++ ) {
00138 short v1, v2, v3;
00139 sgVec3 a, b, c;
00140 geometry_leaf->getTriangle( i, &v1, &v2, &v3 );
00141 sgCopyVec3(a, geometry_leaf->getVertex(v1));
00142 sgCopyVec3(b, geometry_leaf->getVertex(v2));
00143 sgCopyVec3(c, geometry_leaf->getVertex(v3));
00144
00145 int p = tri_idx;
00146 sgMakePlane ( triangles[p].planeEquations, a, b, c );
00147 sgCopyVec3(vertices[ind_idx + v1], a);
00148 sgCopyVec3(vertices[ind_idx + v2], b);
00149 sgCopyVec3(vertices[ind_idx + v3], c);
00150 vertices[ind_idx + v1][SG_W] = 1.0f;
00151 vertices[ind_idx + v2][SG_W] = 1.0f;
00152 vertices[ind_idx + v3][SG_W] = 1.0f;
00153 indices[p*3] = ind_idx + v1;
00154 indices[p*3+1] = ind_idx + v2;
00155 indices[p*3+2] = ind_idx + v3;
00156
00157 tri_idx++;
00158 }
00159 if( num_tri == 0 )
00160 return;
00161 isTranslucent |= geometry_leaf->isTranslucent() ? true : false;
00162 int num_ind = geometry_leaf->getNumVertices();
00163 ind_idx += num_ind;
00164 }
00165
00166 SGShadowVolume::ShadowCaster::~ShadowCaster() {
00167 delete [] indices ;
00168 delete [] vertices ;
00169 delete [] triangles;
00170 delete [] silhouetteEdgeIndices;
00171 }
00172
00173
00174
00175 bool SGShadowVolume::ShadowCaster::sameVertex(int edge1, int edge2) {
00176 if( edge1 == edge2)
00177 return true;
00178 sgVec3 delta_v;
00179 sgSubVec3( delta_v, vertices[edge1], vertices[edge2]);
00180 if( delta_v[SG_X] != 0.0) return false;
00181 if( delta_v[SG_Y] != 0.0) return false;
00182 if( delta_v[SG_Z] != 0.0) return false;
00183 return true;
00184 }
00185
00186
00187
00188
00189 void SGShadowVolume::ShadowCaster::SetConnectivity(void)
00190 {
00191 int edgeCount = 0;
00192
00193
00194 for(int ii=0; ii<numTriangles; ++ii)
00195 triangles[ii].neighbourIndices[0] =
00196 triangles[ii].neighbourIndices[1] =
00197 triangles[ii].neighbourIndices[2] = -1;
00198
00199
00200 for(int i=0; i<numTriangles-1; ++i)
00201 {
00202
00203 for(int edgeI=0; edgeI<3; ++edgeI)
00204 {
00205
00206 if(triangles[i].neighbourIndices[ edgeI ]!=-1)
00207 continue;
00208
00209
00210 int edgeI1=indices[i*3+edgeI];
00211 int edgeI2=indices[i*3+(edgeI == 2 ? 0 : edgeI+1)];
00212
00213
00214 for(int j=i+1; j<numTriangles; ++j)
00215 {
00216
00217 for(int edgeJ=0; edgeJ<3; ++edgeJ)
00218 {
00219
00220 if(triangles[j].neighbourIndices[ edgeJ ]!=-1) {
00221 continue;
00222 }
00223
00224 int edgeJ1=indices[j*3+edgeJ];
00225 int edgeJ2=indices[j*3+(edgeJ == 2 ? 0 : edgeJ+1)];
00226
00227
00228 #if 0
00229
00230
00231 if( sameVertex(edgeI1, edgeJ1) && sameVertex(edgeI2, edgeJ2) ) {
00232
00233
00234 continue;
00235 }
00236 #endif
00237 if( sameVertex(edgeI1, edgeJ2) && sameVertex(edgeI2, edgeJ1) )
00238 {
00239 int edgeI3=indices[i*3+(edgeI == 0 ? 2 : edgeI-1)];
00240 int edgeJ3=indices[j*3+(edgeJ == 0 ? 2 : edgeJ-1)];
00241 if( sameVertex(edgeI3, edgeJ3) ) {
00242
00243
00244
00245 break;
00246 }
00247 triangles[i].neighbourIndices[edgeI]=j;
00248 triangles[j].neighbourIndices[edgeJ]=i;
00249 edgeCount ++;
00250
00251 j = numTriangles;
00252 break;
00253 }
00254 }
00255 }
00256 }
00257 }
00258
00259 }
00260
00261
00262 void SGShadowVolume::ShadowCaster::CalculateSilhouetteEdges(sgVec3 lightPosition)
00263 {
00264
00265 for(int i=0; i<numTriangles; ++i)
00266 {
00267 if( sgDistToPlaneVec3 ( triangles[i].planeEquations, lightPosition ) > 0.0 )
00268 triangles[i].isFacingLight=true;
00269 else
00270 triangles[i].isFacingLight=false;
00271 }
00272
00273
00274 int iEdgeIndices = 0;
00275 sgVec4 farCap = {-lightPosition[SG_X], -lightPosition[SG_Y], -lightPosition[SG_Z], 1.0f};
00276 sgCopyVec4( vertices[ numTriangles*3 ], farCap );
00277
00278 for(int t=0; t < numTriangles; t++) {
00279 int v = t * 3;
00280
00281 if(!triangles[t].isFacingLight)
00282 {
00283 triangles[t].isSilhouetteEdge[0]=false;
00284 triangles[t].isSilhouetteEdge[1]=false;
00285 triangles[t].isSilhouetteEdge[2]=false;
00286 continue;
00287 }
00288
00289 for(int j = 0 ; j < 3 ; j++) {
00290
00291
00292
00293 if(triangles[t].neighbourIndices[j]==-1 ||
00294 !triangles[triangles[t].neighbourIndices[j]].isFacingLight ) {
00295 triangles[t].isSilhouetteEdge[j]=true;
00296 silhouetteEdgeIndices[ iEdgeIndices++ ] = indices[v+(j == 2 ? 0 : j+1)];
00297 silhouetteEdgeIndices[ iEdgeIndices++ ] = indices[v+j];
00298 silhouetteEdgeIndices[ iEdgeIndices++ ] = numTriangles * 3;
00299 }
00300 else
00301 triangles[t].isSilhouetteEdge[j]=false;
00302 }
00303 }
00304 lastSilhouetteIndicesCount = iEdgeIndices;
00305 }
00306
00307 void SGShadowVolume::ShadowCaster::DrawInfiniteShadowVolume(sgVec3 lightPosition, bool drawCaps)
00308 {
00309 glEnableClientState ( GL_VERTEX_ARRAY ) ;
00310 glVertexPointer ( 4, GL_FLOAT, 0, vertices ) ;
00311 glDrawElements ( GL_TRIANGLES, lastSilhouetteIndicesCount, GL_UNSIGNED_SHORT, silhouetteEdgeIndices ) ;
00312
00313
00314 if(drawCaps)
00315 {
00316 glBegin(GL_TRIANGLES);
00317 {
00318 for(int i=0; i<numTriangles; ++i)
00319 {
00320 if(triangles[i].isFacingLight) {
00321 int v = i*3;
00322 glVertex3fv( vertices[indices[v+0]] );
00323 glVertex3fv( vertices[indices[v+1]] );
00324 glVertex3fv( vertices[indices[v+2]] );
00325 }
00326 }
00327 }
00328 glEnd();
00329 }
00330 }
00331
00332
00333 void SGShadowVolume::ShadowCaster::getNetTransform ( ssgBranch * branch, sgMat4 xform )
00334 {
00335
00336 bool first = true;
00337 while( branch && branch != lib_object ) {
00338 if( branch->isA(ssgTypeTransform()) ) {
00339 sgMat4 transform;
00340 if( first ) {
00341 ((ssgTransform *) branch)->getTransform( xform );
00342 first = false;
00343 } else {
00344 ((ssgTransform *) branch)->getTransform(transform);
00345 sgPostMultMat4 ( xform, transform ) ;
00346 }
00347 }
00348 branch = branch->getParent( 0 );
00349 }
00350 if( first )
00351 sgMakeIdentMat4 ( xform ) ;
00352 }
00353
00354
00355
00356 bool SGShadowVolume::ShadowCaster::isSelected ( ssgBranch * branch, float dist ) {
00357 while( branch && branch != lib_object) {
00358 if( sgCheckAnimationBranch( (ssgEntity *) branch ) ) {
00359 if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1)
00360 if( ((SGShadowAnimation *) branch->getUserData())->get_condition_value() )
00361 return false;
00362 }
00363
00364
00365 if( branch->isA(ssgTypeRangeSelector()) )
00366 if( dist >= ((ssgRangeSelector *) branch)->getRange(1) ||
00367 dist < ((ssgRangeSelector *) branch)->getRange(0))
00368 return false;
00369 if( branch->isA(ssgTypeSelector()) )
00370 if( !((ssgSelector *) branch)->isSelected(0) )
00371 return false;
00372 branch = branch->getParent(0);
00373 }
00374 return true;
00375 }
00376
00377
00378
00379
00380
00381
00382
00383
00384 void SGShadowVolume::ShadowCaster::computeShadows(sgMat4 rotation, sgMat4 rotation_translation,
00385 OccluderType occluder_type) {
00386
00387
00388
00389 sgVec4 trans;
00390 sgCopyVec4( trans, rotation_translation[3] );
00391 sgAddVec4( trans, states->CameraViewM[3] );
00392 float dist = sgLengthVec3( trans );
00393
00394 if( first_select && ! isSelected( first_select, dist) )
00395 return;
00396
00397
00398
00399 sgMat4 transf;
00400 sgVec3 lightPos;
00401 int deltaFrame = occluder_type == SGShadowVolume::occluderTypeAircraft ? 0 : 9;
00402 if( states->frameNumber - frameNumber > deltaFrame) {
00403 sgMat4 transform ;
00404 sgMat4 invTransform;
00405 getNetTransform( (ssgBranch *) geometry_leaf, transform );
00406 sgCopyMat4( last_transform, transform );
00407 sgPostMultMat4( transform, rotation );
00408 sgTransposeNegateMat4 ( invTransform, transform );
00409
00410 sgCopyVec3( lightPos, states->sunPos );
00411 sgXformPnt3( lightPos, invTransform );
00412
00413 sgVec3 lightPosNorm;
00414 sgNormaliseVec3( lightPosNorm, lightPos );
00415 float deltaPos = sgAbs(lightPosNorm[0] - last_lightpos[0]) +
00416 sgAbs(lightPosNorm[1] - last_lightpos[1]) +
00417 sgAbs(lightPosNorm[2] - last_lightpos[2]);
00418
00419
00420
00421 if( deltaPos > 0.0 ) {
00422 CalculateSilhouetteEdges( lightPos );
00423 sgCopyVec3( last_lightpos, lightPosNorm );
00424 frameNumber = states->frameNumber ;
00425 statSilhouette ++;
00426 }
00427 }
00428 sgCopyMat4( transf, last_transform );
00429 sgPostMultMat4( transf, rotation_translation );
00430 glLoadMatrixf ( (float *) states->CameraViewM ) ;
00431 glMultMatrixf( (float *) transf );
00432
00433 if( states->shadowsDebug_enabled )
00434 {
00435 glStencilFunc(GL_ALWAYS, 0, ~0);
00436 glDisable( GL_CULL_FACE );
00437 glDisable( GL_DEPTH_TEST );
00438 glDisable(GL_STENCIL_TEST);
00439 glColorMask(1, 1, 1, 1);
00440 glColor4f(0.0, 0.0, 1.0, 1.0);
00441 glBegin(GL_LINES);
00442 for(int i=0; i<numTriangles; ++i)
00443 {
00444 if(!triangles[i].isFacingLight)
00445 continue;
00446 int v = i*3;
00447
00448 sgVec3 vertex1, vertex2, vertex3;
00449 sgCopyVec3(vertex1, vertices[indices[v+0]]);
00450 sgCopyVec3(vertex2, vertices[indices[v+1]]);
00451 sgCopyVec3(vertex3, vertices[indices[v+2]]);
00452
00453 if(triangles[i].isSilhouetteEdge[0]) {
00454 glVertex3fv(vertex2);
00455 glVertex3fv(vertex1);
00456 }
00457 if(triangles[i].isSilhouetteEdge[1]) {
00458 glVertex3fv(vertex2);
00459 glVertex3fv(vertex3);
00460 }
00461 if(triangles[i].isSilhouetteEdge[2]) {
00462 glVertex3fv(vertex3);
00463 glVertex3fv(vertex1);
00464 }
00465 }
00466 glEnd();
00467 glColorMask(0, 0, 0, 0);
00468 glEnable( GL_CULL_FACE );
00469 glEnable( GL_DEPTH_TEST );
00470 glEnable(GL_STENCIL_TEST);
00471 }
00472
00473
00474
00475 bool needZFail=false;
00476
00477
00478
00479 if(needZFail)
00480 {
00481
00482 glStencilFunc(GL_ALWAYS, 0, ~0);
00483 glStencilOp(GL_KEEP, GL_INCR, GL_KEEP);
00484 glCullFace(GL_FRONT);
00485
00486 DrawInfiniteShadowVolume( lightPos, true);
00487
00488
00489 glStencilOp(GL_KEEP, GL_DECR, GL_KEEP);
00490 glCullFace(GL_BACK);
00491
00492 DrawInfiniteShadowVolume( lightPos, true);
00493 }
00494 else
00495 {
00496
00497 if( states->use_alpha ) {
00498 glBlendEquationPtr( GL_FUNC_ADD );
00499 glBlendFunc( GL_ONE, GL_ONE );
00500 glColor4ub(1, 1, 1, 16);
00501 } else {
00502 glColor4f(1.0f, 1.0f, 0.0f, 0.5f);
00503 glStencilFunc(GL_ALWAYS, 0, ~0);
00504 glStencilOp(GL_KEEP, GL_KEEP, GL_INCR);
00505 }
00506 glCullFace(GL_BACK);
00507
00508 DrawInfiniteShadowVolume( lightPos, states->shadowsAC_transp_enabled & isTranslucent);
00509
00510
00511 if( states->use_alpha ) {
00512 glBlendEquationPtr( GL_FUNC_REVERSE_SUBTRACT );
00513 glBlendFunc( GL_ONE, GL_ONE );
00514 glColor4ub(1, 1, 1, 16);
00515 } else {
00516 glStencilOp(GL_KEEP, GL_KEEP, GL_DECR);
00517 }
00518 glCullFace(GL_FRONT);
00519
00520 DrawInfiniteShadowVolume( lightPos, states->shadowsAC_transp_enabled & isTranslucent);
00521 }
00522 }
00523
00524
00525 void SGShadowVolume::SceneryObject::computeShadows(void) {
00526
00527
00528
00529
00530 if( !scenery_object ) {
00531 if( states->frameNumber - states->lastTraverseTreeFrame > 5 ) {
00532 find_trans();
00533 if( scenery_object )
00534 traverseTree( pending_object );
00535 states->lastTraverseTreeFrame = states->frameNumber;
00536 }
00537 return;
00538 }
00539 sgMat4 rotation, rotation_translation;
00540 scenery_object->getNetTransform ( rotation_translation );
00541
00542
00543
00544
00545 sgCopyMat4( rotation, rotation_translation );
00546 sgSetVec4( rotation[3], 0, 0, 0, 1);
00547
00548 ShadowCaster_list::iterator iShadowCaster;
00549 for(iShadowCaster = parts.begin() ; iShadowCaster != parts.end() ; iShadowCaster ++ ) {
00550 (*iShadowCaster)->computeShadows(rotation, rotation_translation, occluder_type);
00551 }
00552 }
00553
00554 static ssgCullResult cull_test ( ssgEntity *e, sgFrustum *f, sgMat4 m, int test_needed )
00555 {
00556 if ( ! test_needed )
00557 return SSG_INSIDE ;
00558
00559 sgSphere tmp = *(e->getBSphere()) ;
00560
00561 if ( tmp.isEmpty () )
00562 return SSG_OUTSIDE ;
00563
00564 tmp . orthoXform ( m ) ;
00565 if( tmp.center[2] == 0.0 )
00566 return SSG_STRADDLE;
00567
00568 if ( tmp.radius / sgAbs(tmp.center[2]) < 1.0 / 40.0 )
00569 return SSG_OUTSIDE ;
00570
00571 return (ssgCullResult) f -> contains ( &tmp ) ;
00572 }
00573
00574
00575 void SGShadowVolume::cull ( ssgBranch *b, sgFrustum *f, sgMat4 m, int test_needed )
00576 {
00577 int cull_result = cull_test ( (ssgEntity *) b, f, m, test_needed ) ;
00578
00579 if ( cull_result == SSG_OUTSIDE )
00580 return ;
00581 if( b->isA( ssgTypeTransform() ) ) {
00582
00583 SceneryObject_map::iterator iSceneryObject = sceneryObjects.find( b );
00584 if( iSceneryObject != sceneryObjects.end() ) {
00585 SceneryObject *an_occluder = iSceneryObject->second;
00586 if( shadowsTO_enabled && (an_occluder->occluder_type == occluderTypeTileObject) ||
00587 shadowsAI_enabled && (an_occluder->occluder_type == occluderTypeAI ) ||
00588 shadowsAC_enabled && (an_occluder->occluder_type == occluderTypeAircraft ) )
00589 an_occluder->computeShadows();
00590
00591 return;
00592 }
00593 sgMat4 tmp, transform ;
00594 sgCopyMat4 ( tmp, m ) ;
00595 ((ssgTransform *)b)->getTransform( transform );
00596 sgPreMultMat4 ( tmp, transform ) ;
00597 glPushMatrix () ;
00598 glLoadMatrixf ( (float *) tmp ) ;
00599 for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid() )
00600 cull ( (ssgBranch *) e, f, tmp, cull_result != SSG_INSIDE ) ;
00601 glPopMatrix () ;
00602 } else if( b->isAKindOf( ssgTypeSelector() ) ) {
00603 int s = ((ssgSelector *) b)->getSelect() ;
00604 if( b->isA( ssgTypeRangeSelector() ) ) {
00605 float range = sgLengthVec3 ( m [ 3 ] ) ;
00606 s = (range < ((ssgRangeSelector *) b)->getRange(1) &&
00607 range >= ((ssgRangeSelector *) b)->getRange(0) ) ? 1 : 0;
00608 }
00609 for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid(), s >>= 1 )
00610 if ( s & 1 )
00611 cull ( (ssgBranch *) e, f, m, cull_result != SSG_INSIDE ) ;
00612 } else if( b->isAKindOf( ssgTypeBranch() ) ) {
00613 char *name = b->getName();
00614
00615 if( name && !strcmp(name, "LocalTerrain") )
00616 return;
00617 for ( ssgEntity *e = b->getKid ( 0 ) ; e != NULL ; e = b->getNextKid() )
00618 if( ! e->isAKindOf( ssgTypeLeaf() ) )
00619 cull ( (ssgBranch *) e, f, m, cull_result != SSG_INSIDE ) ;
00620 }
00621 }
00622
00623
00624
00625
00626
00627
00628
00629
00630
00631
00632
00633
00634
00635 static bool filterLeaf(ssgLeaf *this_kid) {
00636 const char *leaf_name = this_kid->getName();
00637
00638
00639
00640 if( ! leaf_name )
00641 return true;
00642 char lname[20];
00643 unsigned int l = 0;
00644 char *buff;
00645 for( buff = lname; *leaf_name && l < (sizeof( lname )-1); ++buff, l++ )
00646 *buff = tolower(*leaf_name++);
00647 *buff = 0;
00648 if( !strncmp(lname, "noshadow", 8) )
00649 return false;
00650 return true;
00651 }
00652 void SGShadowVolume::SceneryObject::traverseTree(ssgBranch *branch) {
00653 int num_tri = 0;
00654 int num_leaf = 0;
00655
00656 if( sgCheckAnimationBranch( (ssgEntity *) branch ) ) {
00657 if( ((SGAnimation *) branch->getUserData())->get_animation_type() == 1)
00658 if( ((SGShadowAnimation *) branch->getUserData())->get_condition_value() )
00659 return;
00660 }
00661
00662 for(int i = 0 ; i < branch->getNumKids() ; i++) {
00663 ssgEntity *this_kid = branch->getKid( i );
00664 if( this_kid->isAKindOf(ssgTypeLeaf()) ) {
00665 if( filterLeaf( (ssgLeaf *) this_kid ) ) {
00666 num_tri += ((ssgLeaf *) this_kid)->getNumTriangles();
00667 num_leaf ++;
00668 }
00669 } else
00670 traverseTree( (ssgBranch *) this_kid );
00671 }
00672 if( num_tri > 0) {
00673 int tri_idx = 0;
00674 int ind_idx = 0;
00675 ShadowCaster *new_part = new ShadowCaster( num_tri, branch);
00676 new_part->scenery_object = scenery_object;
00677 new_part->lib_object = lib_object;
00678 new_part->isTranslucent = false;
00679 for(int i = 0 ; i < branch->getNumKids() ; i++) {
00680 ssgEntity *this_kid = branch->getKid( i );
00681 if( this_kid->isAKindOf(ssgTypeLeaf()) ) {
00682 if( filterLeaf( (ssgLeaf *) this_kid ) )
00683 new_part->addLeaf( tri_idx, ind_idx, (ssgLeaf *) this_kid );
00684 }
00685 }
00686
00687 if( occluder_type != SGShadowVolume::occluderTypeAircraft )
00688 new_part->isTranslucent = false;
00689 new_part->SetConnectivity();
00690 parts.push_back( new_part );
00691 }
00692 }
00693
00694 void SGShadowVolume::SceneryObject::find_trans(void) {
00695 ssgBranch *branch = pending_object;
00696
00697 while( branch && branch->getNumParents() > 0 ) {
00698 branch = branch->getParent(0);
00699 }
00700
00701 if( !branch->isA(ssgTypeRoot() ) )
00702 return;
00703 scenery_object = pending_object;
00704 }
00705
00706 SGShadowVolume::SceneryObject::SceneryObject(ssgBranch *_scenery_object, OccluderType _occluder_type) :
00707 scenery_object ( 0 ),
00708 pending_object ( _scenery_object ),
00709 occluder_type ( _occluder_type )
00710 {
00711
00712
00713 statObj++;
00714 if( occluder_type == SGShadowVolume::occluderTypeAircraft )
00715 lib_object = _scenery_object;
00716 else
00717 lib_object = (ssgBranch *) ((ssgBranch *)_scenery_object->getKid(0))->getKid(0);
00718 }
00719
00720 SGShadowVolume::SceneryObject::~SceneryObject()
00721 {
00722 ShadowCaster_list::iterator iParts;
00723 for(iParts = parts.begin() ; iParts != parts.end(); iParts++ ) {
00724 delete *iParts;
00725 }
00726 parts.clear();
00727 }
00728
00729 void SGShadowVolume::computeShadows(void) {
00730
00731
00732
00733 double dot_light = cos(sun_angle);
00734
00735 if( dot_light < 0.2 )
00736 return;
00737
00738
00739 glPushAttrib(GL_ALL_ATTRIB_BITS);
00740 glPushClientAttrib ( GL_CLIENT_VERTEX_ARRAY_BIT ) ;
00741 glDisableClientState ( GL_COLOR_ARRAY ) ;
00742 glDisableClientState ( GL_NORMAL_ARRAY ) ;
00743 glDisableClientState ( GL_TEXTURE_COORD_ARRAY ) ;
00744
00745 if( use_alpha ) {
00746 glColorMask(0, 0, 0, 1);
00747 glClearColor(0.0, 0.0, 0.0, 0.0 );
00748 glClear(GL_COLOR_BUFFER_BIT);
00749 glDisable(GL_ALPHA);
00750 glEnable(GL_BLEND);
00751 } else {
00752 glClearStencil( 0 );
00753 glClear(GL_STENCIL_BUFFER_BIT);
00754 glColorMask(0, 0, 0, 0);
00755 glEnable(GL_STENCIL_TEST);
00756 glDisable(GL_ALPHA);
00757 glDisable(GL_BLEND);
00758 }
00759 glDisable( GL_LIGHTING );
00760 glDisable( GL_FOG );
00761 glEnable( GL_CULL_FACE );
00762
00763 glPolygonOffset(0.0,2.0);
00764
00765 glEnable(GL_POLYGON_OFFSET_FILL);
00766
00767 glShadeModel(GL_FLAT);
00768
00769 glDepthMask( false );
00770 glEnable( GL_DEPTH_TEST );
00771 glDepthFunc(GL_LESS);
00772
00773 {
00774 float w, h;
00775 sgFrustum frustum;
00776 sgEnviro.getFOV( w, h );
00777 frustum.setFOV( w, h );
00778 frustum.setNearFar(0.1f, 5000.0f);
00779 sgMat4 m;
00780 ssgGetModelviewMatrix( m );
00781 cull( ssg_root, &frustum, m, true);
00782 }
00783
00784
00785 glMatrixMode ( GL_PROJECTION ) ;
00786 glPushMatrix () ;
00787 glLoadIdentity () ;
00788 glOrtho ( -100, 100, -100, 100, -1, 1 ) ;
00789 glMatrixMode ( GL_MODELVIEW ) ;
00790 glPushMatrix () ;
00791 glLoadIdentity () ;
00792
00793 glDisable(GL_DEPTH_TEST);
00794 glDisable(GL_CULL_FACE);
00795
00796 glPolygonMode(GL_FRONT, GL_FILL);
00797 if( use_alpha ) {
00798
00799
00800
00801
00802
00803
00804
00805
00806
00807
00808
00809 glBlendEquationPtr( GL_MIN_EXT );
00810 glBlendFunc( GL_DST_COLOR, GL_ONE );
00811 glColor4ub(1, 1, 1, 16);
00812 glRectf(-100,-100,100,100);
00813
00814 glBlendEquationPtr( GL_FUNC_ADD );
00815 glBlendFunc( GL_DST_COLOR, GL_ONE );
00816 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00817 glRectf(-100,-100,100,100);
00818 glRectf(-100,-100,100,100);
00819
00820 glBlendFunc( GL_ONE_MINUS_DST_COLOR, GL_ZERO );
00821 glColor4f(1.0f, 1.0f, 1.0f, 1.0f);
00822 glRectf(-100,-100,100,100);
00823
00824 glColorMask(1, 1, 1, 1);
00825 glBlendFunc( GL_ZERO, GL_DST_ALPHA );
00826 glColor4f(1.0f, 0.5f, 0.2f, 1.0f);
00827 glRectf(-100,-100,100,100);
00828 } else {
00829
00830
00831
00832 glColorMask(1, 1, 1, 1);
00833 glStencilFunc(GL_NOTEQUAL, 0, ~0);
00834 glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP);
00835 glEnable(GL_STENCIL_TEST);
00836 glEnable(GL_ALPHA);
00837 glAlphaFunc(GL_GREATER, 0.0f);
00838 glEnable(GL_BLEND);
00839 glBlendFunc ( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ) ;
00840 glColor4f(0.0, 0.0, 0.0, sgLerp(0.1, 0.3, dot_light) );
00841
00842 glColor4f(0.0, 0.0, 0.0, 0.3 );
00843 glRectf(-100,-100,100,100);
00844 }
00845 glMatrixMode ( GL_PROJECTION ) ;
00846 glPopMatrix () ;
00847 glMatrixMode ( GL_MODELVIEW ) ;
00848 glPopMatrix () ;
00849
00850 glDisable(GL_STENCIL_TEST);
00851 glPopClientAttrib ( ) ;
00852 glPopAttrib();
00853 }
00854
00855 SGShadowVolume::SGShadowVolume( ssgBranch *root ) :
00856 shadows_enabled( false ),
00857 frameNumber( 0 ),
00858 lastTraverseTreeFrame ( 0 ),
00859 ssg_root( root ),
00860 shadows_rendered( false )
00861 {
00862 states = this;
00863 }
00864
00865 SGShadowVolume::~SGShadowVolume() {
00866 SceneryObject_map::iterator iSceneryObject;
00867 for(iSceneryObject = sceneryObjects.begin() ; iSceneryObject != sceneryObjects.end(); iSceneryObject++ ) {
00868 delete iSceneryObject->second;
00869 }
00870 sceneryObjects.clear();
00871 }
00872
00873 void SGShadowVolume::init(SGPropertyNode *sim_rendering_options) {
00874 shadows_enabled = true;
00875 sim_rendering = sim_rendering_options;
00876 GLint stencilBits = 0, alphaBits = 0;
00877 glGetIntegerv( GL_STENCIL_BITS, &stencilBits );
00878 glGetIntegerv( GL_ALPHA_BITS, &alphaBits );
00879 bool hasSubtractiveBlend = SGIsOpenGLExtensionSupported("GL_EXT_blend_subtract");
00880 bool hasMinMaxBlend = SGIsOpenGLExtensionSupported("GL_EXT_blend_minmax");
00881 if( hasSubtractiveBlend )
00882 glBlendEquationPtr = (glBlendEquationProc ) SGLookupFunction("glBlendEquationEXT");
00883 canDoAlpha = (alphaBits >= 8) && hasSubtractiveBlend && hasMinMaxBlend;
00884 canDoStencil = (stencilBits >= 3);
00885 if( !canDoStencil )
00886 if( canDoAlpha )
00887 SG_LOG(SG_ALL, SG_WARN, "SGShadowVolume:no stencil buffer, using alpha buffer");
00888 else
00889 SG_LOG(SG_ALL, SG_WARN, "SGShadowVolume:no stencil buffer and no alpha buffer");
00890 }
00891
00892 void SGShadowVolume::startOfFrame(void) {
00893 }
00894 void SGShadowVolume::deleteOccluderFromTile(ssgBranch *tile) {
00895 SceneryObject_map::iterator iSceneryObject;
00896 for(iSceneryObject = sceneryObjects.begin() ; iSceneryObject != sceneryObjects.end(); ) {
00897 SceneryObject_map::iterator iCurrent = iSceneryObject ++;
00898 if( iCurrent->second->tile == tile ) {
00899 delete iCurrent->second;
00900 sceneryObjects.erase( iCurrent );
00901 }
00902 }
00903 }
00904
00905 void SGShadowVolume::deleteOccluder(ssgBranch *occluder) {
00906
00907 while( occluder && !occluder->isA(ssgTypeTransform()))
00908 occluder = (ssgBranch *) occluder->getKid(0);
00909
00910
00911 SceneryObject_map::iterator iSceneryObject = sceneryObjects.find( occluder );
00912 if( iSceneryObject != sceneryObjects.end() ) {
00913 delete iSceneryObject->second;
00914 sceneryObjects.erase( occluder );
00915 }
00916 }
00917
00918 void SGShadowVolume::addOccluder(ssgBranch *occluder, OccluderType occluder_type, ssgBranch *tile) {
00919
00920 while( occluder && !occluder->isA(ssgTypeTransform()))
00921 occluder = (ssgBranch *) occluder->getKid(0);
00922
00923
00924 SceneryObject_map::iterator iSceneryObject = sceneryObjects.find( occluder );
00925 if( iSceneryObject == sceneryObjects.end() ) {
00926
00927 SceneryObject *entry = new SceneryObject( occluder, occluder_type );
00928 entry->tile = tile;
00929 sceneryObjects[ occluder ] = entry;
00930 }
00931
00932 }
00933
00934 void SGShadowVolume::setupShadows( double lon, double lat,
00935 double gst, double SunRightAscension, double SunDeclination, double sunAngle) {
00936
00937 shadowsAC_enabled = sim_rendering->getBoolValue("shadows-ac", false);
00938 shadowsAC_transp_enabled = sim_rendering->getBoolValue("shadows-ac-transp", false);
00939 shadowsAI_enabled = sim_rendering->getBoolValue("shadows-ai", false);
00940 shadowsTO_enabled = sim_rendering->getBoolValue("shadows-to", false);
00941 shadowsDebug_enabled = sim_rendering->getBoolValue("shadows-debug", false);
00942 shadows_enabled = shadowsAC_enabled || shadowsAI_enabled || shadowsTO_enabled;
00943 shadows_enabled &= canDoAlpha || canDoStencil;
00944 use_alpha = ((!canDoStencil) || sim_rendering->getBoolValue("shadows-alpha", false)) &&
00945 canDoAlpha;
00946
00947 if( ! shadows_enabled )
00948 return;
00949
00950 shadows_rendered = false;
00951 sun_angle = sunAngle;
00952 {
00953 sgMat4 GST, RA, DEC;
00954 sgVec3 axis;
00955
00956
00957 sgSetVec3( axis, 0.0, 0.0, -1.0 );
00958 sgMakeRotMat4( GST, (gst) * 15.0, axis );
00959
00960 sgSetVec3( axis, 0.0, 0.0, 1.0 );
00961 sgMakeRotMat4( RA, (SunRightAscension * SGD_RADIANS_TO_DEGREES) - 90.0, axis );
00962
00963 sgSetVec3( axis, 1.0, 0.0, 0.0 );
00964 sgMakeRotMat4( DEC, SunDeclination * SGD_RADIANS_TO_DEGREES, axis );
00965
00966 sgMat4 TRANSFORM;
00967 sgMakeIdentMat4( TRANSFORM );
00968 sgPreMultMat4( TRANSFORM, GST );
00969 sgPreMultMat4( TRANSFORM, RA );
00970 sgPreMultMat4( TRANSFORM, DEC );
00971 sgSetVec3( sunPos, 0.0, 9900000.0, 0.0);
00972 sgXformPnt3( sunPos, TRANSFORM );
00973 }
00974
00975 ssgGetModelviewMatrix( CameraViewM );
00976
00977 }
00978
00979 void SGShadowVolume::endOfFrame(void) {
00980 if( ! shadows_enabled )
00981 return;
00982 if( shadows_rendered )
00983 return;
00984 glBindTexture(GL_TEXTURE_2D, 0);
00985 glBindTexture(GL_TEXTURE_1D, 0);
00986
00987 glMatrixMode(GL_MODELVIEW);
00988 computeShadows();
00989 frameNumber ++;
00990 shadows_rendered = true;
00991 }
00992
00993 int SGShadowVolume::ACpostTravCB( ssgEntity *entity, int traversal_mask ) {
00994 if( states->shadowsAC_transp_enabled && (SSGTRAV_CULL & traversal_mask) )
00995 states->endOfFrame();
00996 return 0;
00997 }
00998