bbcache.cxx

00001 // Billboard helper class
00002 //
00003 // Written by Harald JOHNSEN, started April 2005.
00004 //
00005 // Copyright (C) 2005  Harald JOHNSEN - hjohnsen@evc.net
00006 //
00007 // This program is free software; you can redistribute it and/or
00008 // modify it under the terms of the GNU General Public License as
00009 // published by the Free Software Foundation; either version 2 of the
00010 // License, or (at your option) any later version.
00011 //
00012 // This program is distributed in the hope that it will be useful, but
00013 // WITHOUT ANY WARRANTY; without even the implied warranty of
00014 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015 // General Public License for more details.
00016 //
00017 // You should have received a copy of the GNU General Public License
00018 // along with this program; if not, write to the Free Software
00019 // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
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 <plib/ssg.h>
00032 #include <simgear/screen/extensions.hxx>
00033 #include <simgear/screen/RenderTexture.h>
00034 #include SG_GLU_H
00035 
00036 #include "bbcache.hxx"
00037 
00038 
00039 /*
00040 memory usage :
00041 size          1 tex       8 tex       32 tex      64 tex
00042 64x64x4        16k        128k        512k         1Mo
00043 128x128x4      64k        512k        2Mo          4Mo
00044 256x256x4     256k        2Mo         8Mo         16Mo
00045 */
00046 
00047 void SGBbCache::freeTextureMemory(void) {
00048 
00049         if( bbListCount ) {
00050                 for(int i = 0 ; i < bbListCount ; i++) {
00051                         bbList[i].cldID = 0;
00052                         if(bbList[i].texID)
00053                                 glDeleteTextures(1, & bbList[i].texID);
00054                 }
00055                 delete [] bbList;
00056         }
00057         bbListCount = 0;
00058         cacheSizeKb = 0;
00059         textureWH   = 0;
00060 }
00061 
00062 bool SGBbCache::allocTextureMemory(int cacheCount, int textureDimension) {
00063         textureWH = textureDimension;
00064         bbListCount = cacheCount;
00065         bbList = new bbInfo[bbListCount];
00066         for(int i = 0 ; i < bbListCount ; i++) {
00067                 bbList[i].cldID = 0;
00068                 bbList[i].texID = 0;
00069         glGenTextures(1, &bbList[i].texID);
00070         glBindTexture(GL_TEXTURE_2D, bbList[i].texID);
00071         glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, 
00072                          textureDimension, textureDimension, 0, GL_RGB, GL_FLOAT, NULL);
00073 
00074         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00075         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00076         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00077         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00078         }
00079     glBindTexture(GL_TEXTURE_2D, 0);
00080         cacheSizeKb = (textureDimension * textureDimension * 4);
00081         cacheSizeKb *= cacheCount;
00082         cacheSizeKb /= 1024;
00083         if(rtAvailable) {
00084                 if( rt->BeginCapture() ) {
00085                         glViewport(0, 0, textureDimension, textureDimension);
00086                         rt->EndCapture();
00087                 }
00088         }
00089         return true;
00090 }
00091 
00092 SGBbCache::SGBbCache(void) :
00093         bbListCount(0),
00094         textureWH(0),
00095         cacheSizeKb(0),
00096         builtBBCount(0),
00097         frameNumber(0),
00098         rt(0),
00099         rtAvailable(false),
00100         maxImpostorRegenFrame(20)
00101 {
00102 }
00103 
00104 SGBbCache::~SGBbCache(void) {
00105         delete rt;
00106         freeTextureMemory();
00107 }
00108 
00109 
00110 void SGBbCache::init(int cacheCount) {
00111         GLint colorBits = 0;
00112         glGetIntegerv( GL_BLUE_BITS, &colorBits );
00113 
00114         rt = new RenderTexture();
00115         // don't use default rtt on nvidia/win because of poor performance of glCopyTexSubImage2D
00116         // wihtout default pattrib params - see opengl forum
00117         if( colorBits < 8 )
00118                 rt->Reset("rgba=5,5,5,1 ctt");
00119         else
00120                 rt->Reset("rgba ctt");
00121 
00122 //      rt->Reset("rgba tex2D ctt");
00123 //      rt->Reset("rgba tex2D");
00124         if( rt->Initialize(256, 256, true) ) {
00125                 SG_LOG(SG_ALL, SG_INFO, "bbcache:Initialize sucessfull");
00126                 if (rt->BeginCapture())
00127                 {
00128                         SG_LOG(SG_ALL, SG_INFO, "bbcache:BeginCapture sucessfull, RTT available");
00129                         rtAvailable = true;
00130                         glViewport(0, 0, 256, 256);
00131                         glMatrixMode(GL_PROJECTION);
00132                         glLoadIdentity();
00133                         gluPerspective(60.0,  1, 1, 5.0);
00134                         glMatrixMode(GL_MODELVIEW);
00135                         glLoadIdentity();
00136                         glDisable(GL_LIGHTING);
00137                         glEnable(GL_COLOR_MATERIAL);
00138                         glDisable(GL_CULL_FACE);
00139                         glDisable(GL_FOG);
00140                         glDisable(GL_DEPTH_TEST);
00141                         glClearColor(0.0, 0.0, 0.0, 0.0);
00142                         glEnable(GL_TEXTURE_2D);
00143                         glEnable(GL_ALPHA_TEST);
00144                         glAlphaFunc(GL_GREATER, 0.0f);
00145                         glEnable(GL_SMOOTH);
00146                         glEnable(GL_BLEND);
00147                         glBlendFunc( GL_ONE, GL_ONE_MINUS_SRC_ALPHA );
00148 
00149                         rt->EndCapture();
00150                 } else
00151                         SG_LOG(SG_ALL, SG_WARN, "bbcache:BeginCapture failed, RTT not available for 3D clouds");
00152         } else
00153                 SG_LOG(SG_ALL, SG_WARN, "bbcache:Initialize failed, RTT not available for 3D clouds");
00154         if( cacheCount )
00155                 allocTextureMemory( cacheCount, 64 );
00156 
00157 }
00158 
00159 
00160 bool SGBbCache::setCacheSize(int count, int textureDimension) {
00161         if( count < 0 || count > 500)
00162                 return false;
00163         freeTextureMemory();
00164         if( count == 0)
00165                 return true;
00166 
00167         // only allow some reasonable dimensions
00168         switch(textureDimension) {
00169                 case 0:
00170                         // default size
00171                         textureDimension = 256;
00172                         break;
00173                 case 64:
00174                 case 128:
00175                 case 256:
00176                         break;
00177                 case 512:
00178                         // rt is 256 so higher texture size has no meaning
00179                         textureDimension = 256;
00180                         break;
00181                 default:
00182                         textureDimension = 128;
00183                         break;
00184         }
00185         return allocTextureMemory( count, textureDimension);
00186 }
00187 
00188 
00189 bool SGBbCache::setCacheSize(int sizeKb) {
00190         if( sizeKb < 0 || sizeKb > 256*1024)
00191                 return false;
00192         freeTextureMemory();
00193         if( sizeKb == 0)
00194                 return true;
00195         int count = 1;
00196         int textureDimension = 256;
00197         if( sizeKb >= 8*1024 ) {
00198                 // more than 32 256x256 textures
00199                 textureDimension = 256;
00200         } else  if( sizeKb >= 2*1024 ) {
00201                 // more than 32 128x128 textures
00202                 textureDimension = 128;
00203         } else  {
00204                 // don't go under 64x64 textures
00205                 textureDimension = 64;
00206         }
00207         count = (sizeKb * 1024) / (textureDimension * textureDimension * 4);
00208         if(count == 0)
00209                 count = 1;
00210         return allocTextureMemory( count, textureDimension);
00211 }
00212 
00213 int SGBbCache::queryCacheSize(void) {
00214         return cacheSizeKb;
00215 }
00216 
00217 void SGBbCache::free(int bbId, int cldId) {
00218         if( bbId < 0 || bbId >= bbListCount )
00219                 return;
00220         if( bbList[bbId].cldID != cldId )
00221                 return;
00222         bbList[bbId].cldID = 0;
00223 }
00224 
00225 int SGBbCache::alloc(int cldId) {
00226         // pretend we have no more texture if render to texture is not available
00227         if( ! rtAvailable )
00228                 return -1;
00229         for(int i = 0 ; i < bbListCount ; i++) {
00230                 if( (bbList[i].cldID == 0) && (bbList[i].texID != 0) ) {
00231             bbList[i].cldID = cldId;
00232                         bbList[i].angleX = -999;
00233                         bbList[i].angleY = -999;
00234                         bbList[i].frameUsed = 0;
00235                         bbList[i].needRedraw = true;
00236                         return i;
00237                 }
00238         }
00239         return -1;
00240 }
00241 
00242 GLuint SGBbCache::QueryTexID(int cldId, int bbId) {
00243         if( bbId < 0 || bbId >= bbListCount )
00244                 return 0;
00245         if( bbList[bbId].cldID != cldId )
00246                 return 0;
00247         return bbList[bbId].texID;
00248 }
00249 
00250 int SGBbCache::queryImpostorAge(int bbId) {
00251         if( bbId < 0 || bbId >= bbListCount )
00252                 return 0;
00253         return frameNumber - bbList[bbId].frame;
00254 }
00255 
00256 void SGBbCache::beginCapture(void) {
00257 
00258         rt->BeginCapture();
00259 
00260         glClear(GL_COLOR_BUFFER_BIT);
00261 
00262 }
00263 
00264 
00265 
00266 void SGBbCache::setRadius(float radius, float dist_center) {
00267         float border;
00268         //set viewport to texture resolution
00269         //glViewport(0, 0, 256, 256);
00270         glMatrixMode(GL_PROJECTION);
00271     glLoadIdentity();
00272 
00273     float near_ = dist_center - radius;
00274     float far_ = dist_center + radius;
00275         if( near_ <= 0 ) {
00276         // we are in trouble
00277         glFrustum(-1, 1, -1, 1, 1, 1 + radius * 2);
00278         } else {
00279         border = (near_ * radius) / sqrt(dist_center * dist_center - radius * radius);
00280         glFrustum(-border, border, -border, border, near_, far_);
00281         }
00282     glMatrixMode(GL_MODELVIEW);
00283     glLoadIdentity();
00284 }
00285 void SGBbCache::setTextureData(int bbId) {
00286         if( bbId < 0 || bbId >= bbListCount )
00287                 return;
00288 
00289     glBindTexture(GL_TEXTURE_2D, bbList[bbId].texID);
00290         glCopyTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 0, 0, textureWH, textureWH);
00291  
00292 //    bbList[bbId].angleX = angleX;
00293 //    bbList[bbId].angleY = angleY;
00294     bbList[bbId].frame = frameNumber;
00295         bbList[bbId].frameUsed = frameNumber;
00296         bbList[bbId].needRedraw = false;
00297     builtBBCount ++;
00298         builtBBframe ++;
00299 }
00300 
00301 void SGBbCache::endCapture(void) {
00302 
00303         rt->EndCapture();
00304 //    glBindTexture(GL_TEXTURE_2D, rt->GetTextureID() );
00305 
00306 }
00307 
00308 
00309 bool SGBbCache::isBbValid( int cldId, int bbId, float angleY, float angleX) {
00310         if( bbId < 0 || bbId >= bbListCount )
00311                 return false;
00312         if( bbList[bbId].cldID != cldId )
00313                 return false;
00314 
00315         // it was just allocated
00316         if( bbList[bbId].frameUsed == 0)
00317                 return false;
00318 
00319         // we reuse old impostor to speed up things
00320         if( builtBBframe >= maxImpostorRegenFrame )
00321                 return true;
00322 
00323         if( bbList[bbId].needRedraw )
00324                 return false;
00325 
00326 //    if( fabs(angleY - bbList[bbId].angleY) >= 4.0 )
00327 //        return false;
00328 
00329 //    if( fabs(angleX - bbList[bbId].angleX) >= 4.0 )
00330 //        return false;
00331 
00332         bbList[bbId].frameUsed = frameNumber;
00333         return true;
00334 }
00335 
00336 // TODO:this is not the right way to handle that
00337 void SGBbCache::setReference( int cldId, int bbId, float angleY, float angleX) {
00338         if( bbId < 0 || bbId >= bbListCount )
00339                 return;
00340         if( bbList[bbId].cldID != cldId )
00341                 return;
00342         bbList[bbId].angleX = angleX;
00343         bbList[bbId].angleY = angleY;
00344 }
00345 
00346 void SGBbCache::startNewFrame(void) {
00347         builtBBframe = 0;
00348         // TOTO:find reasonable value
00349         int minFrameNumber = frameNumber - 100;
00350         frameNumber++;
00351         // cleanup of unused enties
00352         for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00353                 if( (bbList[bbId].cldID != 0) && (bbList[bbId].frameUsed < minFrameNumber) ) {
00354                         // entry is now free
00355                         bbList[bbId].cldID = 0;
00356                 }
00357 }
00358 
00359 // force all impostors to be rebuilt, this will enventually be done over several frames
00360 void SGBbCache::invalidateCache(void) {
00361 
00362         for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00363 //              bbList[bbId].cldID = 0;
00364                 bbList[bbId].needRedraw = true;
00365 }
00366 
00367 // flag the impostor for a lazy update
00368 void SGBbCache::invalidate(int cldId, int bbId) {
00369         if( bbId < 0 || bbId >= bbListCount )
00370                 return;
00371         if( bbList[bbId].cldID != cldId )
00372                 return;
00373         bbList[bbId].needRedraw = true;
00374 }
00375 

Generated on Mon Dec 17 09:30:54 2007 for SimGear by  doxygen 1.5.1