00001 #include <OSGConfig.h>
00002
00003 #include "OSGTextureManager.h"
00004
00005 #include <OSGTextureChunk.h>
00006 #include <OSGDrawActionBase.h>
00007 #include <OSGMatrix.h>
00008 #include <OSGVector.h>
00009 #include <OSGQuaternion.h>
00010 #include <OSGLog.h>
00011
00012 #include "OSGDVRVolumeTexture.h"
00013 #include "OSGDVRVolume.h"
00014 #include "OSGSlicer.h"
00015 #include "OSGBrick.h"
00016
00017
00018 #define FACE_FRONT (1)
00019 #define FACE_BACK (2)
00020 #define FACE_RIGHT (4)
00021 #define FACE_LEFT (8)
00022 #define FACE_BOTTOM (16)
00023 #define FACE_TOP (32)
00024
00025
00026 OSG_BEGIN_NAMESPACE
00027
00029
00030 TextureRecord::TextureRecord(ImagePtr img,
00031 UInt32 internal,
00032 UInt32 externalFormat,
00033 Int32 stage0,
00034 Int32 stage1) :
00035 _internalFormat(internal ),
00036 _externalFormat(externalFormat),
00037 _textureStage0 (stage0 ),
00038 _textureStage1 (stage1 )
00039 {
00040 _image = img;
00041 addRefCP(_image);
00042 }
00043
00044 TextureRecord::~TextureRecord()
00045 {
00046 subRefCP(_image);
00047 _image = NullFC;
00048 }
00049
00050
00052
00053
00054 TextureManager::TextureManager(DVRVolume *volume) :
00055 _registeredTextures( ),
00056 _parent (NULL),
00057 _brickSets (NULL)
00058 {
00059 _parent = volume;
00060 _brickSets = new BrickSet[3];
00061 }
00062
00063 TextureManager::~TextureManager()
00064 {
00065 clearTextures();
00066
00067 delete [] _brickSets;
00068 }
00069
00071 Int32 TextureManager::registerTexture(ImagePtr image,
00072 UInt32 internalFormat,
00073 UInt32 externalFormat,
00074 bool ,
00075 Int32 textureStage0,
00076 Int32 textureStage1)
00077 {
00078 FDEBUG(("TextureManager::registerTexture stage0: %d - stage1: %d\n",
00079 textureStage0, textureStage1));
00080
00085
00086
00087 bool unique = true;
00088
00089 for(UInt32 i = 0; i < _registeredTextures.size(); i++)
00090 {
00091 if(textureStage0 == _registeredTextures[i]->_textureStage0 ||
00092 textureStage0 == _registeredTextures[i]->_textureStage1 )
00093 {
00094 unique = false;
00095 }
00096
00097 if((textureStage1 != -1 ) &&
00098 (textureStage1 == _registeredTextures[i]->_textureStage0 ||
00099 textureStage1 == _registeredTextures[i]->_textureStage1 ) )
00100 {
00101 unique = false;
00102 }
00103 }
00104
00105 if(unique == false)
00106 {
00107 SWARNING << "TextureManager::registerTexture - "
00108 << "ID already in use -> ignoring texture"
00109 << std::endl;
00110 return -1;
00111 }
00112
00113
00114 TextureRecord * record = new TextureRecord(image,
00115 internalFormat,
00116 externalFormat,
00117 textureStage0,
00118 textureStage1);
00119 _registeredTextures.push_back(record);
00120
00121 return _registeredTextures.size() - 1;
00122 }
00123
00124
00126 void TextureManager::unregisterTexture(Int32 id)
00127 {
00128 FDEBUG(("TextureManager::unregisterTexture\n"));
00129
00130 if((id < 0) || (UInt32(id) > _registeredTextures.size()))
00131 {
00132 SWARNING << "TextureManager::unregisterTexture - invalid id "
00133 << id
00134 << std::endl;
00135 return;
00136 }
00137
00138 TextureSet::iterator iter = _registeredTextures.begin();
00139
00140 delete _registeredTextures[id];
00141
00142 _registeredTextures.erase(iter + id);
00143 }
00144
00145
00147 void TextureManager::reloadTexture(Int32 id, DrawActionBase *action)
00148 {
00149 if((id < 0) || (UInt32(id) > _registeredTextures.size()))
00150 {
00151 SWARNING << "TextureManager::reloadTexture - invalid id "
00152 << id
00153 << std::endl;
00154 return;
00155 }
00156
00157 for(UInt32 k = 0; k < 3; k++)
00158 {
00159 _brickSets[k].reloadBrickTextures(
00160 action,
00161 _registeredTextures[id]->_textureStage0);
00162
00163 _brickSets[k].reloadBrickTextures(
00164 action,
00165 _registeredTextures[id]->_textureStage1);
00166 }
00167 }
00168
00169
00171 void TextureManager::clearTextures(ChunkMaterialPtr material)
00172 {
00173 FDEBUG(("TextureManager::clearTexture\n"));
00174
00176
00177 if (material != NullFC)
00178 {
00179 for(UInt32 k = 0; k < 3; k++)
00180 {
00181 _brickSets[k].clearBrickTextures(material);
00182
00183 delete [] _brickSets[k].m_pBricks;
00184
00185 _brickSets[k].m_pBricks = 0;
00186 _brickSets[k].m_nNumBricks = 0;
00187 }
00188 }
00189
00190 for(UInt32 i = 0; i < _registeredTextures.size(); i++)
00191 {
00192 delete _registeredTextures[i];
00193 }
00194
00195 _registeredTextures.clear();
00196 }
00197
00198
00200 void TextureManager::buildTextures(ChunkMaterialPtr material,
00201 DVRVolume *volume,
00202 TextureMode textureMode)
00203 {
00204 FDEBUG(("TextureManager::buildTextures\n"));
00205
00206 DVRVolumeTexturePtr vT = DVRVOLUME_PARAMETER(volume, DVRVolumeTexture);
00207
00208 if(vT == NullFC)
00209 {
00210 SWARNING << "TextureManager::buildTextures - No Volume" << std::endl;
00211 return;
00212 }
00213
00214 if(_registeredTextures.size() < 1)
00215 {
00216 SWARNING << "TextureManager::buildTextures - No registerd textures"
00217 << std::endl;
00218 return;
00219 }
00220
00221 switch(textureMode)
00222 {
00223 case TM_2D_Multi:
00224 {
00225
00226 Vec3f res = vT->getResolution();
00227
00228 Vec3f brickSizeX(2, res[1], res[2]);
00229 Vec3f brickSizeY(res[0], 2, res[2]);
00230 Vec3f brickSizeZ(res[0], res[1], 2 );
00231
00232 _brickSets[BrickSet::XY].buildBricks3D(volume,
00233 brickSizeZ,
00234 1,
00235 BrickSet::XY);
00236 _brickSets[BrickSet::XZ].buildBricks3D(volume,
00237 brickSizeY,
00238 1,
00239 BrickSet::XZ);
00240 _brickSets[BrickSet::YZ].buildBricks3D(volume,
00241 brickSizeX,
00242 1,
00243 BrickSet::YZ);
00244
00245 _brickSets[BrickSet::XY].buildBrickTextures( material,
00246 _registeredTextures,
00247 textureMode);
00248 _brickSets[BrickSet::XZ].buildBrickTextures( material,
00249 _registeredTextures,
00250 textureMode);
00251 _brickSets[BrickSet::YZ].buildBrickTextures( material,
00252 _registeredTextures,
00253 textureMode);
00254
00255 break;
00256 }
00257 case TM_2D:
00258 {
00259
00260 _brickSets[BrickSet::XY].buildBricks2D(volume, BrickSet::XY);
00261 _brickSets[BrickSet::XZ].buildBricks2D(volume, BrickSet::XZ);
00262 _brickSets[BrickSet::YZ].buildBricks2D(volume, BrickSet::YZ);
00263
00264 _brickSets[BrickSet::XY].buildBrickTextures( material,
00265 _registeredTextures,
00266 textureMode);
00267 _brickSets[BrickSet::XZ].buildBrickTextures( material,
00268 _registeredTextures,
00269 textureMode);
00270 _brickSets[BrickSet::YZ].buildBrickTextures( material,
00271 _registeredTextures,
00272 textureMode);
00273
00274 break;
00275 }
00276
00277 default:
00278 case TM_3D:
00279 {
00280
00281 Vec3f res = vT->getResolution();
00282 Vec3f brickSubdivision =
00283 calcBrickSubdivision(int(res[0]),
00284 int(res[1]),
00285 int(res[2]),
00286 vT->getImage()->getBpp(), volume);
00287
00288 Vec3f brickSize(Real32((int)(res[0] / brickSubdivision[0])),
00289 Real32((int)(res[1] / brickSubdivision[1])),
00290 Real32((int)(res[2] / brickSubdivision[2])));
00291
00292
00293 FDEBUG(
00294 ("TextureManager::buildTextures - BrickSubdivision %d %d %d\n",
00295 brickSubdivision[0],
00296 brickSubdivision[1],
00297 brickSubdivision[2]));
00298
00299 _brickSets[BrickSet::XY].buildBricks3D(volume,
00300 brickSize,
00301 volume->getBrickOverlap());
00302
00303 _brickSets[BrickSet::XY].buildBrickTextures( material,
00304 _registeredTextures,
00305 textureMode);
00306
00307 break;
00308 }
00309 }
00310 }
00311
00312
00314 void TextureManager::dump( UInt32 ,
00315 const BitVector ) const
00316 {
00317 SLOG << "TextureManager:" << std::endl;
00318
00319 for (UInt32 i = 0; i < _registeredTextures.size(); i++)
00320 {
00321 SLOG << "image: " << _registeredTextures[i]->_image
00322 << std::endl;
00323 SLOG << "internalFormat: " << _registeredTextures[i]->_internalFormat
00324 << std::endl;
00325 SLOG << "textureStage0: " << _registeredTextures[i]->_textureStage0
00326 << std::endl;
00327 SLOG << "textureStage1: " << _registeredTextures[i]->_textureStage1
00328 << std::endl;
00329 }
00330 }
00331
00332
00333 Vec3f TextureManager::calcBrickSubdivision(Int32 resX,
00334 Int32 resY,
00335 Int32 resZ,
00336 Int32 dataSize,
00337 DVRVolume *volume)
00338 {
00339 Int32 mode = volume->getBrickingMode();
00340
00341
00342 Vec3f subdivision(1,1,1);
00343
00344 switch (mode)
00345 {
00346 case BRICK_SUBDIVIDE_STATIC:
00347 {
00348 subdivision = volume->getBrickStaticSubdivision();
00349 break;
00350 }
00351
00352 case BRICK_SUBDIVIDE_ON_TEXTURE_MEMORY:
00353 {
00354 Real32 fMB_available =
00355 1024.0F * 1024.0F * (Real32) volume->getBrickStaticMemoryMB();
00356
00357 Real32 fMB_required = (Real32) (resX * resY * resZ * dataSize);
00358
00359 Int32 nNumBricks = (Int32) osgceil(fMB_required /
00360 fMB_available);
00361 Int32 nRealNumBricks = 1;
00362
00363 while(nNumBricks > nRealNumBricks)
00364 {
00365 if ((resX >= resY) && (resX >= resZ))
00366 {
00367 resX /= 2;
00368 subdivision[0] *= 2;
00369 }
00370 else if (resY >= resZ)
00371 {
00372 resY /= 2;
00373 subdivision[1] *= 2;
00374
00375 }
00376 else
00377 {
00378 resZ /= 2;
00379 subdivision[2] *= 2;
00380 }
00381
00382 nRealNumBricks =
00383 (Int32)(subdivision[0] * subdivision[1] * subdivision[2]);
00384 }
00385 break;
00386 }
00387
00388 case BRICK_SUBDIVIDE_ON_BRICK_SIZE:
00389 {
00390 Vec3f maxSize = volume->getBrickMaxSize();
00391
00392 while(resX > (Int32) maxSize[0])
00393 {
00394 resX /= 2;
00395 subdivision[0] *= 2;
00396 }
00397 while(resY > (Int32) maxSize[1])
00398 {
00399 resY /= 2;
00400 subdivision[1] *= 2;
00401 }
00402 while(resZ > (Int32) maxSize[2])
00403 {
00404 resZ /= 2;
00405 subdivision[2] *= 2;
00406 }
00407 break;
00408 }
00409
00410 }
00411 return subdivision;
00412 }
00413
00414
00415 Brick *TextureManager::sortBricks(DrawActionBase *da,
00416 Matrix modelMat,
00417 Vec3f eyePoint,
00418 DVRVolume * ,
00419 TextureMode mode)
00420 {
00421
00422 FDEBUG(("TextureManager::sortBricks\n"));
00423
00424 if ((mode == TM_2D) || (mode == TM_2D_Multi))
00425 {
00426
00427 BrickSet::Orientation ori = BrickSet::XY;
00428 bool btf = true;
00429
00430 switch(Slicer::getSlicingDirection(da,NULL))
00431 {
00432 case Slicer::SD_X_FRONT_TO_BACK:
00433 ori = BrickSet::YZ;
00434 btf = false;
00435 break;
00436 case Slicer::SD_X_BACK_TO_FRONT:
00437 ori = BrickSet::YZ;
00438 btf = true;
00439 break;
00440 case Slicer::SD_Y_FRONT_TO_BACK:
00441 ori = BrickSet::XZ;
00442 btf = false;
00443 break;
00444 case Slicer::SD_Y_BACK_TO_FRONT:
00445 ori = BrickSet::XZ;
00446 btf = true;
00447 break;
00448 case Slicer::SD_Z_FRONT_TO_BACK:
00449 ori = BrickSet::XY;
00450 btf = false;
00451 break;
00452 case Slicer::SD_Z_BACK_TO_FRONT:
00453 ori = BrickSet::XY;
00454 btf = true;
00455 break;
00456 default:
00457 break;
00458 }
00459
00460
00461 return _brickSets[ori].sortBricks2D(btf);
00462 }
00463 else
00464 {
00465 return _brickSets[BrickSet::XY].sortBricks3D(modelMat, eyePoint);
00466 }
00467 }
00468
00469
00470 OSG_END_NAMESPACE
00471
00472