/**************************************************************************** * VCGLib o o * * Visual and Computer Graphics Library o o * * _ O _ * * Copyright(C) 2004 \/)\/ * * Visual Computing Lab /\/| * * ISTI - Italian National Research Council | * * \ * * All rights reserved. * * * * This program is free software; you can redistribute it and/or modify * * it under the terms of the GNU General Public License as published by * * the Free Software Foundation; either version 2 of the License, or * * (at your option) any later version. * * * * This program is distributed in the hope that it will be useful, * * but WITHOUT ANY WARRANTY; without even the implied warranty of * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * * for more details. * * * ****************************************************************************/ /**************************************************************************** History $Log: not supported by cvs2svn $ Revision 1.4 2007/12/01 18:09:14 m_di_benedetto Added cast to prevent pointer truncation warning/error messages. Revision 1.3 2007/08/28 05:43:56 cignoni Added ifdef needed for mac gcc compilation Revision 1.2 2007/08/25 08:43:33 cignoni moved here callback def and added some needed opengl related casts Revision 1.1 2007/05/14 22:23:36 m_di_benedetto First Commit. ****************************************************************************/ #ifndef __VCGLIB_GLU_TESSELATOR_H #define __VCGLIB_GLU_TESSELATOR_H #include <vector> //#include <GL/glu.h> #ifndef CALLBACK #ifdef WIN32 #define CALLBACK __stdcall #else #define CALLBACK #endif #endif namespace vcg { class glu_tesselator { public: typedef glu_tesselator this_type; /* Works with Point2 and Point3; sample usage: // tesselation input: each outline represents a polygon contour std::vector< std::vector<point_type> > outlines = ...; // tesselation output (triangles indices) std::vector<int> indices; // compute triangles indices glu_tesselator::tesselate(outlines, indices); // unroll input contours points std::vector<point_type> points; for (size_t i=0; i<outlines.size(); ++i) { for (size_t j=0; j<outlines[i].size(); ++j) { points.push_back(outlines[i][j]); } } // or simply call glu_tesselator::unroll(outlines, points); // create triangles for (size_t i=0; i<indices.size(); i+=3) { create_triangle( points[ indices[i+0] ], points[ indices[i+1] ], points[ indices[i+2] ]); } */ template <class point_type> static inline void unroll(const std::vector< std::vector<point_type> > & outlines, std::vector<point_type> & points) { for (size_t i=0; i<outlines.size(); ++i) { for (size_t j=0; j<outlines[i].size(); ++j) { points.push_back(outlines[i][j]); } } } template <class point_type> static inline void tesselate(const std::vector< std::vector<point_type> > & outlines, std::vector<int> & indices) { tess_prim_data_vec t_data; this_type::do_tesselation(outlines, t_data); //int k = 0; for (size_t i=0; i<t_data.size(); ++i) { const size_t st = t_data[i].indices.size(); if (st < 3) continue; switch (t_data[i].type) { case GL_TRIANGLES: for (size_t j=0; j<st; ++j) { indices.push_back(t_data[i].indices[j]); } break; case GL_TRIANGLE_STRIP: { int i0 = t_data[i].indices[0]; int i1 = t_data[i].indices[1]; bool ccw = true; for (size_t j=2; j<st; ++j) { const int i2 = t_data[i].indices[j]; indices.push_back(i0); indices.push_back(i1); indices.push_back(i2); if (ccw) i0 = i2; else i1 = i2; ccw = !ccw; } } break; case GL_TRIANGLE_FAN: { const int first = t_data[i].indices[0]; int prev = t_data[i].indices[1]; for (size_t j=2; j<st; ++j) { const int curr = t_data[i].indices[j]; indices.push_back(first); indices.push_back(prev); indices.push_back(curr); prev = curr; } } break; default: break; } } } protected: class tess_prim_data { public: typedef tess_prim_data this_type; GLenum type; std::vector<int> indices; tess_prim_data(void) { } tess_prim_data(GLenum t) : type(t) { } }; typedef std::vector<tess_prim_data> tess_prim_data_vec; static void CALLBACK begin_cb(GLenum type, void * polygon_data) { tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; t_data->push_back(tess_prim_data(type)); } static void CALLBACK end_cb(void * polygon_data) { (void)polygon_data; } static void CALLBACK vertex_cb(void * vertex_data, void * polygon_data) { tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; t_data->back().indices.push_back((int)((size_t)vertex_data)); } template <class point_type> static void do_tesselation(const std::vector< std::vector<point_type> > & outlines, tess_prim_data_vec & t_data) { GLUtesselator * tess = gluNewTess(); #ifdef __APPLE__ gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)(...))(this_type::begin_cb)); gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)(...))(this_type::end_cb)); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)(...))(this_type::vertex_cb)); #else gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)())(this_type::begin_cb)); gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)())(this_type::end_cb)); gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)())(this_type::vertex_cb)); #endif void * polygon_data = (void *)(&t_data); GLdouble vertex[3]; int k = 0; gluTessBeginPolygon(tess, polygon_data); for (size_t i=0; i<outlines.size(); ++i) { gluTessBeginContour(tess); for (size_t j=0; j<outlines[i].size(); ++j) { this_type::get_position(outlines[i][j], vertex); gluTessVertex(tess, vertex, (void *)k); ++k; } gluTessEndContour(tess); } gluTessEndPolygon(tess); gluDeleteTess(tess); } template <class scalar_type> static inline void get_position(const vcg::Point2<scalar_type> & p, GLdouble * d) { d[0] = (GLdouble)(p[0]); d[1] = (GLdouble)(p[1]); d[2] = (GLdouble)(0); } template <class scalar_type> static inline void get_position(const vcg::Point3<scalar_type> & p, GLdouble * d) { d[0] = (GLdouble)(p[0]); d[1] = (GLdouble)(p[1]); d[2] = (GLdouble)(p[2]); } }; } // end namespace vcg #endif // __VCGLIB_GLU_TESSELATOR_H