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 <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
00041
00042
00043
00044
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
00116
00117 if( colorBits < 8 )
00118 rt->Reset("rgba=5,5,5,1 ctt");
00119 else
00120 rt->Reset("rgba ctt");
00121
00122
00123
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
00168 switch(textureDimension) {
00169 case 0:
00170
00171 textureDimension = 256;
00172 break;
00173 case 64:
00174 case 128:
00175 case 256:
00176 break;
00177 case 512:
00178
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
00199 textureDimension = 256;
00200 } else if( sizeKb >= 2*1024 ) {
00201
00202 textureDimension = 128;
00203 } else {
00204
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
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
00269
00270 glMatrixMode(GL_PROJECTION);
00271 glLoadIdentity();
00272
00273 float near_ = dist_center - radius;
00274 float far_ = dist_center + radius;
00275 if( near_ <= 0 ) {
00276
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
00293
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
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
00316 if( bbList[bbId].frameUsed == 0)
00317 return false;
00318
00319
00320 if( builtBBframe >= maxImpostorRegenFrame )
00321 return true;
00322
00323 if( bbList[bbId].needRedraw )
00324 return false;
00325
00326
00327
00328
00329
00330
00331
00332 bbList[bbId].frameUsed = frameNumber;
00333 return true;
00334 }
00335
00336
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
00349 int minFrameNumber = frameNumber - 100;
00350 frameNumber++;
00351
00352 for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00353 if( (bbList[bbId].cldID != 0) && (bbList[bbId].frameUsed < minFrameNumber) ) {
00354
00355 bbList[bbId].cldID = 0;
00356 }
00357 }
00358
00359
00360 void SGBbCache::invalidateCache(void) {
00361
00362 for( int bbId = 0 ; bbId < bbListCount ; bbId++)
00363
00364 bbList[bbId].needRedraw = true;
00365 }
00366
00367
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