Geant4 Cross Reference |
1 // Copyright (C) 2010, Guy Barrand. All rights reserved. 2 // See the file tools.license for terms. 3 4 #ifndef tools_tess_contour 5 #define tools_tess_contour 6 7 #include "glutess/glutess" 8 #include "lina/vec3f" 9 #include "glprims" 10 11 namespace tools { 12 13 typedef struct { 14 double pointA[3]; 15 double pointB[3]; 16 double pointC[3]; 17 } tess_triangle; 18 19 class tess_contour { 20 public: 21 tess_contour(std::ostream& a_out,std::vector<tess_triangle>& a_triangles) 22 :m_out(a_out) 23 ,m_triangles(a_triangles) 24 ,m_vertex_number(0),m_begin_type(gl::triangles()),m_error(false){} 25 virtual ~tess_contour(){} 26 protected: 27 tess_contour(const tess_contour& a_from):m_out(a_from.m_out),m_triangles(a_from.m_triangles){} 28 tess_contour& operator=(const tess_contour&){return *this;} 29 public: 30 void getFilledArea(const std::vector<std::vector<vec3f> >& aContour) { 31 m_triangles.clear(); 32 m_combine_tmps.clear(); 33 m_error = false; 34 35 GLUtesselator* tobj = gluNewTess(); 36 37 // g++-8.1.0 : the five below lines induce warnings : cast between incompatible function types. 38 //::gluTessCallback(tobj,(GLUenum)GLU_TESS_VERTEX_DATA, (Func)vertexCallback); 39 //::gluTessCallback(tobj,(GLUenum)GLU_TESS_BEGIN_DATA, (Func)beginCallback); 40 //::gluTessCallback(tobj,(GLUenum)GLU_TESS_END_DATA, (Func)endCallback); 41 //::gluTessCallback(tobj,(GLUenum)GLU_TESS_ERROR_DATA, (Func)errorCallback); 42 //::gluTessCallback(tobj,(GLUenum)GLU_TESS_COMBINE_DATA,(Func)combineCallback); 43 44 // NOTE : the gluTessCallback_<> are tools/glutess specific. 45 ::gluTessCallback_GLU_TESS_VERTEX_DATA (tobj,vertexCallback); 46 ::gluTessCallback_GLU_TESS_BEGIN_DATA (tobj,beginCallback); 47 ::gluTessCallback_GLU_TESS_END_DATA (tobj,endCallback); 48 ::gluTessCallback_GLU_TESS_ERROR_DATA (tobj,errorCallback); 49 ::gluTessCallback_GLU_TESS_COMBINE_DATA(tobj,combineCallback); 50 51 ::gluTessProperty(tobj,(GLUenum)GLU_TESS_WINDING_RULE,GLU_TESS_WINDING_ODD); 52 53 for(unsigned int a=0;a<aContour.size();a++) { 54 //if(aContour[a][0]!=aContour[a][aContour[a].size()-1]) continue; 55 if(aContour[a].size()<=1) continue; //should not happen. 56 size_t vecSize = aContour[a].size()-1; 57 58 typedef GLUdouble point[3]; 59 point* tab = new point[vecSize]; 60 61 ::gluTessBeginPolygon(tobj, this); 62 63 ::gluTessBeginContour(tobj); 64 for(size_t b=0;b<vecSize;b++) { 65 tab[b][0] = aContour[a][b][0]; 66 tab[b][1] = aContour[a][b][1]; 67 tab[b][2] = aContour[a][b][2]; 68 ::gluTessVertex(tobj, tab[b],tab[b]); 69 } 70 ::gluTessEndContour(tobj); 71 72 ::gluTessEndPolygon(tobj); 73 74 delete [] tab; 75 } 76 77 ::gluDeleteTess(tobj); 78 79 for(unsigned int index=0;index<m_combine_tmps.size();index++) { 80 delete [] m_combine_tmps[index]; 81 } 82 m_combine_tmps.clear(); 83 84 if(m_error) m_triangles.clear(); 85 } 86 87 protected: 88 void resetVertex() {m_vertex_number = 0;} 89 void setBeginType(gl::mode_t aType) {m_begin_type = aType;} 90 void setError(bool aError) {m_error = aError;} 91 std::vector<double*>& combineTmps(){return m_combine_tmps;} 92 93 void addVertex(const double* vertex) { 94 // GLU_TRIANGLE_STRIP 95 // Draws a connected group of triangles. One triangle is defined for each 96 // vertex presented after the first two vertices. For odd n, vertices n, 97 // n+1, and n+2 define triangle n. For even n, vertices n+1, n, and n+2 98 // define triangle n. N-2 triangles are drawn. 99 if (m_begin_type == gl::triangle_strip()) { 100 m_tmp.pointC[0] = vertex[0]; 101 m_tmp.pointC[1] = vertex[1]; 102 m_tmp.pointC[2] = vertex[2]; 103 104 if(m_vertex_number>=2) m_triangles.push_back(m_tmp); 105 106 int rest = m_vertex_number % 2; 107 if(rest==1) { 108 m_tmp.pointA[0] = vertex[0]; 109 m_tmp.pointA[1] = vertex[1]; 110 m_tmp.pointA[2] = vertex[2]; 111 } else { 112 m_tmp.pointB[0] = vertex[0]; 113 m_tmp.pointB[1] = vertex[1]; 114 m_tmp.pointB[2] = vertex[2]; 115 } 116 m_vertex_number++; 117 } 118 119 // GLU_TRIANGLE_FAN 120 // Draws a connected group of triangles. One triangle is defined for each 121 // vertex presented after the first two vertices. Vertices 1, n+1, 122 // and n+2 define triangle n. N-2 triangles are drawn. 123 else if (m_begin_type == gl::triangle_fan()) { 124 if (m_vertex_number == 0) { 125 m_tmp.pointA[0] = vertex[0]; 126 m_tmp.pointA[1] = vertex[1]; 127 m_tmp.pointA[2] = vertex[2]; 128 } else { 129 m_tmp.pointC[0] = vertex[0]; 130 m_tmp.pointC[1] = vertex[1]; 131 m_tmp.pointC[2] = vertex[2]; 132 133 if (m_vertex_number >=2 ) { 134 m_triangles.push_back(m_tmp); 135 } 136 m_tmp.pointB[0] = vertex[0]; 137 m_tmp.pointB[1] = vertex[1]; 138 m_tmp.pointB[2] = vertex[2]; 139 } 140 m_vertex_number++; 141 } 142 143 // GLU_TRIANGLES 144 // Treats each triplet of vertices as an independent triangle. 145 // Vertices 3n-2, 3n-1, and 3n define triangle n. N/3 triangles are drawn. 146 else if (m_begin_type == gl::triangles()) { 147 148 int rest = m_vertex_number % 3; 149 150 if(rest==2) { 151 m_tmp.pointC[0] = vertex[0]; 152 m_tmp.pointC[1] = vertex[1]; 153 m_tmp.pointC[2] = vertex[2]; 154 155 m_triangles.push_back(m_tmp); 156 157 } else if(rest==1) { 158 m_tmp.pointB[0] = vertex[0]; 159 m_tmp.pointB[1] = vertex[1]; 160 m_tmp.pointB[2] = vertex[2]; 161 162 } else if(rest==0) { 163 m_tmp.pointA[0] = vertex[0]; 164 m_tmp.pointA[1] = vertex[1]; 165 m_tmp.pointA[2] = vertex[2]; 166 } 167 m_vertex_number++; 168 169 } else { 170 // do nothing and should never happend 171 } 172 } 173 protected: 174 #ifdef TOOLS_TESS_CONTOUR_STDCALL 175 typedef GLUvoid(__stdcall *Func)(); 176 #else 177 typedef GLUvoid(*Func)(); 178 #endif 179 180 static void 181 #ifdef TOOLS_TESS_CONTOUR_STDCALL 182 __stdcall 183 #endif 184 beginCallback(GLUenum aWhich,GLUvoid * aThis) { 185 tess_contour* This = (tess_contour*)aThis; 186 This->setBeginType(aWhich); 187 This->resetVertex(); 188 } 189 190 static void 191 #ifdef TOOLS_TESS_CONTOUR_STDCALL 192 __stdcall 193 #endif 194 errorCallback(GLUenum aErrorCode,GLUvoid * aThis) { 195 tess_contour* This = (tess_contour*)aThis; 196 This->m_out << "tools::tess_contour::errorCallback : " << aErrorCode << std::endl; 197 This->setError(true); 198 } 199 200 static void 201 #ifdef TOOLS_TESS_CONTOUR_STDCALL 202 __stdcall 203 #endif 204 endCallback(void*){} 205 206 static void 207 #ifdef TOOLS_TESS_CONTOUR_STDCALL 208 __stdcall 209 #endif 210 vertexCallback(GLUvoid *vertex,GLUvoid* aThis) { 211 tess_contour* This = (tess_contour*)aThis; 212 This->addVertex((double*)vertex); 213 } 214 215 static void 216 #ifdef TOOLS_TESS_CONTOUR_STDCALL 217 __stdcall 218 #endif 219 combineCallback(GLUdouble coords[3], 220 void* /*vertex_data*/[4], 221 GLUfloat /*weight*/[4], 222 void** dataOut, 223 void* aThis) { 224 tess_contour* This = (tess_contour*)aThis; 225 double* vertex = new double[3]; 226 vertex[0] = coords[0]; 227 vertex[1] = coords[1]; 228 vertex[2] = coords[2]; 229 This->combineTmps().push_back(vertex); 230 *dataOut = vertex; 231 } 232 233 protected: 234 std::ostream& m_out; 235 std::vector<tess_triangle>& m_triangles; 236 tess_triangle m_tmp; 237 unsigned int m_vertex_number; 238 gl::mode_t m_begin_type; 239 bool m_error; 240 std::vector<double*> m_combine_tmps; 241 }; 242 243 } 244 245 #endif