00001 #ifndef OPENTISSUE_UTILITY_GL_GL_CROSS_SECTIONS_H
00002 #define OPENTISSUE_UTILITY_GL_GL_CROSS_SECTIONS_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/utility/gl/gl_util.h>
00013 #include <OpenTissue/gpu/image/image.h>
00014 #include <cassert>
00015 #include <cmath>
00016
00017 namespace OpenTissue
00018 {
00019 namespace gl
00020 {
00021
00026 class SignColorFunctor
00027 {
00028 public:
00029 template <typename value_type>
00030 void operator()( value_type const & val, value_type const & , value_type const & , GLubyte & red, GLubyte & green, GLubyte & blue, GLubyte & alpha ) const
00031 {
00032 if(val>=0)
00033 {
00034 red = 0;
00035 blue = 255;
00036 }
00037 else
00038 {
00039 red = 255;
00040 blue = 0;
00041 }
00042 green = 0;
00043 alpha = 255;
00044 }
00045 };
00046
00047
00052 class GreyScaleColorFunctor
00053 {
00054 public:
00055 template <typename value_type>
00056 void operator()( value_type const & val, value_type const & min_val, value_type const & max_val, GLubyte & red, GLubyte & green, GLubyte & blue, GLubyte & alpha ) const
00057 {
00058 value_type range = max_val - min_val;
00059 if(val>max_val || val<min_val)
00060 {
00061 red = green = blue = 0;
00062 alpha = 255;
00063 return;
00064 }
00065 value_type intensity = static_cast<value_type>( ( ( val - min_val ) * 255.0 ) / range );
00066 red = ( GLubyte ) ( intensity );
00067 green = ( GLubyte ) ( intensity );
00068 blue = ( GLubyte ) ( intensity );
00069 alpha = 255;
00070 }
00071 };
00072
00077 class GradientColorFunctor
00078 {
00079 public:
00080 template <typename value_type>
00081 void operator()( value_type const & val, value_type const & min_val, value_type const & max_val, GLubyte & red, GLubyte & green, GLubyte & blue, GLubyte & alpha ) const
00082 {
00083 value_type range = max_val - min_val;
00084 value_type red_intensity = static_cast<value_type>( ( ( max_val - val ) * 255.0 ) / range );
00085 value_type blue_intensity = static_cast<value_type>( ( ( val - min_val ) * 255.0 ) / range );
00086 red = (GLubyte) ( red_intensity );
00087 green = 0;
00088 blue = (GLubyte) ( blue_intensity );
00089 alpha = 255;
00090 }
00091 };
00092
00093
00100 template <typename grid_type>
00101 class CrossSections
00102 {
00103 public:
00104
00105 typedef typename grid_type::value_type value_type;
00106 typedef OpenTissue::image::Image<unsigned char> image_type;
00107
00108 protected:
00109
00110 image_type m_bitmap_i;
00111 image_type m_bitmap_j;
00112 image_type m_bitmap_k;
00113
00114 OpenTissue::texture::texture2D_pointer m_texture_i;
00115 OpenTissue::texture::texture2D_pointer m_texture_j;
00116 OpenTissue::texture::texture2D_pointer m_texture_k;
00117
00118 bool m_changed_i;
00119 bool m_changed_j;
00120 bool m_changed_k;
00121 unsigned int m_i;
00122 unsigned int m_j;
00123 unsigned int m_k;
00124 unsigned int m_max_i;
00125 unsigned int m_max_j;
00126 unsigned int m_max_k;
00127 grid_type * m_ptr_grid;
00128
00129 public:
00130
00131 CrossSections( )
00132 : m_changed_i(false)
00133 , m_changed_j(false)
00134 , m_changed_k(false)
00135 , m_i(0)
00136 , m_j(0)
00137 , m_k(0)
00138 , m_max_i(0)
00139 , m_max_j(0)
00140 , m_max_k(0)
00141 , m_ptr_grid(0)
00142 {}
00143
00144 protected:
00145
00157 template<typename color_func_type>
00158 void get_i_cut(color_func_type & color_func )
00159 {
00160 using OpenTissue::grid::min_element;
00161 using OpenTissue::grid::max_element;
00162
00163 if(!m_ptr_grid)
00164 return;
00165 if(!(m_ptr_grid->size()))
00166 return;
00167
00168 GLubyte * imgdata = static_cast<GLubyte*>( m_bitmap_i.get_data() );
00169
00170 assert( m_i >= 0u && m_i < m_ptr_grid->I() );
00171
00172 value_type min_val = min_element( *m_ptr_grid );
00173 value_type max_val = max_element( *m_ptr_grid );
00174 for ( unsigned int k = 0;k < m_ptr_grid->K();++k )
00175 {
00176 for ( unsigned int j = 0;j < m_ptr_grid->J();++j )
00177 {
00178 GLubyte * red = &imgdata[ ( k * m_ptr_grid->J() + j ) * 4 ];
00179 GLubyte * green = red + 1;
00180 GLubyte * blue = green + 1;
00181 GLubyte * alpha = blue + 1;
00182 unsigned int idx = ( k * m_ptr_grid->I() * m_ptr_grid->J() ) + ( j * m_ptr_grid->I() ) + m_i;
00183 value_type val = (*m_ptr_grid)(idx);
00184 color_func( val, min_val, max_val, *red, *green, *blue, *alpha );
00185 }
00186 }
00187
00188 m_texture_i->load( m_bitmap_i.get_data() );
00189 }
00190
00202 template<typename color_func_type>
00203 void get_j_cut(color_func_type & color_func )
00204 {
00205 using OpenTissue::grid::min_element;
00206 using OpenTissue::grid::max_element;
00207
00208 if(!m_ptr_grid)
00209 return;
00210 if(!(m_ptr_grid->size()))
00211 return;
00212
00213 GLubyte * imgdata = static_cast<GLubyte*>( m_bitmap_j.get_data() );
00214 assert( m_j >= 0u && m_j < m_ptr_grid->J() );
00215 value_type min_val = min_element( *m_ptr_grid );
00216 value_type max_val = max_element( *m_ptr_grid );
00217 for ( unsigned int k = 0; k < m_ptr_grid->K(); ++k )
00218 {
00219 for ( unsigned int i = 0; i < m_ptr_grid->I(); ++i )
00220 {
00221 GLubyte * red = &imgdata[ ( k * m_ptr_grid->I() + i ) * 4 ];
00222 GLubyte * green = red + 1;
00223 GLubyte * blue = green + 1;
00224 GLubyte * alpha = blue + 1;
00225 unsigned int idx = ( k * m_ptr_grid->I() * m_ptr_grid->J() ) + ( m_j * m_ptr_grid->I() ) + i;
00226 value_type val = (*m_ptr_grid)(idx);
00227 color_func( val, min_val, max_val, *red, *green, *blue, *alpha );
00228 }
00229 }
00230
00231 m_texture_j->load( m_bitmap_j.get_data() );
00232 }
00233
00245 template<typename color_func_type>
00246 void get_k_cut( color_func_type & color_func )
00247 {
00248 using OpenTissue::grid::min_element;
00249 using OpenTissue::grid::max_element;
00250
00251 if(!m_ptr_grid)
00252 return;
00253 if(!(m_ptr_grid->size()))
00254 return;
00255
00256 GLubyte * imgdata = static_cast<GLubyte*>( m_bitmap_k.get_data() );
00257 assert( m_k >= 0u && m_k < m_ptr_grid->K() );
00258 value_type min_val = min_element( *m_ptr_grid );
00259 value_type max_val = max_element( *m_ptr_grid );
00260 for ( unsigned int j = 0; j < m_ptr_grid->J(); ++j )
00261 {
00262 for ( unsigned int i = 0; i < m_ptr_grid->I(); ++i )
00263 {
00264 GLubyte * red = &imgdata[ ( j * m_ptr_grid->I() + i ) * 4 ];
00265 GLubyte * green = red + 1;
00266 GLubyte * blue = green + 1;
00267 GLubyte * alpha = blue + 1;
00268 unsigned int idx = ( m_k * m_ptr_grid->I() * m_ptr_grid->J() ) + ( j * m_ptr_grid->I() ) + i;
00269 value_type val = (*m_ptr_grid)(idx);
00270 color_func( val, min_val, max_val, *red, *green, *blue, *alpha );
00271 }
00272 }
00273
00274 m_texture_k->load( m_bitmap_k.get_data() );
00275 }
00276
00287 template<typename color_func_type>
00288 void get_bitmaps( color_func_type & color_func )
00289 {
00290 if(!m_ptr_grid)
00291 return;
00292 if(!(m_ptr_grid->size()))
00293 return;
00294
00295 if(m_max_i != m_ptr_grid->I() || m_max_j != m_ptr_grid->J() || m_max_k != m_ptr_grid->K() )
00296 allocate();
00297 if(m_changed_i)
00298 {
00299 get_i_cut ( color_func );
00300 m_changed_i = false;
00301 }
00302 if(m_changed_j)
00303 {
00304 get_j_cut ( color_func );
00305 m_changed_j = false;
00306 }
00307 if(m_changed_k)
00308 {
00309 get_k_cut ( color_func );
00310 m_changed_k = false;
00311 }
00312 }
00313
00314 void allocate()
00315 {
00316 m_max_i = m_ptr_grid->I();
00317 m_max_j = m_ptr_grid->J();
00318 m_max_k = m_ptr_grid->K();
00319 m_bitmap_i.create(m_max_j,m_max_k,4);
00320 m_bitmap_j.create(m_max_i,m_max_k,4);
00321 m_bitmap_k.create(m_max_i,m_max_j,4);
00322 m_texture_i = m_bitmap_i.create_texture(GL_RGBA, m_max_j!=m_max_k );
00323 m_texture_j = m_bitmap_j.create_texture(GL_RGBA, m_max_i!=m_max_k );
00324 m_texture_k = m_bitmap_k.create_texture(GL_RGBA, m_max_i!=m_max_j );
00325 m_i = m_max_i/2;
00326 m_j = m_max_j/2;
00327 m_k = m_max_k/2;
00328 m_changed_i = m_changed_j = m_changed_k = true;
00329 }
00330
00331 public:
00332
00339 void forward_i_plane()
00340 {
00341 if(!m_ptr_grid)
00342 return;
00343 if(!(m_ptr_grid->size()))
00344 return;
00345 m_i = (m_i + 1)%m_max_i;
00346 m_changed_i = true;
00347 }
00348
00355 void backward_i_plane()
00356 {
00357 if(!m_ptr_grid)
00358 return;
00359 if(!(m_ptr_grid->size()))
00360 return;
00361 m_i = (m_i - 1)%m_max_i;
00362 if(m_i<0)
00363 m_i += m_max_i;
00364 m_changed_i = true;
00365 }
00366
00373 void forward_j_plane()
00374 {
00375 if(!m_ptr_grid)
00376 return;
00377 if(!(m_ptr_grid->size()))
00378 return;
00379 m_j = (m_j + 1)%m_max_j;
00380 m_changed_j = true;
00381 }
00382
00389 void backward_j_plane()
00390 {
00391 if(!m_ptr_grid)
00392 return;
00393 if(!(m_ptr_grid->size()))
00394 return;
00395 m_j = (m_j - 1)%m_max_j;
00396 if(m_j<0)
00397 m_j += m_max_j;
00398 m_changed_j = true;
00399 }
00400
00407 void forward_k_plane()
00408 {
00409 if(!m_ptr_grid)
00410 return;
00411 if(!(m_ptr_grid->size()))
00412 return;
00413 m_k = (m_k + 1)%m_max_k;
00414 m_changed_k = true;
00415 }
00416
00423 void backward_k_plane()
00424 {
00425 if(!m_ptr_grid)
00426 return;
00427 if(!(m_ptr_grid->size()))
00428 return;
00429 m_k = (m_k - 1)%m_max_k;
00430 if(m_k<0)
00431 m_k += m_max_k;
00432 m_changed_k = true;
00433 }
00434
00435 public:
00436
00446 void invalidate()
00447 {
00448 if(!m_ptr_grid)
00449 return;
00450
00451 if(!(m_ptr_grid->size()))
00452 return;
00453
00454 m_changed_i = m_changed_j = m_changed_k = true;
00455 }
00456
00470 void init(grid_type const & grid)
00471 {
00472 glPushAttrib(GL_ALL_ATTRIB_BITS);
00473 m_ptr_grid = const_cast<grid_type*>(&grid);
00474 allocate();
00475 glPopAttrib();
00476 }
00477
00487 template<typename color_func_type>
00488 void draw( color_func_type const & color_func )
00489 {
00490 gl::gl_check_errors("OpenTissue::CrossSections::draw() - start");
00491
00492 if(!m_ptr_grid)
00493 return;
00494
00495 if(!(m_ptr_grid->size()))
00496 return;
00497
00498 glPushAttrib(GL_ALL_ATTRIB_BITS);
00499 glDisable(GL_LIGHTING);
00500
00501 get_bitmaps(color_func);
00502
00503 GLfloat sx = ( m_ptr_grid->max_coord(0) - m_ptr_grid->min_coord(0) ) / m_ptr_grid->I();
00504 GLfloat sy = ( m_ptr_grid->max_coord(1) - m_ptr_grid->min_coord(1) ) / m_ptr_grid->J();
00505 GLfloat sz = ( m_ptr_grid->max_coord(2) - m_ptr_grid->min_coord(2) ) / m_ptr_grid->K();
00506
00507 GLfloat tx = m_i * m_ptr_grid->dx();
00508 GLfloat ty = m_j * m_ptr_grid->dy();
00509 GLfloat tz = m_k * m_ptr_grid->dz();
00510
00511 GLfloat cx = m_ptr_grid->min_coord(0);
00512 GLfloat cy = m_ptr_grid->min_coord(1);
00513 GLfloat cz = m_ptr_grid->min_coord(2);
00514
00515 GLfloat Ival = 1.0f*m_ptr_grid->I();
00516 GLfloat Jval = 1.0f*m_ptr_grid->J();
00517 GLfloat Kval = 1.0f*m_ptr_grid->K();
00518
00519 glPushMatrix();
00520 glTranslatef( cx, cy, cz );
00521 glPushMatrix();
00522 glTranslatef( tx, 0, 0 );
00523 glRotatef( 90, 0, 0, 1 );
00524 glRotatef( 90, 1, 0, 0 );
00525 glScalef( sy, sz, 1 );
00526 gl::ColorPicker( 1.0, 0, 0, 1.0 );
00527 glBegin( GL_LINE_LOOP );
00528 glVertex3f( 0, 0, 0 );
00529 glVertex3f( Jval, 0, 0 );
00530 glVertex3f( Jval, Kval, 0 );
00531 glVertex3f( 0, Kval, 0 );
00532 glEnd();
00533 gl::ColorPicker( 1.0, 1.0, 1.0, 1.0 );
00534 gl::DrawTexture2D(*m_texture_i);
00535 glPopMatrix();
00536
00537 glPushMatrix();
00538 glTranslatef( 0, ty, 0 );
00539 glRotatef( 90, 1, 0, 0 );
00540 glScalef( sx, sz, 1 );
00541 gl::ColorPicker( 0, 1.0, 0, 1.0 );
00542 glBegin( GL_LINE_LOOP );
00543 glVertex3f( 0, 0, 0 );
00544 glVertex3f( Ival, 0, 0 );
00545 glVertex3f( Ival, Kval, 0 );
00546 glVertex3f( 0, Kval, 0 );
00547 glEnd();
00548 gl::ColorPicker( 1.0, 1.0, 1.0, 1.0 );
00549 gl::DrawTexture2D(*m_texture_j);
00550 glPopMatrix();
00551
00552 glPushMatrix();
00553 glTranslatef( 0, 0, tz );
00554 glScalef( sx, sy, 1 );
00555 gl::ColorPicker( 0, 0, 1.0, 1.0 );
00556 glBegin( GL_LINE_LOOP );
00557 glVertex3f( 0, 0, 0 );
00558 glVertex3f( Ival, 0, 0 );
00559 glVertex3f( Ival, Jval, 0 );
00560 glVertex3f( 0, Jval, 0 );
00561 glEnd();
00562 gl::ColorPicker( 1.0, 1.0, 1.0, 1.0 );
00563 gl::DrawTexture2D(*m_texture_k);
00564 glPopMatrix();
00565
00566 glPopMatrix();
00567 glPopAttrib();
00568 }
00569
00570 };
00571
00572 }
00573 }
00574
00575
00576 #endif