00001 #ifndef OPENTISSUE_CORE_GEOMETRY_T4_GPU_SCAN_T4_GPU_SCAN_H
00002 #define OPENTISSUE_CORE_GEOMETRY_T4_GPU_SCAN_T4_GPU_SCAN_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/core/geometry/t4_gpu_scan/compute_obb_shell.h>
00013
00014 #include <OpenTissue/utility/gl/gl_util.h>
00015 #include <OpenTissue/gpu/cg/cg_util.h>
00016 #include <OpenTissue/gpu/cg/cg_program.h>
00017
00018 #include <OpenTissue/gpu/texture/texture_texture2D.h>
00019 #include <OpenTissue/gpu/texture/texture_create_texture2D.h>
00020
00021 #include <OpenTissue/core/math/math_vector3.h>
00022 #include <OpenTissue/core/containers/mesh/mesh.h>
00023 #include <OpenTissue/core/containers/t4mesh/t4mesh.h>
00024
00025 #include <OpenTissue/core/geometry/geometry_tetrahedron_z_slicer.h>
00026 #include <OpenTissue/core/geometry/geometry_local_triangle_frame.h>
00027
00028 #include <boost/type_traits.hpp>
00029
00030 #include<vector>
00031
00032 namespace OpenTissue
00033 {
00034
00035 namespace detail
00036 {
00037
00038 template<typename real_type_ >
00039 class T4GPUScan
00040 {
00041 public:
00042
00043 typedef real_type_ real_type;
00044
00045 protected:
00046
00047 struct event_type
00048 {
00049 public:
00050
00051 real_type m_z_min;
00052 real_type m_z_max;
00053 int m_idx;
00054
00055 public:
00056
00057 event_type( int const & idx, real_type const & z_min, real_type const & z_max)
00058 : m_z_min(z_min)
00059 , m_z_max(z_max)
00060 , m_idx(idx)
00061 {}
00062
00063 bool operator <(event_type const & E) const
00064 {
00065 if(m_z_min < E.m_z_min)
00066 return true;
00067 return false;
00068 }
00069 };
00070
00071 typedef std::vector<event_type> event_container;
00072 typedef typename event_container::iterator event_iterator;
00073
00074 protected:
00075
00076 real_type m_z_value;
00077 real_type m_delta_z_value;
00078 real_type m_max_z_value;
00079 real_type m_min_z_value;
00080 event_container m_events;
00081 event_container m_status;
00082 event_iterator m_last_event;
00083
00084 real_type m_thickness;
00085
00086 OpenTissue::texture::texture2D_pointer m_distance_texture[2];
00087
00088 gl::FramebufferObject m_fbo[2];
00089 gl::renderbuffer_pointer m_rb_depth[2];
00090
00091 cg::Program m_fragment_program;
00092
00093
00094 GLint m_state_current_drawbuf;
00095 GLint m_state_viewport[4];
00096 float m_state_color_clear_value[4];
00097 bool m_state_depth_test;
00098 GLint m_state_depth_func;
00099 float m_state_depth_clear_value;
00100
00101 protected:
00102
00103 template<typename grid_type>
00104 void set_gl_state(grid_type const & phi)
00105 {
00106 gl::gl_check_errors("set_gl_state: called");
00107
00108 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
00109 gl::gl_check_errors("set_gl_state: switched to color0 attachement");
00110
00111
00112
00113 glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
00114 glMatrixMode( GL_PROJECTION );
00115 glLoadIdentity();
00116 GLdouble left = phi.min_coord(0) - phi.dx()/2;
00117 GLdouble right = phi.max_coord(0) + phi.dx()/2;
00118 GLdouble bottom = phi.min_coord(1) - phi.dy()/2;
00119 GLdouble top = phi.max_coord(1) + phi.dy()/2;
00120 gluOrtho2D( left, right, bottom, top);
00121 glMatrixMode( GL_MODELVIEW );
00122 glLoadIdentity();
00123
00124 glViewport(0,0,phi.I(),phi.J());
00125 gl::gl_check_errors("set_gl_state: proj and modelview setup");
00126
00127 glClearColor( phi.unused(), 0, 0, 0 );
00128 glEnable( GL_DEPTH_TEST );
00129 glDepthFunc( GL_LESS );
00130 glClearDepth( 1.0 );
00131 gl::gl_check_errors("set_gl_state: clear and depth setup");
00132 }
00133
00137 template<typename grid_type>
00138 void init_fbo(grid_type const & phi)
00139 {
00140 gl::gl_check_errors("init_fbo: called");
00141
00142 for(int i=0; i<2; ++i)
00143 {
00144
00145 m_distance_texture[i] = OpenTissue::texture::create_float_texture_rectangle( phi.I(), phi.J(), 1, 0 );
00146
00147 m_fbo[i].bind();
00148 m_fbo[i].attach_texture(GL_COLOR_ATTACHMENT0_EXT, m_distance_texture[i] );
00149
00150
00151 m_rb_depth[i] = gl::create_depth_buffer( phi.I(), phi.J() );
00152 m_fbo[i].attach_render_buffer( GL_DEPTH_ATTACHMENT_EXT, m_rb_depth[i] );
00153 gl::gl_check_errors("init_fbo: renderbuffer attached");
00154
00155
00156 m_fbo[i].is_valid();
00157 gl::gl_check_errors("init_fbo: validated fbo");
00158
00159 set_gl_state(phi);
00160 }
00161
00162 gl::FramebufferObject::disable();
00163 gl::gl_check_errors("init_fbo: done configuring fbo");
00164 }
00165
00169 void disable_fbo()
00170 {
00171 gl::gl_check_errors("disable_fbo: called");
00172
00173 gl::FramebufferObject::disable();
00174 gl::gl_check_errors("disable_fbo: fbo disabled");
00175 }
00176
00180 void store_gl_state()
00181 {
00182 gl::gl_check_errors("store_gl_state: called");
00183
00184 glGetIntegerv(GL_DRAW_BUFFER, &m_state_current_drawbuf);
00185 gl::gl_check_errors("store_gl_state: stored current drawbuffer");
00186
00187
00188
00189 glGetIntegerv(GL_VIEWPORT, m_state_viewport);
00190 gl::gl_check_errors("store_gl_state: stored current viewport");
00191
00192 glGetFloatv(GL_COLOR_CLEAR_VALUE, m_state_color_clear_value);
00193 m_state_depth_test = ( glIsEnabled(GL_DEPTH_TEST) != 0 );
00194 glGetIntegerv(GL_DEPTH_FUNC, &m_state_depth_func);
00195 glGetFloatv(GL_DEPTH_CLEAR_VALUE, &m_state_depth_clear_value);
00196 gl::gl_check_errors("store_gl_state: current color and depth state stored");
00197
00198 glMatrixMode( GL_PROJECTION );
00199 glPushMatrix();
00200 glMatrixMode( GL_MODELVIEW );
00201 glPushMatrix();
00202 gl::gl_check_errors("store_gl_state: current projection and modelview matrices stored");
00203 }
00207 void restore_gl_state()
00208 {
00209 gl::gl_check_errors("restore_gl_state: called");
00210
00211 glMatrixMode( GL_PROJECTION );
00212 glPopMatrix();
00213 glMatrixMode( GL_MODELVIEW );
00214 glPopMatrix();
00215 gl::gl_check_errors("restore_gl_state: projection and modelview matrices restored");
00216
00217 glClearDepth( m_state_depth_clear_value );
00218 glDepthFunc( m_state_depth_func );
00219 if ( !m_state_depth_test )
00220 glDisable( GL_DEPTH_TEST );
00221 glClearColor( m_state_color_clear_value[0],m_state_color_clear_value[1],m_state_color_clear_value[2],m_state_color_clear_value[3] );
00222 gl::gl_check_errors("restore_gl_state: depth and clear color restored");
00223
00224 glDrawBuffer(m_state_current_drawbuf);
00225 gl::gl_check_errors("restore_gl_state: back to current drawbuf");
00226
00227 glViewport(m_state_viewport[0], m_state_viewport[1], m_state_viewport[2], m_state_viewport[3]);
00228 gl::gl_check_errors("restore_gl_state: viewport restored");
00229 }
00230
00231 template<typename grid_type>
00232 bool init_rendering(grid_type const & phi, bool use_unsigned)
00233 {
00234 gl::gl_check_errors("init_rendering: called");
00235 if(!OpenTissue::gl::is_framebuffer_object_supported())
00236 return false;
00237 if(!OpenTissue::gl::is_float_texture_supported())
00238 return false;
00239 if(!OpenTissue::cg::startup())
00240 return false;
00241 store_gl_state();
00242 std::string filename;
00243 if(use_unsigned)
00244 {
00245 filename = opentissue_path + "/OpenTissue/core/geometry/t4_gpu_scan/fp_t4gpu_unsigned.cg";
00246 }
00247 else
00248 {
00249 filename = opentissue_path + "/OpenTissue/core/geometry/t4_gpu_scan/fp_t4gpu_faster.cg";
00250 }
00251 m_fragment_program.load_from_file(cg::Program::fragment_program, filename);
00252 gl::gl_check_errors("init_fragment_program: program loaded");
00253 init_fbo(phi);
00254 m_fragment_program.enable();
00255 return true;
00256 }
00257
00258 void cleanup_rendering()
00259 {
00260 gl::gl_check_errors("cleanup_rendering: called");
00261
00262 disable_fbo();
00263 m_fragment_program.disable();
00264 OpenTissue::cg::shutdown();
00265 restore_gl_state();
00266 }
00267
00282 template<typename surface_mesh, typename point_container,typename volume_mesh, typename grid_type>
00283 void init(
00284 surface_mesh & surface
00285 , volume_mesh const & shell
00286 , point_container const & points
00287 , grid_type const & phi
00288 , point_container & edge_normals
00289 , bool use_unsigned
00290 )
00291 {
00292
00293 m_min_z_value = phi.min_coord(2);
00294 m_max_z_value = phi.max_coord(2);
00295 m_z_value = m_min_z_value;
00296
00297 m_delta_z_value = phi.dz();
00298
00299
00300 m_status.clear();
00301 m_events.clear();
00302
00303 typename volume_mesh::tetrahedron_iterator begin = shell.tetrahedron_begin();
00304 typename volume_mesh::tetrahedron_iterator end = shell.tetrahedron_end();
00305 typename volume_mesh::tetrahedron_iterator T;
00306 for (T = begin; T != end; ++T)
00307 {
00308 real_type z_min = std::min( points[T->i()->idx()](2), std::min( points[T->j()->idx()](2), std::min( points[T->k()->idx()](2) , points[T->m()->idx()](2) )));
00309 real_type z_max = std::max( points[T->i()->idx()](2), std::max( points[T->j()->idx()](2), std::max( points[T->k()->idx()](2) , points[T->m()->idx()](2) )));
00310 m_events.push_back(event_type(T->idx(),z_min,z_max));
00311 }
00312 std::sort( m_events.begin(), m_events.end() );
00313 m_last_event = m_events.begin();
00314
00315 if(!use_unsigned)
00316 {
00317
00318 point_container face_normals;
00319 face_normals.resize(surface.size_faces());
00320 typename surface_mesh::face_iterator f_end = surface.face_end();
00321 typename surface_mesh::face_iterator f = surface.face_begin();
00322 for(unsigned int i = 0;f!=f_end;++f,++i)
00323 {
00324 f->m_tag = i;
00325 compute_face_normal(*f, face_normals[i]);
00326 }
00327
00328 edge_normals.resize(surface.size_edges());
00329 typename surface_mesh::edge_iterator e_end = surface.edge_end();
00330 typename surface_mesh::edge_iterator e = surface.edge_begin();
00331 for(unsigned int i = 0;e!=e_end;++e,++i)
00332 {
00333 e->m_tag = i;
00334 edge_normals[i].clear();
00335 typename surface_mesh::face_type * f0=0,*f1=0;
00336 if(! e->get_halfedge0_iterator()->get_face_handle().is_null())
00337 {
00338 f0 = &(*e->get_halfedge0_iterator()->get_face_iterator());
00339 edge_normals[i] += face_normals[f0->m_tag];
00340 }
00341 if(! e->get_halfedge1_iterator()->get_face_handle().is_null())
00342 {
00343 f1 = &(*e->get_halfedge1_iterator()->get_face_iterator());
00344 edge_normals[i] += face_normals[f1->m_tag];
00345 }
00346 edge_normals[i] = unit( edge_normals[i] );
00347 }
00348 }
00349 }
00350
00359 void update_status_set(real_type const & z)
00360 {
00361 if( m_events.empty() )
00362 return;
00363 m_status.clear();
00364
00365
00366
00367
00368
00369
00370
00371 event_iterator begin = m_last_event;
00372 event_iterator end = m_events.end();
00373 event_iterator event;
00374 for ( event=begin; event!=end; ++event )
00375 {
00376 if( event->m_z_min <= z && z <= event->m_z_max )
00377 m_status.push_back( (*event) );
00378 if( event->m_z_min > z )
00379 break;
00380 }
00381 for ( ; m_last_event!=event && m_last_event->m_z_max < z; ++m_last_event )
00382 ;
00383 }
00384
00403 template< typename volume_mesh, typename lut_container, typename point_container >
00404 void draw_slice(
00405 volume_mesh const & shell
00406 , lut_container & lut
00407 , point_container const & points
00408 , real_type const & z
00409 , point_container & edge_normals
00410 )
00411 {
00412 typedef typename lut_container::value_type face_ptr_type;
00413 typedef typename boost::remove_pointer<face_ptr_type>::type face_type;
00414
00415 typedef typename face_type::mesh_type surface_mesh;
00416 typedef typename surface_mesh::face_vertex_circulator face_vertex_circulator;
00417
00418 typedef typename surface_mesh::math_types math_types;
00419 typedef typename math_types::vector3_type vector3_type;
00420
00421
00422 gl::gl_check_errors("draw_slice: called");
00423 static geometry::LocalTriangleFrame<vector3_type> local_frame;
00424 static vector3_type slice[4];
00425
00426 event_iterator begin = m_status.begin();
00427 event_iterator end = m_status.end();
00428 event_iterator event;
00429
00430 typename volume_mesh::tetrahedron_iterator T;
00431 typename volume_mesh::node_iterator i;
00432 typename volume_mesh::node_iterator j;
00433 typename volume_mesh::node_iterator k;
00434 typename volume_mesh::node_iterator m;
00435 typename surface_mesh::face_type * face;
00436 unsigned int cnt;
00437 real_type e10x;
00438 real_type e10y;
00439 real_type e21x;
00440 real_type e21y;
00441 vector3_type nv0;
00442 vector3_type nv1;
00443 vector3_type nv2;
00444 vector3_type ne0;
00445 vector3_type ne1;
00446 vector3_type ne2;
00447 vector3_type local;
00448 for ( event = begin; event!=end; ++event )
00449 {
00450 T = shell.tetrahedron(event->m_idx);
00451 i = T->i();
00452 j = T->j();
00453 k = T->k();
00454 m = T->m();
00455
00456 face = lut[event->m_idx];
00457 assert(valency(*face)==3 || !"Only triangular faces are supported!");
00458
00459 typename surface_mesh::face_vertex_circulator v(*face);
00460 vector3_type & p0 = v->m_coord; ++v;
00461 vector3_type & p1 = v->m_coord; ++v;
00462 vector3_type & p2 = v->m_coord;
00463
00464 local_frame.init(p0,p1,p2);
00465
00466 OpenTissue::geometry::ZTetrahedronSlicer<vector3_type> slicer(
00467 points[i->idx()]
00468 , points[j->idx()]
00469 , points[k->idx()]
00470 , points[m->idx()]
00471 );
00472
00473 cnt = slicer.intersect(z,slice);
00474
00475 e10x = slice[1](0)-slice[0](0);
00476 e10y = slice[1](1)-slice[0](1);
00477 e21x = slice[2](0)-slice[1](0);
00478 e21y = slice[2](1)-slice[1](1);
00479 bool flip = false;
00480 if ( (e10x*e21y-e21x*e10y)<=0)
00481 flip = true;
00482
00483 {
00484 typename surface_mesh::face_halfedge_circulator nh(*face);
00485 nv0 = (nh->get_origin_iterator()->m_normal);
00486 ne0 = edge_normals[nh->get_edge_iterator()->m_tag];
00487 ++nh;
00488 nv1 = (nh->get_origin_iterator()->m_normal);
00489 ne1 = edge_normals[nh->get_edge_iterator()->m_tag];
00490 ++nh;
00491 nv2 = (nh->get_origin_iterator()->m_normal);
00492 ne2 = edge_normals[nh->get_edge_iterator()->m_tag];
00493 local_frame.compute_local_normals(nv0,nv1,nv2,ne0,ne1,ne2);
00494 }
00495
00496 glBegin(GL_POLYGON);
00497 for(unsigned int i=0;i<cnt;++i)
00498 {
00499 unsigned int j = i;
00500 if(flip)
00501 j = cnt - 1 - i;
00502 local = local_frame.get_local_coord(slice[j]);
00503 glNormal3f( 0, 0, 1 );
00504 glMultiTexCoord3f( GL_TEXTURE0, local(0), local(1), local(2) );
00505 glMultiTexCoord3f( GL_TEXTURE1, local_frame.a(), local_frame.b(), local_frame.h() );
00506 glMultiTexCoord3f( GL_TEXTURE2, local_frame.nv0()(0), local_frame.nv0()(1), local_frame.nv0()(2) );
00507 glMultiTexCoord3f( GL_TEXTURE3, local_frame.nv1()(0), local_frame.nv1()(1), local_frame.nv1()(2) );
00508 glMultiTexCoord3f( GL_TEXTURE4, local_frame.nv2()(0), local_frame.nv2()(1), local_frame.nv2()(2) );
00509 glMultiTexCoord3f( GL_TEXTURE5, local_frame.ne0()(0), local_frame.ne0()(1), local_frame.ne0()(2) );
00510 glMultiTexCoord3f( GL_TEXTURE6, local_frame.ne1()(0), local_frame.ne1()(1), local_frame.ne1()(2) );
00511 glMultiTexCoord3f( GL_TEXTURE7, local_frame.ne2()(0), local_frame.ne2()(1), local_frame.ne2()(2) );
00512 glVertex3f( slice[j](0), slice[j](1), slice[j](2) );
00513 }
00514 glEnd();
00515 gl::gl_check_errors("draw_slice: polygon has been drawn");
00516 }
00517 }
00518
00519
00520 template< typename volume_mesh, typename lut_container, typename point_container >
00521 void draw_slice_unsigned(
00522 volume_mesh const & shell
00523 , lut_container & lut
00524 , point_container const & points
00525 , real_type const & z
00526 )
00527 {
00528 typedef typename lut_container::value_type face_ptr_type;
00529 typedef typename boost::remove_pointer<face_ptr_type>::type face_type;
00530
00531 typedef typename face_type::mesh_type surface_mesh;
00532 typedef typename surface_mesh::face_vertex_circulator face_vertex_circulator;
00533
00534 typedef typename surface_mesh::math_types math_types;
00535 typedef typename math_types::vector3_type vector3_type;
00536
00537
00538 gl::gl_check_errors("draw_slice_unsigned: called");
00539 static geometry::LocalTriangleFrame<vector3_type> local_frame;
00540 static vector3_type slice[4];
00541
00542 event_iterator begin = m_status.begin();
00543 event_iterator end = m_status.end();
00544 event_iterator event;
00545
00546 typename volume_mesh::tetrahedron_iterator T;
00547 typename volume_mesh::node_iterator i;
00548 typename volume_mesh::node_iterator j;
00549 typename volume_mesh::node_iterator k;
00550 typename volume_mesh::node_iterator m;
00551 typename surface_mesh::face_type * face;
00552 unsigned int cnt;
00553 real_type e10x;
00554 real_type e10y;
00555 real_type e21x;
00556 real_type e21y;
00557 vector3_type local;
00558 for ( event = begin; event!=end; ++event )
00559 {
00560 T = shell.tetrahedron(event->m_idx);
00561 i = T->i();
00562 j = T->j();
00563 k = T->k();
00564 m = T->m();
00565
00566 face = lut[event->m_idx];
00567 assert(valency(*face)==3 || !"Only triangular faces are supported!");
00568
00569 typename surface_mesh::face_vertex_circulator v(*face);
00570 vector3_type & p0 = v->m_coord; ++v;
00571 vector3_type & p1 = v->m_coord; ++v;
00572 vector3_type & p2 = v->m_coord;
00573
00574 local_frame.init(p0,p1,p2);
00575
00576 OpenTissue::geometry::ZTetrahedronSlicer<vector3_type> slicer(
00577 points[i->idx()]
00578 , points[j->idx()]
00579 , points[k->idx()]
00580 , points[m->idx()]
00581 );
00582
00583 cnt = slicer.intersect(z,slice);
00584
00585 e10x = slice[1](0)-slice[0](0);
00586 e10y = slice[1](1)-slice[0](1);
00587 e21x = slice[2](0)-slice[1](0);
00588 e21y = slice[2](1)-slice[1](1);
00589 bool flip = false;
00590 if ( (e10x*e21y-e21x*e10y)<=0)
00591 flip = true;
00592
00593
00594 glBegin(GL_POLYGON);
00595 for(unsigned int i=0;i<cnt;++i)
00596 {
00597 unsigned int j = i;
00598 if(flip)
00599 j = cnt - 1 - i;
00600 local = local_frame.get_local_coord(slice[j]);
00601 glNormal3f( 0, 0, 1 );
00602 glMultiTexCoord3f( GL_TEXTURE0, local(0), local(1), local(2) );
00603 glMultiTexCoord3f( GL_TEXTURE1, local_frame.a(), local_frame.b(), local_frame.h() );
00604 glVertex3f( slice[j](0), slice[j](1), slice[j](2) );
00605 }
00606 glEnd();
00607 gl::gl_check_errors("draw_slice_unsigned: polygon has been drawn");
00608 }
00609 }
00610
00611
00612 public:
00613
00634 template<typename surface_mesh,typename volume_mesh,typename lut_container, typename point_container,typename grid_type>
00635 bool run(
00636 surface_mesh & surface
00637 , volume_mesh const & shell
00638 , lut_container & lut
00639 , point_container const & points
00640 , real_type const & thickness
00641 , grid_type & phi
00642 , bool use_unsigned
00643 )
00644 {
00645 point_container edge_normals;
00646
00647 m_thickness = thickness;
00648
00649 init(surface,shell,points,phi,edge_normals,use_unsigned);
00650
00651 if(!init_rendering(phi,use_unsigned))
00652 return false;
00653
00654 m_fragment_program.set_float_param( "narrowband", m_thickness );
00655
00656 update_status_set(m_z_value);
00657 unsigned int current = 0;
00658 gl::gl_check_errors("init_rendering: fbo bound");
00659 OpenTissue::gl::ColorPicker(1.0,0.0,0.0);
00660 for(unsigned int k=0; k<phi.K(); ++k)
00661 {
00662 gl::gl_check_errors("run: init loop");
00663 unsigned int next = (current+1)%2;
00664 m_fbo[current].bind();
00665 glClear( GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT );
00666 gl::gl_check_errors("run: buffer cleared");
00667
00668 if(use_unsigned)
00669 draw_slice_unsigned(shell, lut, points, m_z_value);
00670 else
00671 draw_slice(shell, lut, points, m_z_value,edge_normals);
00672
00673
00674 float * zplane = phi.data() + k * phi.I()*phi.J();
00675 glReadPixels( 0, 0, phi.I(), phi.J(), GL_RED, GL_FLOAT, zplane );
00676 gl::gl_check_errors("run: texture readback");
00677 m_z_value += m_delta_z_value;
00678 update_status_set(m_z_value);
00679 current = next;
00680 }
00681 cleanup_rendering();
00682 return true;
00683 }
00684 };
00685
00686 }
00687
00688
00689 struct t4_gpu_unsigned {};
00690 struct t4_gpu_signed {};
00691
00704 template<typename surface_mesh, typename grid_type>
00705 inline bool t4_gpu_scan(
00706 surface_mesh & surface
00707 , double const & thickness
00708 , grid_type & phi
00709 )
00710 {
00711 return t4_gpu_scan( surface, thickness, phi, t4_gpu_signed() );
00712 }
00713
00714
00720 template<typename surface_mesh, typename grid_type>
00721 inline bool t4_gpu_scan(
00722 surface_mesh & surface
00723 , double const & thickness
00724 , grid_type & phi
00725 , t4_gpu_signed const &
00726 )
00727 {
00728 typedef double real_type;
00729 typedef OpenTissue::math::Vector3<real_type> vector3_type;
00730 typedef OpenTissue::t4mesh::T4Mesh<> volume_mesh;
00731 typedef std::vector< typename surface_mesh::face_type * > lut_container;
00732 typedef std::vector< vector3_type > point_container;
00733
00734 point_container points;
00735 volume_mesh shell;
00736 lut_container lut;
00737
00738 detail::T4GPUScan<real_type> calculator;
00739
00740 OpenTissue::mesh::compute_angle_weighted_vertex_normals(surface);
00741
00742 detail::compute_obb_shell(surface,thickness,shell,points,lut);
00743
00744 return calculator.run(surface,shell,lut,points,thickness,phi,false);
00745 }
00746
00752 template<typename surface_mesh, typename grid_type>
00753 inline bool t4_gpu_scan(
00754 surface_mesh & surface
00755 , double const & thickness
00756 , grid_type & phi
00757 , t4_gpu_unsigned const &
00758 )
00759 {
00760 typedef double real_type;
00761 typedef OpenTissue::math::Vector3<real_type> vector3_type;
00762 typedef OpenTissue::t4mesh::T4Mesh<> volume_mesh;
00763 typedef std::vector< typename surface_mesh::face_type * > lut_container;
00764 typedef std::vector< vector3_type > point_container;
00765
00766 point_container points;
00767 volume_mesh shell;
00768 lut_container lut;
00769
00770 detail::T4GPUScan<real_type> calculator;
00771 detail::compute_obb_shell(surface,thickness,shell,points,lut);
00772 return calculator.run(surface,shell,lut,points,thickness,phi,true);
00773 }
00774
00775
00776
00777
00778
00779 }
00780
00781
00782 #endif