00001 #ifndef OPENTISSUE_UTILITY_GL_GL_DRAW_MESH_H
00002 #define OPENTISSUE_UTILITY_GL_GL_DRAW_MESH_H
00003
00004
00005
00006
00007
00008
00009
00010 #include <OpenTissue/configuration.h>
00011
00012 #include <OpenTissue/utility/gl/gl_util.h>
00013
00014 namespace OpenTissue
00015 {
00016
00017 namespace gl
00018 {
00019
00029 template<typename mesh_type>
00030 class MeshDrawArray
00031 {
00032 protected:
00033
00034 typedef typename mesh_type::vertex_traits vertex_data;
00035 typedef typename mesh_type::math_types::vector3_type vector3_type;
00036 typedef typename mesh_type::math_types::real_type real_type;
00037
00038 vertex_data * m_data;
00039 unsigned int * m_indices;
00040 std::size_t m_count;
00041
00042 public:
00043
00044 MeshDrawArray()
00045 : m_data(0)
00046 , m_indices(0)
00047 , m_count(0)
00048 { }
00049
00050 MeshDrawArray(mesh_type const & mesh)
00051 {
00052
00053
00054
00055 {
00056 m_data = new vertex_data[mesh.size_vertices()];
00057 typename mesh_type::const_vertex_iterator end = mesh.vertex_end();
00058 typename mesh_type::const_vertex_iterator v = mesh.vertex_begin();
00059 vertex_data * data = m_data;
00060 for(;v!=end;++v,++data)
00061 {
00062
00063 (*data).m_coord = v->m_coord;
00064 (*data).m_normal = v->m_normal;
00065 (*data).m_u = v->m_u;
00066 (*data).m_v = v->m_v;
00067 (*data).m_color = v->m_color;
00068
00069 }
00070 }
00071
00072
00073
00074
00075
00076 {
00077 m_count = 3*mesh.size_faces();
00078 m_indices = new unsigned int[m_count];
00079 typename mesh_type::const_face_iterator end = mesh.face_end();
00080 typename mesh_type::const_face_iterator f = mesh.face_begin();
00081 unsigned int * indices = m_indices;
00082 for(;f!=end;++f)
00083 {
00084 assert(valency(*f)==3 || !"Only triangles are supported");
00085 typename mesh_type::const_face_vertex_circulator v( *f );
00086
00087 *indices = static_cast<unsigned int>( v->get_handle().get_idx() );
00088 ++indices;
00089 ++v;
00090
00091 *indices = static_cast<unsigned int>( v->get_handle().get_idx() );
00092 ++indices;
00093 ++v;
00094
00095 *indices = static_cast<unsigned int>( v->get_handle().get_idx() );
00096 ++indices;
00097 ++v;
00098 }
00099 }
00100 }
00101
00102 ~MeshDrawArray()
00103 {
00104 if(m_data)
00105 delete [] m_data;
00106 if(m_indices)
00107 delete [] m_indices;
00108 };
00109
00110 public:
00111
00112 void operator()()const
00113 {
00114 if(m_count==0) return;
00115
00116 assert(m_data || !"No data to show?");
00117 assert(m_indices || !"No data to show?");
00118 assert(m_count || !"No data to show?");
00119
00120 glEnableClientState(GL_VERTEX_ARRAY);
00121 glEnableClientState(GL_NORMAL_ARRAY);
00122 glEnableClientState(GL_TEXTURE_COORD_ARRAY);
00123 glEnableClientState(GL_COLOR_ARRAY );
00124
00125 GLvoid * ptr_coord = m_data;
00126 GLvoid * ptr_normal = &(m_data->m_normal);
00127 GLvoid * ptr_tex = &(m_data->m_u);
00128 GLvoid * ptr_color = &(m_data->m_color);
00129
00130 GLsizei stride = sizeof(vertex_data);
00131
00132 unsigned int real_size = sizeof(real_type);
00133 switch(real_size)
00134 {
00135 case 4:
00136 glVertexPointer ( 3, GL_FLOAT, stride, ptr_coord );
00137 glNormalPointer ( GL_FLOAT, stride, ptr_normal );
00138 glTexCoordPointer( 2, GL_FLOAT, stride, ptr_tex );
00139 glColorPointer ( 3, GL_FLOAT, stride, ptr_color );
00140 break;
00141 case 8:
00142 glVertexPointer ( 3, GL_DOUBLE, stride, ptr_coord );
00143 glNormalPointer ( GL_DOUBLE, stride, ptr_normal );
00144 glTexCoordPointer( 2, GL_DOUBLE, stride, ptr_tex );
00145 glColorPointer ( 3, GL_DOUBLE, stride, ptr_color );
00146 break;
00147 default:
00148 assert(!"Could not deduce data type");
00149 break;
00150 };
00151
00152 glDrawElements(GL_TRIANGLES, (GLsizei)m_count, GL_UNSIGNED_INT, m_indices);
00153
00154 glDisableClientState(GL_NORMAL_ARRAY);
00155 glDisableClientState(GL_VERTEX_ARRAY);
00156 glDisableClientState(GL_TEXTURE_COORD_ARRAY);
00157 glDisableClientState(GL_COLOR_ARRAY );
00158 }
00159 };
00160
00161
00170 template<typename face_type>
00171 inline void DrawMeshFace(face_type const & face, bool wireframe = false, bool use_colors = true, bool use_normals = true, bool use_texcoords = true)
00172 {
00173 glBegin(wireframe ? GL_LINE_LOOP : GL_POLYGON);
00174 typename face_type::mesh_type::const_face_vertex_circulator v(face), vend;
00175 for(; v != vend; ++v)
00176 {
00177 if(use_normals)
00178 {
00179 glNormal3f( (GLfloat) v->m_normal(0), (GLfloat)v->m_normal(1), (GLfloat)v->m_normal(2) );
00180 }
00181 if(use_texcoords)
00182 {
00183 glTexCoord2f( (GLfloat) v->m_u, (GLfloat)v->m_v );
00184 }
00185 if(use_colors)
00186 {
00187 glColor3f( (GLfloat) v->m_color(0), (GLfloat)v->m_color(1), (GLfloat)v->m_color(2) );
00188 }
00189 glVertex3f ( (GLfloat) v->m_coord(0), (GLfloat)v->m_coord(1), (GLfloat)v->m_coord(2) );
00190 }
00191 glEnd();
00192 }
00193
00194
00203 template<typename mesh_type>
00204 inline void DrawMesh(mesh_type const & mesh, unsigned int mode = GL_POLYGON, bool use_colors = true, bool use_normals = true, bool use_texcoords = true)
00205 {
00206 assert(mode==GL_POLYGON || mode==GL_LINE_LOOP || !"Illegal opengl mode");
00207 typename mesh_type::const_face_iterator fend = mesh.face_end();
00208 typename mesh_type::const_face_iterator f = mesh.face_begin();
00209
00210 for(;f!=fend;++f)
00211 {
00212 DrawMeshFace(*f, mode == GL_LINE_LOOP, use_colors, use_normals, use_texcoords);
00213 }
00214 }
00215
00216
00217 template<typename mesh_type>
00218 inline void DrawSkinMesh(mesh_type const & mesh, unsigned int mode = GL_POLYGON )
00219 {
00220 assert(mode==GL_POLYGON || mode==GL_LINE_LOOP || !"Illegal opengl mode");
00221
00222 typedef typename mesh_type::math_types::real_type real_type;
00223
00224 typename mesh_type::const_face_iterator fend = mesh.face_end();
00225 typename mesh_type::const_face_iterator f = mesh.face_begin();
00226
00227 for(;f!=fend;++f)
00228 {
00229 typename mesh_type::const_face_vertex_circulator v(*f),vend;
00230 glBegin(mode);
00231
00232 for(;v!=vend;++v)
00233 {
00234
00235
00236
00237
00238 real_type weights[] = { 0, 0, 0, 0 };
00239 size_t bones[] = { 0, 0, 0, 0 };
00240
00241
00242 assert( v->m_influences < 5 || !"Only up to 4 bone influces is supported by GPU skinning!" );
00243 for(int i= 0; i < v->m_influences; ++i)
00244 {
00245 weights[i] = v->m_weight[i];
00246 bones[i] = v->m_bone[i];
00247
00248
00249 }
00250
00251
00252
00253 glColor4f( weights[0], weights[1], weights[2], weights[3] );
00254
00255
00256 glTexCoord4f( bones[0], bones[1], bones[2], bones[3] );
00257
00258
00259
00260
00261
00262
00263
00264
00265 glNormal3f( (GLfloat) v->m_normal(0), (GLfloat)v->m_normal(1), (GLfloat)v->m_normal(2) );
00266 glVertex3f ( (GLfloat) v->m_coord(0), (GLfloat)v->m_coord(1), (GLfloat)v->m_coord(2) );
00267
00268
00269 }
00270
00271 glEnd();
00272 }
00273 }
00274
00285 template<typename mesh_type>
00286 class MeshDrawDisplayLists
00287 {
00288 protected:
00289
00290 GLuint m_lists;
00291 GLuint m_range;
00292
00293 private:
00294
00295 void create_display_list(mesh_type const & mesh, unsigned int mode = GL_POLYGON, bool use_colors = true, bool use_normals = true, bool use_texcoords = true)
00296 {
00297 using std::ceil;
00298 assert(mode==GL_POLYGON || mode==GL_LINE_LOOP || !"Illegal opengl mode");
00299
00300 unsigned int total_count = static_cast<unsigned int>( mesh.size_faces() );
00301 if(total_count == 0)
00302 {
00303 m_range = m_lists = 0u;
00304 return;
00305 }
00306 unsigned int list_count = std::min( total_count, 50000u );
00307 m_range = static_cast<int>( ceil( total_count / static_cast<float>( list_count ) ) );
00308 unsigned int count_left = total_count;
00309 m_lists = glGenLists( m_range );
00310
00311 typename mesh_type::const_face_iterator f = mesh.face_begin();
00312 for ( GLuint number = 0; number < m_range; ++number )
00313 {
00314 glNewList( m_lists + number, GL_COMPILE );
00315 unsigned int count = std::min(count_left,list_count);
00316 for ( unsigned int i = 0; i < count; ++i, ++f )
00317 {
00318 typename mesh_type::const_face_vertex_circulator v(*f),vend;
00319 glBegin(mode);
00320 for(;v!=vend;++v)
00321 {
00322 if(use_normals)
00323 glNormal3f ( (GLfloat) v->m_normal(0), (GLfloat)v->m_normal(1), (GLfloat)v->m_normal(2) );
00324 if(use_texcoords)
00325 glTexCoord2f( (GLfloat) v->m_u , (GLfloat)v->m_v );
00326 if(use_colors)
00327 glColor3f ( (GLfloat) v->m_color(0) , (GLfloat)v->m_color(1) , (GLfloat)v->m_color(2) );
00328 glVertex3f ( (GLfloat) v->m_coord(0) , (GLfloat) v->m_coord(1) , (GLfloat) v->m_coord(2) );
00329 }
00330 glEnd();
00331 }
00332 count_left -= count;
00333 glEndList();
00334 }
00335 };
00336
00337 void delete_display_lists()
00338 {
00339 if ( m_lists )
00340 glDeleteLists( m_lists, m_range );
00341 m_lists = 0;
00342 m_range = 0;
00343 };
00344
00345 void call_display_lists()
00346 {
00347 for ( GLuint number = 0; number < m_range; ++number )
00348 glCallList( m_lists + number );
00349 };
00350
00351 public:
00352
00353 MeshDrawDisplayLists()
00354 : m_lists(0)
00355 , m_range (0)
00356 {};
00357
00358 MeshDrawDisplayLists(mesh_type const & mesh, unsigned int mode = GL_POLYGON, bool use_colors = true, bool use_normals = true, bool use_texcoords = true)
00359 {
00360 create_display_list(mesh,mode,use_colors,use_normals,use_texcoords);
00361 };
00362
00363 ~MeshDrawDisplayLists(){delete_display_lists();};
00364
00365 public:
00366
00367 void operator()(){ call_display_lists(); };
00368 };
00369
00370 }
00371
00372 }
00373
00374
00375 #endif