00001 #ifndef OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_VOXELIZER_H
00002 #define OPENTISSUE_CORE_CONTAINERS_GRID_UTIL_VOXELIZER_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/texture/texture_create_texture2D.h>
00014 #include <OpenTissue/core/math/math_vector3.h>
00015 #include <OpenTissue/core/containers/mesh/mesh.h>
00016 #include <OpenTissue/core/containers/grid/grid.h>
00017
00018 #include <boost/cast.hpp>
00019
00020 #include <cmath>
00021 #include <iostream>
00022
00023 namespace OpenTissue
00024 {
00025 namespace grid
00026 {
00027
00028 namespace detail
00029 {
00030
00031 template<typename grid_type>
00032 class Voxelizer
00033 {
00034 public:
00035
00036 typedef typename grid_type::value_type T;
00037 typedef typename grid_type::math_types math_types;
00038 typedef typename math_types::real_type real_type;
00039 typedef typename math_types::vector3_type vector3_type;
00040
00041 protected:
00042
00043 std::vector<GLubyte> m_pixels;
00044
00045 OpenTissue::texture::texture2D_pointer m_texture;
00046 gl::renderbuffer_pointer m_stencil;
00047 gl::renderbuffer_pointer m_color;
00048 gl::FramebufferObject m_fbo;
00049
00050 public:
00051
00052 Voxelizer()
00053 : m_pixels()
00054 {}
00055
00056 ~Voxelizer(){}
00057
00058 public:
00059
00060 template<typename mesh_type>
00061 void run(mesh_type & mesh, grid_type & voxels)
00062 {
00063 using std::min;
00064 using std::max;
00065
00066 if(mesh.size_faces()==0)
00067 return;
00068
00069
00070 std::fill(voxels.begin(),voxels.end(), boost::numeric_cast<T>(0) );
00071 m_pixels.resize( voxels.I()*voxels.J()*4 );
00072
00073 glPushAttrib(GL_ALL_ATTRIB_BITS);
00074 gl::gl_check_errors("voxelizer(): push all atrribs");
00075
00076 int w = voxels.I();
00077 int h = voxels.J();
00078
00079 bool fbo_support = true;
00080 if(fbo_support)
00081 {
00082 m_stencil = gl::create_packed_depth_and_stencil_buffer(w,h);
00083 gl::gl_check_errors("voxelizer(): stencil buffer created");
00084 m_color.reset( new gl::Renderbuffer(GL_RGBA8_EXT, w, h) );
00085 gl::gl_check_errors("voxelizer(): color buffer created");
00086 m_fbo.bind();
00087 gl::gl_check_errors("voxelizer(): fbo bind");
00088 m_fbo.attach_render_buffer(GL_STENCIL_ATTACHMENT_EXT, m_stencil);
00089 gl::gl_check_errors("voxelizer(): attach stencil buffer");
00090 m_fbo.attach_render_buffer(GL_DEPTH_ATTACHMENT_EXT, m_stencil);
00091 gl::gl_check_errors("voxelizer(): attach stencil buffer");
00092 m_fbo.attach_render_buffer(GL_COLOR_ATTACHMENT0_EXT, m_color);
00093 gl::gl_check_errors("voxelizer(): attach color buffer");
00094 m_fbo.is_valid();
00095 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00096 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
00097 }
00098
00099 glDisable(GL_COLOR_MATERIAL);
00100 glDisable(GL_LIGHTING);
00101 glMatrixMode( GL_PROJECTION );
00102 glPushMatrix();
00103 glLoadIdentity();
00104 GLdouble left = voxels.min_coord(0);
00105 GLdouble right = voxels.max_coord(0);
00106 GLdouble bottom = voxels.min_coord(1);
00107 GLdouble top = voxels.max_coord(1);
00108 left -= voxels.dx()/2;
00109 right += voxels.dx()/2;
00110 bottom -= voxels.dy()/2;
00111 top += voxels.dy()/2;
00112 GLdouble zdiff = 2.*(voxels.max_coord(2) - voxels.min_coord(2));
00113 glOrtho(left,right,bottom,top,-zdiff,zdiff);
00114 glViewport(0,0,w,h);
00115 glMatrixMode( GL_MODELVIEW );
00116 glPushMatrix();
00117 glLoadIdentity();
00118
00119
00120 vector3_type vmin,vmax;
00121 mesh::compute_mesh_minimum_coord(mesh,vmin);
00122 mesh::compute_mesh_maximum_coord(mesh,vmax);
00123
00124
00125 int kmin = boost::numeric_cast<int>((vmin(2) - voxels.min_coord(2))/voxels.dz()) - 1;
00126 kmin = max(kmin,0);
00127 int kmax = boost::numeric_cast<int>((vmax(2) - voxels.min_coord(2))/voxels.dz()) + 1;
00128 kmax = min(kmax,boost::numeric_cast<int>(voxels.K()));
00129
00130 for(int k=kmin;k<kmax;++k)
00131 clip(&mesh, voxels, k, vmin, vmax);
00132
00133
00134 if(fbo_support)
00135 gl::FramebufferObject::disable();
00136
00137 glMatrixMode( GL_MODELVIEW );
00138 glPopMatrix();
00139 glMatrixMode( GL_PROJECTION );
00140 glPopMatrix();
00141 glPopAttrib();
00142 }
00143
00144 private:
00145
00146 void draw_rectangle(grid_type & voxels, real_type const & minx,real_type const & miny,real_type const & maxx,real_type const & maxy)
00147 {
00148 glBegin(GL_POLYGON);
00149 glVertex3d(minx,miny,voxels.max_coord(2));
00150 glVertex3d(maxx,miny,voxels.max_coord(2));
00151 glVertex3d(maxx,maxy,voxels.max_coord(2));
00152 glVertex3d(minx,maxy,voxels.max_coord(2));
00153 glEnd();
00154 }
00155
00164 template<typename mesh_type>
00165 void clip(mesh_type * mesh, grid_type & voxels, int k,vector3_type & vmin,vector3_type & vmax)
00166 {
00167
00168
00169
00170
00171
00172 {
00173 GLdouble zcut = (k * voxels.dz()) + voxels.min_coord(2);
00174
00175 GLdouble planeEq[4];
00176 planeEq[0] = 0;
00177 planeEq[1] = 0;
00178 planeEq[2] = 1;
00179 planeEq[3] = -zcut;
00180
00181 glClipPlane(GL_CLIP_PLANE0,planeEq);
00182 glEnable(GL_CLIP_PLANE0);
00183 }
00184
00185
00186 {
00187 glClearColor( 0.0, 0.0, 0.0, 0.0 );
00188 glClearDepth(0);
00189 glDepthMask(GL_TRUE);
00190 glClearStencil(0);
00191 glStencilMask(~0u);
00192 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00193 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
00194 }
00195
00196
00197 {
00198 glEnable(GL_STENCIL_TEST);
00199 glColorMask(GL_FALSE,GL_FALSE,GL_FALSE,GL_FALSE);
00200 glDisable(GL_DEPTH_TEST);
00201 glEnable(GL_CULL_FACE);
00202 glStencilFunc(GL_ALWAYS,0,~0u);
00203 glCullFace(GL_BACK);
00204 glStencilOp(GL_KEEP,GL_KEEP,GL_INCR);
00205
00206 glColor3f(1.0,0.0,0.0);
00207 gl::DrawMesh(*mesh,GL_POLYGON,false,false,false);
00208 }
00209
00210
00211 {
00212 glCullFace(GL_FRONT);
00213 glStencilOp(GL_KEEP,GL_KEEP,GL_DECR);
00214
00215 glColor3f(0.0,1.0,0.0);
00216 gl::DrawMesh(*mesh,GL_POLYGON,false,false,false);
00217 }
00218
00219
00220 {
00221 glColorMask(GL_TRUE,GL_TRUE,GL_TRUE,GL_TRUE);
00222 glStencilFunc(GL_EQUAL,1,~0u);
00223 glStencilOp(GL_KEEP,GL_KEEP,GL_KEEP);
00224
00225 glCullFace(GL_BACK);
00226 glColor3f(0,0,1);
00227 draw_rectangle(voxels,vmin(0),vmin(1),vmax(0),vmax(1));
00228 }
00229
00230 extract_voxels(voxels,k);
00231
00232
00233 {
00234 glDisable(GL_CLIP_PLANE0);
00235 glEnable(GL_DEPTH_TEST);
00236 glDisable(GL_STENCIL_TEST);
00237 glCullFace(GL_BACK);
00238 }
00239 }
00240
00241 template<typename grid_type2>
00242 void extract_voxels(grid_type2 & voxels, int k)
00243 {
00244 gl::gl_check_errors("extract_voxels::clip(): on entry");
00245
00246 int w = boost::numeric_cast<int>( voxels.I() );
00247 int h = boost::numeric_cast<int>( voxels.J() );
00248
00249 glFinish();
00250 gl::gl_check_errors("voxelizer::clip(): glFinish");
00251 glReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, &m_pixels[0] );
00252 gl::gl_check_errors("extract_voxels::clip(): glReadPixels");
00253 for( int j=0;j<h;++j)
00254 {
00255 for( int i=0;i<w;++i)
00256 {
00257 int offset = (w*j + i)*4;
00258
00259
00260 unsigned char blue = m_pixels[ offset + 2];
00261
00262 if(blue>0)
00263 voxels(i,j,k) = 1;
00264 else
00265 voxels(i,j,k) = 0;
00266 }
00267 }
00268 }
00269
00270 };
00271
00272 }
00273
00280 template<typename mesh_type,typename grid_type>
00281 inline void voxelizer(mesh_type & mesh, grid_type & phi)
00282 {
00283 typedef detail::Voxelizer<grid_type> voxelizer_type;
00284 voxelizer_type().run(mesh,phi);
00285 }
00286
00287 }
00288 }
00289
00290
00291 #endif