29 #include "rawVolModel.h"
40 static GLuint createPreintegrationTable(
const uint8_t* Table );
42 static bool readTransferFunction( FILE* file, std::vector<uint8_t>& TF );
44 static bool readDimensionsAndScaling
47 uint32_t& w, uint32_t& h, uint32_t& d,
48 VolumeScaling& volScaling
53 RawVolumeModel::RawVolumeModel(
const std::string& filename )
54 : _headerLoaded( false )
55 , _filename( filename )
63 , _hasDerivatives( true )
67 bool RawVolumeModel::loadHeader(
const float brightness,
const float alpha )
69 LBASSERT( !_headerLoaded );
70 LBASSERT( brightness > 0.0f );
71 LBASSERT( alpha > 0.0f );
72 LBLOG(
eq::LOG_CUSTOM ) <<
"-------------------------------------------"
73 << std::endl <<
"model: " << _filename;
75 hFile header( fopen( ( _filename + std::string(
".vhf" ) ).c_str(),
"rb" ));
79 LBERROR <<
"Can't open header file" << std::endl;
84 const size_t fNameLen = _filename.length();
86 ( fNameLen >= 6 && _filename.substr( fNameLen-6, 6 ) ==
"_d.raw" ) ?
89 if( !readDimensionsAndScaling( header.f, _w, _h, _d, _volScaling ) )
92 _resolution = LB_MAX( _w, LB_MAX( _h, _d ) );
94 if( !readTransferFunction( header.f, _TF ))
99 if( brightness != 1.0f )
101 for(
size_t i = 0; i < _TF.size(); i+=4 )
103 _TF[i+0] =
static_cast< uint8_t
>( _TF[i+0] * brightness );
104 _TF[i+1] =
static_cast< uint8_t
>( _TF[i+1] * brightness );
105 _TF[i+2] =
static_cast< uint8_t
>( _TF[i+2] * brightness );
110 for(
size_t i = 3; i < _TF.size(); i+=4 )
111 _TF[i] = static_cast< uint8_t >( _TF[i] * alpha );
117 static int32_t calcHashKey(
const eq::Range& range )
119 return static_cast<int32_t
>(( range.start*10000.f + range.end )*10000.f );
123 bool RawVolumeModel::getVolumeInfo( VolumeInfo& info,
const eq::Range& range )
125 if( !_headerLoaded && !loadHeader( 1.0f, 1.0f ))
128 if( _preintName == 0 )
131 _preintName = createPreintegrationTable( &_TF[0] );
134 VolumePart* volumePart = 0;
135 const int32_t key = calcHashKey( range );
137 if( _volumeHash.find( key ) == _volumeHash.end( ) )
140 volumePart = &_volumeHash[ key ];
141 if( !_createVolumeTexture( volumePart->volume, volumePart->TD, range ))
146 volumePart = &_volumeHash[ key ];
149 info.volume = volumePart->volume;
150 info.TD = volumePart->TD;
151 info.preint = _preintName;
152 info.volScaling = _volScaling;
153 if( _hasDerivatives )
155 info.voxelSize.W = 1.f;
156 info.voxelSize.H = 1.f;
157 info.voxelSize.D = 1.f;
160 info.voxelSize.W = 1.f / _tW;
161 info.voxelSize.H = 1.f / _tH;
162 info.voxelSize.D = 1.f / _tD;
168 void RawVolumeModel::releaseVolumeInfo(
const eq::Range& range )
170 const int32_t key = calcHashKey( range );
171 if( _volumeHash.find( key ) == _volumeHash.end() )
174 _volumeHash.erase( key );
180 static uint32_t calcMinPow2( uint32_t size )
199 bool RawVolumeModel::_createVolumeTexture( GLuint& volume,
201 const eq::Range& range )
203 const uint32_t w = _w;
204 const uint32_t h = _h;
205 const uint32_t d = _d;
206 const uint32_t bytes = _hasDerivatives ? 4 : 1;
208 const int32_t bwStart = 2;
209 const int32_t bwEnd = 2;
212 clip<int32_t>(
static_cast< int32_t
>( d*range.start ), 0, d-1 );
215 clip<int32_t>(
static_cast< int32_t
>( d*range.end-1 ), 0, d-1 );
217 const uint32_t start =
218 static_cast<uint32_t
>( clip<int32_t>( s-bwStart, 0, d-1 ) );
221 static_cast<uint32_t
>( clip<int32_t>( e+bwEnd , 0, d-1 ) );
223 const uint32_t depth = end-start+1;
225 _tW = calcMinPow2( w );
226 _tH = calcMinPow2( h );
227 _tD = calcMinPow2( depth );
230 TD.
W =
static_cast<float>( w ) / static_cast<float>( _tW );
231 TD.
H =
static_cast<float>( h ) / static_cast<float>( _tH );
232 TD.
D =
static_cast<float>( e-s+1 ) / static_cast<float>( _tD );
233 TD.
D /= range.end>range.start ? (range.end-range.start) : 1.0f;
237 TD.
Db = range.start > 0.0001 ? bwStart /
static_cast<float>(_tD) : 0;
240 <<
"===============================================" << std::endl
241 <<
" w: " << w <<
" " << _tW
242 <<
" h: " << h <<
" " << _tH
243 <<
" d: " << d <<
" " << depth <<
" " << _tD << std::endl
244 <<
" r: " << _resolution << std::endl
245 <<
" ws: " << TD.
W <<
" hs: " << TD.
H <<
" wd: " << TD.
D
246 <<
" Do: " << TD.
Do <<
" Db: " << TD.
Db << std::endl
247 <<
" s= " << start <<
" e= " << end << std::endl;
250 std::vector<uint8_t> data( _tW*_tH*_tD*bytes, 0 );
251 const uint32_t wh4 = w * h * bytes;
252 const uint32_t tWH4 = _tW * _tH * bytes;
254 std::ifstream file ( _filename.c_str(), std::ifstream::in |
255 std::ifstream::binary | std::ifstream::ate );
257 if( !file.is_open() )
259 LBERROR <<
"Can't open model data file";
263 file.seekg( wh4*start, std::ios::beg );
265 if( w==_tW && h==_tH )
267 file.read( (
char*)( &data[0] ), wh4*depth );
271 for( uint32_t i=0; i<depth; i++ )
272 file.read( (
char*)( &data[i*tWH4] ), wh4 );
276 const uint32_t w4 = w * bytes;
277 const uint32_t tW4 = _tW * bytes;
279 for( uint32_t i=0; i<depth; i++ )
280 for( uint32_t j=0; j<h; j++ )
281 file.read( (
char*)( &data[ i*tWH4 + j*tW4] ), w4 );
286 LBASSERT( _glewContext );
288 glGenTextures( 1, &volume );
289 LBLOG(
eq::LOG_CUSTOM ) <<
"generated texture: " << volume << std::endl;
290 glBindTexture(GL_TEXTURE_3D, volume);
292 glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_S , GL_CLAMP_TO_EDGE );
293 glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_T , GL_CLAMP_TO_EDGE );
294 glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_WRAP_R , GL_CLAMP_TO_EDGE );
295 glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
296 glTexParameteri( GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
298 if( _hasDerivatives )
300 glTexImage3D( GL_TEXTURE_3D,
301 0, GL_RGBA, _tW, _tH, _tD,
302 0, GL_RGBA, GL_UNSIGNED_BYTE, (GLvoid*)(&data[0]) );
305 glTexImage3D( GL_TEXTURE_3D,
306 0, GL_ALPHA, _tW, _tH, _tD,
307 0, GL_ALPHA, GL_UNSIGNED_BYTE, (GLvoid*)(&data[0]) );
318 static void normalizeScaling
327 float maxS = float( LB_MAX( w, LB_MAX( h, d ) ));
329 scaling.
W *= w / maxS;
330 scaling.
H *= h / maxS;
331 scaling.
D *= d / maxS;
334 maxS = LB_MAX( scaling.
W, LB_MAX( scaling.
H, scaling.
D ) );
342 static bool readDimensionsAndScaling
345 uint32_t& w, uint32_t& h, uint32_t& d,
346 VolumeScaling& volScaling
349 if( fscanf( file,
"w=%u\n", &w ) == EOF )
351 if( fscanf( file,
"h=%u\n", &h ) == EOF )
353 if( fscanf( file,
"d=%u\n", &d ) != 1 )
355 LBERROR <<
"Can't read dimensions from header file" << std::endl;
359 if( fscanf( file,
"wScale=%g\n", &volScaling.W ) == EOF )
361 if( fscanf( file,
"hScale=%g\n", &volScaling.H ) == EOF )
363 if( fscanf( file,
"dScale=%g\n", &volScaling.D ) != 1 )
365 LBERROR <<
"Can't read scaling from header file: " << std::endl;
369 if( w<1 || h<1 || d<1 ||
370 volScaling.W<0.001 ||
371 volScaling.H<0.001 ||
374 LBERROR <<
"volume scaling is incorrect, check header file"<< std::endl;
378 normalizeScaling( w, h, d, volScaling );
380 LBLOG(
eq::LOG_CUSTOM ) <<
" " << w <<
"x" << h <<
"x" << d << std::endl
381 <<
"( " << volScaling.W <<
" x "
382 << volScaling.H <<
" x "
383 << volScaling.D <<
" )" << std::endl;
388 static bool readTransferFunction( FILE* file, std::vector<uint8_t>& TF )
390 if( fscanf(file,
"TF:\n") !=0 )
392 LBERROR <<
"Error in header file, can't find 'TF:' marker.";
397 if( fscanf( file,
"size=%u\n", &TFSize ) == EOF )
401 LBWARN <<
"Wrong size of transfer function, should be 256" << std::endl;
403 TFSize = clip<int32_t>( TFSize, 1, 256 );
404 TF.resize( TFSize*4 );
407 for( uint32_t i=0; i<TFSize; i++ )
409 if( fscanf( file,
"r=%d\n", &tmp ) == EOF )
412 if( fscanf( file,
"g=%d\n", &tmp ) == EOF )
415 if( fscanf( file,
"b=%d\n", &tmp ) == EOF )
418 if( fscanf( file,
"a=%d\n", &tmp ) != 1 )
420 LBERROR <<
"Failed to read entity #" << i
421 <<
" of TF from header file" << std::endl;
430 static GLuint createPreintegrationTable(
const uint8_t *Table )
432 LBLOG(
eq::LOG_CUSTOM ) <<
"Calculating preintegration table" << std::endl;
434 double rInt[256]; rInt[0] = 0.;
435 double gInt[256]; gInt[0] = 0.;
436 double bInt[256]; bInt[0] = 0.;
437 double aInt[256]; aInt[0] = 0.;
440 for(
int i=1; i<256; i++ )
443 const double tauc = ( Table[(i-1)*4+3] + Table[i*4+3] ) / 2. / 255.;
447 rInt[i] = rInt[i-1] + ( Table[(i-1)*4+0] + Table[i*4+0] )/2.*tauc;
448 gInt[i] = gInt[i-1] + ( Table[(i-1)*4+1] + Table[i*4+1] )/2.*tauc;
449 bInt[i] = bInt[i-1] + ( Table[(i-1)*4+2] + Table[i*4+2] )/2.*tauc;
452 aInt[i] = aInt[i-1] + tauc;
455 std::vector<GLubyte> lookupImg( 256*256*4, 255 );
459 for(
int sb=0; sb<256; sb++ )
461 for(
int sf=0; sf<256; sf++ )
464 if( sb<sf ) { smin=sb; smax=sf; }
465 else { smin=sf; smax=sb; }
467 double rcol, gcol, bcol, acol;
470 const double factor = 1. / (double)(smax-smin);
471 rcol = ( rInt[smax] - rInt[smin] ) * factor;
472 gcol = ( gInt[smax] - gInt[smin] ) * factor;
473 bcol = ( bInt[smax] - bInt[smin] ) * factor;
474 acol = exp( -( aInt[smax] - aInt[smin] ) * factor) * 255.;
477 const int index = smin*4;
478 const double factor = 1./255.;
479 rcol = Table[index+0] * Table[index+3] * factor;
480 gcol = Table[index+1] * Table[index+3] * factor;
481 bcol = Table[index+2] * Table[index+3] * factor;
482 acol = exp( -Table[index+3] * factor ) * 256.;
484 lookupImg[lookupindex++] = clip( static_cast<int>(rcol), 0, 255 );
485 lookupImg[lookupindex++] = clip( static_cast<int>(gcol), 0, 255 );
486 lookupImg[lookupindex++] = clip( static_cast<int>(bcol), 0, 255 );
487 lookupImg[lookupindex++] = clip( static_cast<int>(acol), 0, 255 );
491 GLuint preintName = 0;
492 glGenTextures( 1, &preintName );
493 glBindTexture( GL_TEXTURE_2D, preintName );
494 glTexImage2D( GL_TEXTURE_2D, 0, GL_RGBA, 256, 256, 0,
495 GL_RGBA, GL_UNSIGNED_BYTE, &lookupImg[0] );
497 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE );
498 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE );
499 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR );
500 glTexParameteri( GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR );
User-defined log topics (65536)
float D
Depth of data in texture (0..1].
float Do
Depth offset (start of range)
Contain overall volume proportions relatively [-1,-1,-1]..[1,1,1] cube.
float Db
Depth border (necessary for preintegration)
Just helping structure to automatically close files.
float W
Width of data in texture (0..1].
float H
Height of data in texture (0..1].
Structure that contain actual dimensions of data that is stored in volume texture.