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