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 <simgear/compiler.h>
00028 #include <simgear/debug/logstream.hxx>
00029 
00030 #include <plib/sg.h>
00031 #include <simgear/screen/extensions.hxx>
00032 #include <simgear/screen/RenderTexture.h>
00033 #include <osg/GLU>
00034 
00035 #include "bbcache.hxx"
00036 
00037 
00038 
00039 
00040 
00041 
00042 
00043 
00044 
00045 
00046 void SGBbCache::freeTextureMemory(void) {
00047 
00048         if( bbListCount ) {
00049                 for(int i = 0 ; i < bbListCount ; i++) {
00050                         bbList[i].cldID = 0;
00051                         if(bbList[i].texID)
00052                                 glDeleteTextures(1, & bbList[i].texID);
00053                 }
00054                 delete [] bbList;
00055         }
00056         bbListCount = 0;
00057         cacheSizeKb = 0;
00058         textureWH   = 0;
00059 }
00060 
00061 bool SGBbCache::allocTextureMemory(int cacheCount, int textureDimension) {
00062         textureWH = textureDimension;
00063         bbListCount = cacheCount;
00064         bbList = new bbInfo[bbListCount];
00065         for(int i = 0 ; i < bbListCount ; i++) {
00066                 bbList[i].cldID = 0;
00067                 bbList[i].texID = 0;
00068         glGenTextures(1, &bbList[i].texID);
00069         glBindTexture(GL_TEXTURE_2D, bbList[i].texID);
00070         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 
00071                          textureDimension, textureDimension, 0, GL_RGB, GL_FLOAT, NULL);
00072 
00073         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00074         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00075         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00076         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00077         }
00078     glBindTexture(GL_TEXTURE_2D, 0);
00079         cacheSizeKb = (textureDimension * textureDimension * 4);
00080         cacheSizeKb *= cacheCount;
00081         cacheSizeKb /= 1024;
00082         if(rtAvailable) {
00083                 if( rt->BeginCapture() ) {
00084                         glViewport(0, 0, textureDimension, textureDimension);
00085                         rt->EndCapture();
00086                 }
00087         }
00088         return true;
00089 }
00090 
00091 SGBbCache::SGBbCache(void) :
00092         bbListCount(0),
00093         textureWH(0),
00094         cacheSizeKb(0),
00095         builtBBCount(0),
00096         frameNumber(0),
00097         rt(0),
00098         rtAvailable(false),
00099         maxImpostorRegenFrame(20)
00100 {
00101 }
00102 
00103 SGBbCache::~SGBbCache(void) {
00104         delete rt;
00105         freeTextureMemory();
00106 }
00107 
00108 
00109 void SGBbCache::init(int cacheCount) {
00110         GLint colorBits = 0;
00111         glGetIntegerv( GL_BLUE_BITS, &colorBits );
00112 
00113         rt = new RenderTexture();
00114         
00115         
00116         if( colorBits < 8 )
00117                 rt->Reset("rgba=5,5,5,1 ctt");
00118         else
00119                 rt->Reset("rgba ctt");
00120 
00121 
00122 
00123         if( rt->Initialize(256, 256, true) ) {
00124                 SG_LOG(SG_ALL, SG_INFO, "bbcache:Initialize sucessfull");
00125                 if (rt->BeginCapture())
00126                 {
00127                         SG_LOG(SG_ALL, SG_INFO, "bbcache:BeginCapture sucessfull, RTT available");
00128                         rtAvailable = true;
00129                         glViewport(0, 0, 256, 256);
00130                         glMatrixMode(GL_PROJECTION);
00131                         glLoadIdentity();
00132                         gluPerspective(60.0,  1, 1, 5.0);
00133                         glMatrixMode(GL_MODELVIEW);
00134                         glLoadIdentity();
00135                         glDisable(GL_LIGHTING);
00136                         glEnable(GL_COLOR_MATERIAL);
00137                         glDisable(GL_CULL_FACE);
00138                         glDisable(GL_FOG);
00139                         glDisable(GL_DEPTH_TEST);
00140                         glClearColor(0.0, 0.0, 0.0, 0.0);
00141                         glEnable(GL_TEXTURE_2D);
00142                         glEnable(GL_ALPHA_TEST);
00143                         glAlphaFunc(GL_GREATER, 0.0f);
00144                         glEnable(GL_SMOOTH);
00145                         glEnable(GL_BLEND);
00146                         glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
00147 
00148                         rt->EndCapture();
00149                 } else
00150                         SG_LOG(SG_ALL, SG_WARN, "bbcache:BeginCapture failed, RTT not available for 3D clouds");
00151         } else
00152                 SG_LOG(SG_ALL, SG_WARN, "bbcache:Initialize failed, RTT not available for 3D clouds");
00153         if( cacheCount )
00154                 allocTextureMemory( cacheCount, 64 );
00155 
00156 }
00157 
00158 
00159 bool SGBbCache::setCacheSize(int count, int textureDimension) {
00160         if( count < 0 || count > 500)
00161                 return false;
00162         freeTextureMemory();
00163         if( count == 0)
00164                 return true;
00165 
00166         
00167         switch(textureDimension) {
00168                 case 0:
00169                         
00170                         textureDimension = 256;
00171                         break;
00172                 case 64:
00173                 case 128:
00174                 case 256:
00175                         break;
00176                 case 512:
00177                         
00178                         textureDimension = 256;
00179                         break;
00180                 default:
00181                         textureDimension = 128;
00182                         break;
00183         }
00184         return allocTextureMemory( count, textureDimension);
00185 }
00186 
00187 
00188 bool SGBbCache::setCacheSize(int sizeKb) {
00189         if( sizeKb < 0 || sizeKb > 256*1024)
00190                 return false;
00191         freeTextureMemory();
00192         if( sizeKb == 0)
00193                 return true;
00194         int count = 1;
00195         int textureDimension = 256;
00196         if( sizeKb >= 8*1024 ) {
00197                 
00198                 textureDimension = 256;
00199         } else  if( sizeKb >= 2*1024 ) {
00200                 
00201                 textureDimension = 128;
00202         } else  {
00203                 
00204                 textureDimension = 64;
00205         }
00206         count = (sizeKb * 1024) / (textureDimension * textureDimension * 4);
00207         if(count == 0)
00208                 count = 1;
00209         return allocTextureMemory( count, textureDimension);
00210 }
00211 
00212 int SGBbCache::queryCacheSize(void) {
00213         return cacheSizeKb;
00214 }
00215 
00216 void SGBbCache::free(int bbId, int cldId) {
00217         if( bbId < 0 || bbId >= bbListCount )
00218                 return;
00219         if( bbList[bbId].cldID != cldId )
00220                 return;
00221         bbList[bbId].cldID = 0;
00222 }
00223 
00224 int SGBbCache::alloc(int cldId) {
00225         
00226         if( ! rtAvailable )
00227                 return -1;
00228         for(int i = 0 ; i < bbListCount ; i++) {
00229                 if( (bbList[i].cldID == 0) && (bbList[i].texID != 0) ) {
00230             bbList[i].cldID = cldId;
00231                         bbList[i].angleX = -999;
00232                         bbList[i].angleY = -999;
00233                         bbList[i].frameUsed = 0;
00234                         bbList[i].needRedraw = true;
00235                         return i;
00236                 }
00237         }
00238         return -1;
00239 }
00240 
00241 GLuint SGBbCache::QueryTexID(int cldId, int bbId) {
00242         if( bbId < 0 || bbId >= bbListCount )
00243                 return 0;
00244         if( bbList[bbId].cldID != cldId )
00245                 return 0;
00246         return bbList[bbId].texID;
00247 }
00248 
00249 int SGBbCache::queryImpostorAge(int bbId) {
00250         if( bbId < 0 || bbId >= bbListCount )
00251                 return 0;
00252         return frameNumber - bbList[bbId].frame;
00253 }
00254 
00255 void SGBbCache::beginCapture(void) {
00256 
00257         rt->BeginCapture();
00258 
00259         glClear(GL_COLOR_BUFFER_BIT);
00260 
00261 }
00262 
00263 
00264 
00265 void SGBbCache::setRadius(float radius, float dist_center) {
00266         float border;
00267         
00268         
00269         glMatrixMode(GL_PROJECTION);
00270     glLoadIdentity();
00271 
00272     float near_ = dist_center - radius;
00273     float far_ = dist_center + radius;
00274         if( near_ <= 0 ) {
00275         
00276         glFrustum(-1, 1, -1, 1, 1, 1 + radius * 2);
00277         } else {
00278         border = (near_ * radius) / sqrt(dist_center * dist_center - radius * radius);
00279         glFrustum(-border, border, -border, border, near_, far_);
00280         }
00281     glMatrixMode(GL_MODELVIEW);
00282     glLoadIdentity();
00283 }
00284 void SGBbCache::setTextureData(int bbId) {
00285         if( bbId < 0 || bbId >= bbListCount )
00286                 return;
00287 
00288     glBindTexture(GL_TEXTURE_2D, bbList[bbId].texID);
00289         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureWH, textureWH);
00290  
00291 
00292 
00293     bbList[bbId].frame = frameNumber;
00294         bbList[bbId].frameUsed = frameNumber;
00295         bbList[bbId].needRedraw = false;
00296     builtBBCount ++;
00297         builtBBframe ++;
00298 }
00299 
00300 void SGBbCache::endCapture(void) {
00301 
00302         rt->EndCapture();
00303 
00304 
00305 }
00306 
00307 
00308 bool SGBbCache::isBbValid( int cldId, int bbId, float angleY, float angleX) {
00309         if( bbId < 0 || bbId >= bbListCount )
00310                 return false;
00311         if( bbList[bbId].cldID != cldId )
00312                 return false;
00313 
00314         
00315         if( bbList[bbId].frameUsed == 0)
00316                 return false;
00317 
00318         
00319         if( builtBBframe >= maxImpostorRegenFrame )
00320                 return true;
00321 
00322         if( bbList[bbId].needRedraw )
00323                 return false;
00324 
00325 
00326 
00327 
00328 
00329 
00330 
00331         bbList[bbId].frameUsed = frameNumber;
00332         return true;
00333 }
00334 
00335 
00336 void SGBbCache::setReference( int cldId, int bbId, float angleY, float angleX) {
00337         if( bbId < 0 || bbId >= bbListCount )
00338                 return;
00339         if( bbList[bbId].cldID != cldId )
00340                 return;
00341         bbList[bbId].angleX = angleX;
00342         bbList[bbId].angleY = angleY;
00343 }
00344 
00345 void SGBbCache::startNewFrame(void) {
00346         builtBBframe = 0;
00347         
00348         int minFrameNumber = frameNumber - 100;
00349         frameNumber++;
00350         
00351         for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00352                 if( (bbList[bbId].cldID != 0) && (bbList[bbId].frameUsed < minFrameNumber) ) {
00353                         
00354                         bbList[bbId].cldID = 0;
00355                 }
00356 }
00357 
00358 
00359 void SGBbCache::invalidateCache(void) {
00360 
00361         for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00362 
00363                 bbList[bbId].needRedraw = true;
00364 }
00365 
00366 
00367 void SGBbCache::invalidate(int cldId, int bbId) {
00368         if( bbId < 0 || bbId >= bbListCount )
00369                 return;
00370         if( bbList[bbId].cldID != cldId )
00371                 return;
00372         bbList[bbId].needRedraw = true;
00373 }
00374