1 /**************************************************************************** 2 * VCGLib o o * 3 * Visual and Computer Graphics Library o o * 4 * _ O _ * 5 * Copyright(C) 2004-2016 \/)\/ * 6 * Visual Computing Lab /\/| * 7 * ISTI - Italian National Research Council | * 8 * \ * 9 * All rights reserved. * 10 * * 11 * This program is free software; you can redistribute it and/or modify * 12 * it under the terms of the GNU General Public License as published by * 13 * the Free Software Foundation; either version 2 of the License, or * 14 * (at your option) any later version. * 15 * * 16 * This program is distributed in the hope that it will be useful, * 17 * but WITHOUT ANY WARRANTY; without even the implied warranty of * 18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * 19 * GNU General Public License (http://www.gnu.org/licenses/gpl.txt) * 20 * for more details. * 21 * * 22 ****************************************************************************/ 23 #ifndef __VCGLIB_GLU_TESSELATOR_H 24 #define __VCGLIB_GLU_TESSELATOR_H 25 #include <vcg/space/point2.h> 26 #include <vector> 27 28 #ifndef GL_VERSION_1_1 29 #error "Please include OpenGL before including this file" 30 #endif 31 32 33 // The inclusion of glu should be always safe (if someone has already included gl stuff). 34 #ifndef GLU_VERSIONS 35 #ifdef __APPLE__ 36 #include <OpenGL/glu.h> 37 #else 38 #ifdef _WIN32 39 #include <windows.h> 40 #endif 41 #include <GL/glu.h> 42 #endif 43 #endif 44 45 #ifndef CALLBACK 46 #ifdef _WIN32 47 #define CALLBACK __stdcall 48 #else 49 #define CALLBACK 50 #endif 51 #endif 52 53 namespace vcg 54 { 55 56 class glu_tesselator 57 { 58 public: 59 60 typedef glu_tesselator this_type; 61 62 /* 63 Works with Point2 and Point3; 64 65 sample usage: 66 67 // tesselation input: each outline represents a polygon contour 68 std::vector< std::vector<point_type> > outlines = ...; 69 70 // tesselation output (triangles indices) 71 std::vector<int> indices; 72 73 // compute triangles indices 74 glu_tesselator::tesselate(outlines, indices); 75 76 // unroll input contours points 77 std::vector<point_type> points; 78 79 for (size_t i=0; i<outlines.size(); ++i) 80 { 81 for (size_t j=0; j<outlines[i].size(); ++j) 82 { 83 points.push_back(outlines[i][j]); 84 } 85 } 86 // or simply call glu_tesselator::unroll(outlines, points); 87 88 // create triangles 89 for (size_t i=0; i<indices.size(); i+=3) 90 { 91 create_triangle( 92 points[ indices[i+0] ], 93 points[ indices[i+1] ], 94 points[ indices[i+2] ]); 95 } 96 */ 97 98 template <class point_type> unroll(const std::vector<std::vector<point_type>> & outlines,std::vector<point_type> & points)99 static inline void unroll(const std::vector< std::vector<point_type> > & outlines, std::vector<point_type> & points) 100 { 101 for (size_t i=0; i<outlines.size(); ++i) 102 { 103 for (size_t j=0; j<outlines[i].size(); ++j) 104 { 105 points.push_back(outlines[i][j]); 106 } 107 } 108 } 109 110 template <class point_type> tesselate(const std::vector<std::vector<point_type>> & outlines,std::vector<int> & indices)111 static inline void tesselate(const std::vector< std::vector<point_type> > & outlines, std::vector<int> & indices) 112 { 113 tess_prim_data_vec t_data; 114 115 this_type::do_tesselation(outlines, t_data); 116 117 //int k = 0; 118 for (size_t i=0; i<t_data.size(); ++i) 119 { 120 const size_t st = t_data[i].indices.size(); 121 if (st < 3) continue; 122 123 switch (t_data[i].type) 124 { 125 case GL_TRIANGLES: 126 for (size_t j=0; j<st; ++j) 127 { 128 indices.push_back(t_data[i].indices[j]); 129 } 130 break; 131 132 case GL_TRIANGLE_STRIP: 133 { 134 int i0 = t_data[i].indices[0]; 135 int i1 = t_data[i].indices[1]; 136 137 bool ccw = true; 138 139 for (size_t j=2; j<st; ++j) 140 { 141 const int i2 = t_data[i].indices[j]; 142 143 indices.push_back(i0); 144 indices.push_back(i1); 145 indices.push_back(i2); 146 147 if (ccw) i0 = i2; 148 else i1 = i2; 149 150 ccw = !ccw; 151 } } 152 break; 153 154 case GL_TRIANGLE_FAN: 155 { 156 const int first = t_data[i].indices[0]; 157 int prev = t_data[i].indices[1]; 158 159 for (size_t j=2; j<st; ++j) 160 { 161 const int curr = t_data[i].indices[j]; 162 163 indices.push_back(first); 164 indices.push_back(prev); 165 indices.push_back(curr); 166 167 prev = curr; 168 } 169 } 170 break; 171 172 default: 173 break; 174 } 175 } 176 } 177 178 protected: 179 180 class tess_prim_data 181 { 182 public: 183 184 typedef tess_prim_data this_type; 185 186 GLenum type; 187 std::vector<int> indices; 188 tess_prim_data(void)189 tess_prim_data(void) { } tess_prim_data(GLenum t)190 tess_prim_data(GLenum t) : type(t) { } 191 }; 192 193 typedef std::vector<tess_prim_data> tess_prim_data_vec; 194 begin_cb(GLenum type,void * polygon_data)195 static void CALLBACK begin_cb(GLenum type, void * polygon_data) 196 { 197 tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; 198 t_data->push_back(tess_prim_data(type)); 199 } 200 end_cb(void * polygon_data)201 static void CALLBACK end_cb(void * polygon_data) 202 { 203 (void)polygon_data; 204 } 205 vertex_cb(void * vertex_data,void * polygon_data)206 static void CALLBACK vertex_cb(void * vertex_data, void * polygon_data) 207 { 208 tess_prim_data_vec * t_data = (tess_prim_data_vec *)polygon_data; 209 t_data->back().indices.push_back((int)((size_t)vertex_data)); 210 } 211 212 template <class point_type> do_tesselation(const std::vector<std::vector<point_type>> & outlines,tess_prim_data_vec & t_data)213 static void do_tesselation(const std::vector< std::vector<point_type> > & outlines, tess_prim_data_vec & t_data) 214 { 215 GLUtesselator * tess = gluNewTess(); 216 //#ifdef __APPLE__ 217 // gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)(...))(this_type::begin_cb)); 218 // gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)(...))(this_type::end_cb)); 219 // gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)(...))(this_type::vertex_cb)); 220 //#else 221 gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (GLvoid (CALLBACK *)())(this_type::begin_cb)); 222 gluTessCallback(tess, GLU_TESS_END_DATA, (GLvoid (CALLBACK *)())(this_type::end_cb)); 223 gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (GLvoid (CALLBACK *)())(this_type::vertex_cb)); 224 //#endif 225 void * polygon_data = (void *)(&t_data); 226 227 GLdouble vertex[3]; 228 229 size_t k = 0; 230 gluTessBeginPolygon(tess, polygon_data); 231 for (size_t i=0; i<outlines.size(); ++i) 232 { 233 gluTessBeginContour(tess); 234 for (size_t j=0; j<outlines[i].size(); ++j) 235 { 236 this_type::get_position(outlines[i][j], vertex); 237 gluTessVertex(tess, vertex, (void *)k); 238 ++k; 239 } 240 gluTessEndContour(tess); 241 } 242 gluTessEndPolygon(tess); 243 244 gluDeleteTess(tess); 245 } 246 247 template <class scalar_type> get_position(const vcg::Point2<scalar_type> & p,GLdouble * d)248 static inline void get_position(const vcg::Point2<scalar_type> & p, GLdouble * d) 249 { 250 d[0] = (GLdouble)(p[0]); 251 d[1] = (GLdouble)(p[1]); 252 d[2] = (GLdouble)(0); 253 } 254 255 template <class scalar_type> get_position(const vcg::Point3<scalar_type> & p,GLdouble * d)256 static inline void get_position(const vcg::Point3<scalar_type> & p, GLdouble * d) 257 { 258 d[0] = (GLdouble)(p[0]); 259 d[1] = (GLdouble)(p[1]); 260 d[2] = (GLdouble)(p[2]); 261 } 262 }; 263 264 } // end namespace vcg 265 266 #endif // __VCGLIB_GLU_TESSELATOR_H 267