00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028 #ifndef DISPLAY4D_H
00029 #define DISPLAY4D_H
00030
00031
00032 #include <limits>
00033 #include <error.h>
00034
00035
00036 namespace Display
00037 {
00095 class Volume4D
00096 {
00097 public:
00098 enum Mode {
00099 VRT,
00100 MIP,
00101 MPR,
00102 };
00103
00104 Volume4D();
00105 ~Volume4D();
00106
00107 public:
00108
00112 template <typename DataType>
00113 void update(const DataType* data,
00114 unsigned int width,
00115 unsigned int height,
00116 unsigned int depth,
00117 unsigned int nb_frames);
00118
00120 void display() const;
00121
00123 void setFrame(unsigned int frame);
00124
00126 unsigned int getFrame() const;
00127
00129 unsigned int getNbFrames() const;
00130
00132 void nextFrame();
00133
00136 void setMode(Mode mode);
00137
00139 Mode getMode() const;
00140
00142 void setMprMatrix(const float matrix[]);
00143
00144 public:
00145
00149 void updateRamp(float min, float max);
00150
00154 void updateLut(const float* lut, unsigned int lutSize);
00155
00162 template <typename Lut>
00163 void updateLut(const Lut &lut);
00164
00170 void alignWithScreen() const;
00171
00176 void setQuality(float quality);
00177
00181 void setInterpolation(int interpolation);
00182
00185 void setMaxTextureSize(unsigned int w, unsigned int h, unsigned int d);
00186
00188 void getIntensityRange(float &min, float &max) const;
00189
00190 protected:
00191
00193 void initShader();
00194
00197 static void getTextureSize(const unsigned int data_size[],
00198 unsigned int texture_size[],
00199 const unsigned int max_texture_size[]);
00200
00205 template <typename DataType, typename DataOutType>
00206 static DataOutType* createTextureData(const DataType* data,
00207 const unsigned int data_size[],
00208 DataType &min,
00209 DataType& max,
00210 const unsigned int texture_size[]);
00211
00214 void render() const;
00215
00218 void renderSlice(const float m[]) const;
00219
00222 int getNbRenderingPlanes() const;
00223
00225 static void transf(const float p[], const float m[], float pp[]);
00226
00228 static void transp(float m[]);
00229
00231 static void normalize(float m[]);
00232
00233 protected:
00234 Mode m_rendering_mode;
00235 float m_quality;
00236 GLint m_interpolation;
00237 GLuint* m_data_texture;
00238 unsigned int m_nb_frames;
00239 unsigned int m_frame;
00240 unsigned int m_max_texture_size[3];
00241 float m_texture_scale[3];
00242 float m_intensity_range[2];
00243 float m_mpr_matrix[16];
00244
00245 protected:
00246 GLuint m_gpu_program;
00247 GLuint m_fragment_shader;
00248 float* m_internal_lut;
00249 GLuint m_lut_texture;
00250
00251 protected:
00253 template <typename DataType>
00254 struct OpenGLArgs {
00255 static GLenum type;
00256 static DataType min;
00257 static DataType max;
00258 };
00259 };
00260
00261 }
00262
00263
00265
00267
00268 namespace Display
00269 {
00275 template <typename DataType>
00276 void Volume4D::update(const DataType* data,
00277 unsigned int width,
00278 unsigned int height,
00279 unsigned int depth,
00280 unsigned int nb_frames)
00281 {
00282
00283 typedef unsigned char TextureType;
00284
00285
00286
00287 if(!data || !width || !height || !depth || !nb_frames) throw LOCATE(Error("wrong inputs"));
00288
00289
00290 if(!m_gpu_program) initShader();
00291
00292
00293 glUseProgram(m_gpu_program);
00294
00295
00296 unsigned int data_size[3] = {width, height, depth};
00297 unsigned int texture_size[3];
00298 getTextureSize(data_size, texture_size, m_max_texture_size);
00299 DataType min_intensity = OpenGLArgs<DataType>::max;
00300 DataType max_intensity = OpenGLArgs<DataType>::min;
00301
00302
00303 for(unsigned int i=0; i<3; ++i)
00304 {
00305 m_texture_scale[i] = (float)data_size[i] / texture_size[i];
00306
00307
00308 if(m_texture_scale[i]>1) m_texture_scale[i] = 1.0f;
00309 }
00310
00311
00312 if(m_data_texture)
00313 {
00314 if(m_nb_frames != nb_frames)
00315 {
00316 glDeleteTextures(m_nb_frames, m_data_texture);
00317 delete [] m_data_texture;
00318
00319 m_nb_frames = nb_frames;
00320 m_data_texture = new GLuint [nb_frames];
00321 glGenTextures(m_nb_frames, m_data_texture);
00322 }
00323 }
00324 else
00325 {
00326 m_nb_frames = nb_frames;
00327 m_data_texture = new GLuint [nb_frames];
00328 glGenTextures(m_nb_frames, m_data_texture);
00329 }
00330
00331
00332 for(unsigned int frame=0; frame<m_nb_frames; ++frame)
00333 {
00334
00335 DataType min, max;
00336 const DataType* current_frame = &data[frame*data_size[0]*data_size[1]*data_size[2]];
00337 TextureType* buffer = createTextureData<DataType, TextureType>(current_frame, data_size, min, max, texture_size);
00338 if(min < min_intensity) min_intensity = min;
00339 if(max > max_intensity) max_intensity = max;
00340
00341
00342 glBindTexture(GL_TEXTURE_3D, m_data_texture[frame]); glCheckError();
00343 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
00344 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
00345 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
00346 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, m_interpolation);
00347 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_interpolation);
00348 glTexImage3D(GL_TEXTURE_3D,
00349 0,
00350 GL_LUMINANCE,
00351 texture_size[0],
00352 texture_size[1],
00353 texture_size[2],
00354 0,
00355 GL_LUMINANCE,
00356 OpenGLArgs<TextureType>::type,
00357 buffer);
00358 glCheckError();
00359
00360
00361 glEnable(GL_TEXTURE_3D);
00362 glBindTexture(GL_TEXTURE_3D, m_data_texture[frame]); glCheckError();
00363 glDisable(GL_TEXTURE_3D);
00364
00365
00366 delete [] buffer;
00367 }
00368
00369
00370 m_intensity_range[0] = static_cast<float>(min_intensity);
00371 m_intensity_range[1] = static_cast<float>(max_intensity);
00372 updateRamp(m_intensity_range[0], m_intensity_range[1]);
00373
00374
00375 glUseProgram(0);
00376
00377
00378 m_frame = 0;
00379 }
00380
00381
00382 template <typename Lut>
00383 void Volume4D::updateLut(const Lut& lut)
00384 {
00385
00386 glUseProgram(m_gpu_program);
00387
00388
00389
00390
00391 GLint size = 4096;
00392 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
00393
00394
00395 if(!m_internal_lut) m_internal_lut = new float [size*4];
00396
00397
00398 float scale = (float)(m_intensity_range[1]-m_intensity_range[0])/size;
00399 for(int i=0; i<size; ++i)
00400 {
00401
00402
00403
00404 float intensity = i*scale + m_intensity_range[0];
00405
00406 float r=0,g=0,b=0,a=0;
00407 lut.get(intensity, r,g,b,a);
00408
00409 m_internal_lut[i*4+0] = r;
00410 m_internal_lut[i*4+1] = g;
00411 m_internal_lut[i*4+2] = b;
00412 m_internal_lut[i*4+3] = a;
00413 }
00414
00415
00416 if(!glIsTexture(m_lut_texture)) glGenTextures(1, &m_lut_texture);
00417 glBindTexture(GL_TEXTURE_2D, m_lut_texture); glCheckError();
00418 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00419 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00420 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00421 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00422 glTexImage2D(GL_TEXTURE_2D,
00423 0,
00424 GL_RGBA8,
00425 size,
00426 1,
00427 0,
00428 GL_RGBA,
00429 GL_FLOAT,
00430 m_internal_lut);
00431 glCheckError();
00432
00433
00434
00435
00436
00437
00438 glUseProgram(0);
00439 }
00440
00441
00447 template <typename DataType, typename DataOutType>
00448 DataOutType* Volume4D::createTextureData(const DataType* data,
00449 const unsigned int data_size[],
00450 DataType &min,
00451 DataType& max,
00452 const unsigned int texture_size[])
00453 {
00454
00455 min = OpenGLArgs<DataType>::max;
00456 max = OpenGLArgs<DataType>::min;
00457 for(const DataType* it=data; it!=&data[data_size[0]*data_size[1]*data_size[2]]; ++it)
00458 {
00459 if(*it < min) min = *it;
00460 if(*it > max) max = *it;
00461 }
00462
00463
00464 DataOutType* buffer = new DataOutType [texture_size[0]*texture_size[1]*texture_size[2]];
00465
00466
00467 float scale[3] = {
00468 (float)data_size[0] / texture_size[0],
00469 (float)data_size[1] / texture_size[1],
00470 (float)data_size[2] / texture_size[2]
00471 };
00472
00473
00474
00475
00476
00477
00478 for(unsigned int k=0; k<texture_size[2]; ++k)
00479 for(unsigned int j=0; j<texture_size[1]; ++j)
00480 for(unsigned int i=0; i<texture_size[0]; ++i)
00481 {
00482
00483 unsigned int I = (scale[0]>1) ? (unsigned int)(i*scale[0]) : i;
00484 unsigned int J = (scale[1]>1) ? (unsigned int)(j*scale[1]) : j;
00485 unsigned int K = (scale[2]>1) ? (unsigned int)(k*scale[2]) : k;
00486
00487
00488 DataType val = 0;
00489 if(I<data_size[0] && J<data_size[1] && K<data_size[2])
00490 val = data[(K*data_size[1]+J)*data_size[0]+I];
00491
00492
00493 if(max>min)
00494 val = (val-min) * OpenGLArgs<DataOutType>::max / (max-min);
00495
00496
00497 buffer[(k*texture_size[1]+j)*texture_size[0]+i] = static_cast<DataOutType>(val);
00498 }
00499
00500 return buffer;
00501 }
00502
00503
00504 }
00505
00506 #endif