00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00028 #ifndef DISPLAY3D_H
00029 #define DISPLAY3D_H
00030
00031
00032 #include <limits>
00033 #include <error.h>
00034
00035
00036 namespace Display
00037 {
00092 class Volume
00093 {
00094 public:
00095 enum Mode {
00096 VRT,
00097 MIP,
00098 MPR,
00099 };
00100
00101 Volume();
00102 ~Volume();
00103
00104 public:
00105
00109 template <typename DataType>
00110 void update(const DataType* data, unsigned int w, unsigned int h, unsigned int d);
00111
00113 void display() const;
00114
00117 void setMode(Mode mode);
00118
00120 Mode getMode() const;
00121
00123 void setMprMatrix(const float matrix[]);
00124
00125 public:
00126
00130 void updateRamp(float min, float max);
00131
00135 void updateLut(const float* lut, unsigned int lutSize);
00136
00143 template <typename Lut>
00144 void updateLut(const Lut &lut);
00145
00151 void alignWithScreen() const;
00152
00157 void setQuality(float quality);
00158
00162 void setInterpolation(int interpolation);
00163
00166 void setMaxTextureSize(unsigned int w, unsigned int h, unsigned int d);
00167
00169 void getIntensityRange(float &min, float &max) const;
00170
00171 protected:
00172
00174 void initShader();
00175
00178 static void getTextureSize(const unsigned int data_size[],
00179 unsigned int texture_size[],
00180 const unsigned int max_texture_size[]);
00181
00186 template <typename DataType, typename DataOutType>
00187 static DataOutType* createTextureData(const DataType* data,
00188 const unsigned int data_size[],
00189 DataType &min,
00190 DataType& max,
00191 const unsigned int texture_size[]);
00192
00195 void render() const;
00196
00199 void renderSlice(const float m[]) const;
00200
00203 int getNbRenderingPlanes() const;
00204
00206 static void transf(const float p[], const float m[], float pp[]);
00207
00209 static void transp(float m[]);
00210
00212 static void normalize(float m[]);
00213
00214 protected:
00215 Mode m_rendering_mode;
00216 float m_quality;
00217 GLint m_interpolation;
00218 GLuint m_data_texture;
00219 unsigned int m_max_texture_size[3];
00220 float m_texture_scale[3];
00221 float m_intensity_range[2];
00222 float m_mpr_matrix[16];
00223
00224 protected:
00225 GLuint m_gpu_program;
00226 GLuint m_fragment_shader;
00227 float* m_internal_lut;
00228 GLuint m_lut_texture;
00229
00230 protected:
00232 template <typename DataType>
00233 struct OpenGLArgs {
00234 static GLenum type;
00235 static DataType min;
00236 static DataType max;
00237 };
00238 };
00239
00240 }
00241
00242
00244
00246
00247 namespace Display
00248 {
00254 template <typename DataType>
00255 void Volume::update(const DataType* data, unsigned int width, unsigned int height, unsigned int depth)
00256 {
00257
00258 typedef unsigned char TextureType;
00259
00260
00261
00262 if(!data || !width || !height || !depth) throw LOCATE(Error("wrong inputs"));
00263
00264
00265 if(!m_gpu_program) initShader();
00266
00267
00268 glUseProgram(m_gpu_program);
00269
00270
00271 unsigned int data_size[3] = {width, height, depth};
00272 unsigned int texture_size[3];
00273 DataType min, max;
00274 getTextureSize(data_size, texture_size, m_max_texture_size);
00275 TextureType* buffer = createTextureData<DataType, TextureType>(data, data_size, min, max, texture_size);
00276
00277
00278 for(unsigned int i=0; i<3; ++i) m_texture_scale[i] = (float)data_size[i] / texture_size[i];
00279
00280
00281 if(!glIsTexture(m_data_texture)) glGenTextures(1, &m_data_texture); glCheckError();
00282 glBindTexture(GL_TEXTURE_3D, m_data_texture); glCheckError();
00283 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_BORDER);
00284 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_BORDER);
00285 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_BORDER);
00286 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, m_interpolation);
00287 glTexParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, m_interpolation);
00288 glTexImage3D(GL_TEXTURE_3D,
00289 0,
00290 GL_LUMINANCE,
00291 texture_size[0],
00292 texture_size[1],
00293 texture_size[2],
00294 0,
00295 GL_LUMINANCE,
00296 OpenGLArgs<TextureType>::type,
00297 buffer);
00298 glCheckError();
00299
00300
00301 glEnable(GL_TEXTURE_3D);
00302 glBindTexture(GL_TEXTURE_3D, m_data_texture); glCheckError();
00303 glDisable(GL_TEXTURE_3D);
00304
00305
00306 delete [] buffer;
00307
00308
00309 m_intensity_range[0] = static_cast<float>(min);
00310 m_intensity_range[1] = static_cast<float>(max);
00311 updateRamp(m_intensity_range[0], m_intensity_range[1]);
00312
00313
00314 glUseProgram(0);
00315 }
00316
00317
00318 template <typename Lut>
00319 void Volume::updateLut(const Lut& lut)
00320 {
00321
00322 glUseProgram(m_gpu_program);
00323
00324
00325
00326
00327 GLint size = 4096;
00328 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &size);
00329
00330
00331 if(!m_internal_lut) m_internal_lut = new float [size*4];
00332
00333
00334 float scale = (float)(m_intensity_range[1]-m_intensity_range[0])/size;
00335 for(int i=0; i<size; ++i)
00336 {
00337
00338
00339
00340 float intensity = i*scale + m_intensity_range[0];
00341
00342 float r=0,g=0,b=0,a=0;
00343 lut.get(intensity, r,g,b,a);
00344
00345 m_internal_lut[i*4+0] = r;
00346 m_internal_lut[i*4+1] = g;
00347 m_internal_lut[i*4+2] = b;
00348 m_internal_lut[i*4+3] = a;
00349 }
00350
00351
00352 if(!glIsTexture(m_lut_texture)) glGenTextures(1, &m_lut_texture);
00353 glBindTexture(GL_TEXTURE_2D, m_lut_texture); glCheckError();
00354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
00355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
00356 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
00357 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
00358 glTexImage2D(GL_TEXTURE_2D,
00359 0,
00360 GL_RGBA8,
00361 size,
00362 1,
00363 0,
00364 GL_RGBA,
00365 GL_FLOAT,
00366 m_internal_lut);
00367 glCheckError();
00368
00369
00370
00371
00372
00373
00374 glUseProgram(0);
00375 }
00376
00377
00383 template <typename DataType, typename DataOutType>
00384 DataOutType* Volume::createTextureData(const DataType* data,
00385 const unsigned int data_size[],
00386 DataType &min,
00387 DataType& max,
00388 const unsigned int texture_size[])
00389 {
00390
00391 min = OpenGLArgs<DataType>::max;
00392 max = OpenGLArgs<DataType>::min;
00393 for(const DataType* it=data; it!=&data[data_size[0]*data_size[1]*data_size[2]]; ++it)
00394 {
00395 if(*it < min) min = *it;
00396 if(*it > max) max = *it;
00397 }
00398
00399
00400 DataOutType* buffer = new DataOutType [texture_size[0]*texture_size[1]*texture_size[2]];
00401
00402
00403 for(unsigned int k=0; k<texture_size[2]; ++k)
00404 for(unsigned int j=0; j<texture_size[1]; ++j)
00405 for(unsigned int i=0; i<texture_size[0]; ++i)
00406 {
00407
00408 DataType val = 0;
00409 if(i<data_size[0] && j<data_size[1] && k<data_size[2])
00410 val = data[(k*data_size[1]+j)*data_size[0]+i];
00411
00412
00413 if(max>min)
00414 val = (val-min) * OpenGLArgs<DataOutType>::max / (max-min);
00415
00416
00417 buffer[(k*texture_size[1]+j)*texture_size[0]+i] = static_cast<DataOutType>(val);
00418 }
00419
00420 return buffer;
00421 }
00422
00423
00424 }
00425
00426 #endif