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