Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #ifndef __VCGLIB_GLU_TESSELATOR_H
00024 #define __VCGLIB_GLU_TESSELATOR_H
00025 #include <vcg/space/point2.h>
00026 #include <vector>
00027
00028 #ifndef GL_VERSION_1_1
00029 #error "Please include OpenGL before including this file"
00030 #endif
00031
00032
00033
00034 #ifndef GLU_VERSIONS
00035 #ifdef __APPLE__
00036 #include <OpenGL/glu.h>
00037 #else
00038 #ifdef _WIN32
00039 #include <windows.h>
00040 #endif
00041 #include <GL/glu.h>
00042 #endif
00043 #endif
00044
00045 #ifndef CALLBACK
00046 #ifdef _WIN32
00047 #define CALLBACK __stdcall
00048 #else
00049 #define CALLBACK
00050 #endif
00051 #endif
00052
00053 namespace vcg
00054 {
00055
00056 class glu_tesselator
00057 {
00058 public:
00059
00060 typedef glu_tesselator this_type;
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098 template <class point_type>
00099 static inline void unroll(const std::vector< std::vector<point_type> > & outlines, std::vector<point_type> & points)
00100 {
00101 for (size_t i=0; i<outlines.size(); ++i)
00102 {
00103 for (size_t j=0; j<outlines[i].size(); ++j)
00104 {
00105 points.push_back(outlines[i][j]);
00106 }
00107 }
00108 }
00109
00110 template <class point_type>
00111 static inline void tesselate(const std::vector< std::vector<point_type> > & outlines, std::vector<int> & indices)
00112 {
00113 tess_prim_data_vec t_data;
00114
00115 this_type::do_tesselation(outlines, t_data);
00116
00117
00118 for (size_t i=0; i<t_data.size(); ++i)
00119 {
00120 const size_t st = t_data[i].indices.size();
00121 if (st < 3) continue;
00122
00123 switch (t_data[i].type)
00124 {
00125 case GL_TRIANGLES:
00126 for (size_t j=0; j<st; ++j)
00127 {
00128 indices.push_back(t_data[i].indices[j]);
00129 }
00130 break;
00131
00132 case GL_TRIANGLE_STRIP:
00133 {
00134 int i0 = t_data[i].indices[0];
00135 int i1 = t_data[i].indices[1];
00136
00137 bool ccw = true;
00138
00139 for (size_t j=2; j<st; ++j)
00140 {
00141 const int i2 = t_data[i].indices[j];
00142
00143 indices.push_back(i0);
00144 indices.push_back(i1);
00145 indices.push_back(i2);
00146
00147 if (ccw) i0 = i2;
00148 else i1 = i2;
00149
00150 ccw = !ccw;
00151 } }
00152 break;
00153
00154 case GL_TRIANGLE_FAN:
00155 {
00156 const int first = t_data[i].indices[0];
00157 int prev = t_data[i].indices[1];
00158
00159 for (size_t j=2; j<st; ++j)
00160 {
00161 const int curr = t_data[i].indices[j];
00162
00163 indices.push_back(first);
00164 indices.push_back(prev);
00165 indices.push_back(curr);
00166
00167 prev = curr;
00168 }
00169 }
00170 break;
00171
00172 default:
00173 break;
00174 }
00175 }
00176 }
00177
00178 protected:
00179
00180 class tess_prim_data
00181 {
00182 public:
00183
00184 typedef tess_prim_data this_type;
00185
00186 GLenum type;
00187 std::vector<int> indices;
00188
00189 tess_prim_data(void) { }
00190 tess_prim_data(GLenum t) : type(t) { }
00191 };
00192
00193 typedef std::vector<tess_prim_data> tess_prim_data_vec;
00194
00195 static void CALLBACK begin_cb(GLenum type, void * polygon_data)
00196 {
00197 tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data;
00198 t_data->push_back(tess_prim_data(type));
00199 }
00200
00201 static void CALLBACK end_cb(void * polygon_data)
00202 {
00203 (void)polygon_data;
00204 }
00205
00206 static void CALLBACK vertex_cb(void * vertex_data, void * polygon_data)
00207 {
00208 tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data;
00209 t_data->back().indices.push_back((int)((size_t)vertex_data));
00210 }
00211
00212 template <class point_type>
00213 static void do_tesselation(const std::vector< std::vector<point_type> > & outlines, tess_prim_data_vec & t_data)
00214 {
00215 GLUtesselator * tess = gluNewTess();
00216
00217
00218
00219
00220
00221 gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)())(this_type::begin_cb));
00222 gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)())(this_type::end_cb));
00223 gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)())(this_type::vertex_cb));
00224
00225 void * polygon_data = (void *)(&t_data);
00226
00227 GLdouble vertex[3];
00228
00229 size_t k = 0;
00230 gluTessBeginPolygon(tess, polygon_data);
00231 for (size_t i=0; i<outlines.size(); ++i)
00232 {
00233 gluTessBeginContour(tess);
00234 for (size_t j=0; j<outlines[i].size(); ++j)
00235 {
00236 this_type::get_position(outlines[i][j], vertex);
00237 gluTessVertex(tess, vertex, (void *)k);
00238 ++k;
00239 }
00240 gluTessEndContour(tess);
00241 }
00242 gluTessEndPolygon(tess);
00243
00244 gluDeleteTess(tess);
00245 }
00246
00247 template <class scalar_type>
00248 static inline void get_position(const vcg::Point2<scalar_type> & p, GLdouble * d)
00249 {
00250 d[0] = (GLdouble)(p[0]);
00251 d[1] = (GLdouble)(p[1]);
00252 d[2] = (GLdouble)(0);
00253 }
00254
00255 template <class scalar_type>
00256 static inline void get_position(const vcg::Point3<scalar_type> & p, GLdouble * d)
00257 {
00258 d[0] = (GLdouble)(p[0]);
00259 d[1] = (GLdouble)(p[1]);
00260 d[2] = (GLdouble)(p[2]);
00261 }
00262 };
00263
00264 }
00265
00266 #endif // __VCGLIB_GLU_TESSELATOR_H