00001 #ifndef K3DSDK_MESH_TRIANGULATE_DETAIL_H
00002 #define K3DSDK_MESH_TRIANGULATE_DETAIL_H
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023 #include <k3dsdk/sgi_tesselator.h>
00024
00025 namespace detail
00026 {
00027
00028 template<typename OutputFaceIterator, typename OutputPointIterator>
00029 class glu_triangulator_t
00030 {
00031 public:
00032 glu_triangulator_t(OutputFaceIterator OutputFaces, OutputPointIterator OutputPoints) :
00033 tessellator(sgiNewTess()),
00034 output_faces(OutputFaces),
00035 output_points(OutputPoints),
00036 current_face(0)
00037 {
00038 sgiTessCallback(tessellator, GLU_TESS_BEGIN_DATA, reinterpret_cast<callback_t>(&raw_begin));
00039 sgiTessCallback(tessellator, GLU_TESS_VERTEX_DATA, reinterpret_cast<callback_t>(&raw_vertex));
00040 sgiTessCallback(tessellator, GLU_TESS_COMBINE_DATA, reinterpret_cast<callback_t>(&raw_combine));
00041 sgiTessCallback(tessellator, GLU_TESS_END_DATA, reinterpret_cast<callback_t>(&raw_end));
00042 sgiTessCallback(tessellator, GLU_TESS_ERROR_DATA, reinterpret_cast<callback_t>(&raw_error));
00043 }
00044
00045 ~glu_triangulator_t()
00046 {
00047 sgiDeleteTess(tessellator);
00048 }
00049
00050 void operator()(face& Face)
00051 {
00052 current_face = &Face;
00053
00054 sgiTessBeginPolygon(tessellator, this);
00055
00056
00057 sgiTessBeginContour(tessellator);
00058 for(split_edge* edge = Face.first_edge; edge && edge->face_clockwise; edge = edge->face_clockwise)
00059 {
00060 sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
00061 if(edge->face_clockwise == Face.first_edge)
00062 break;
00063 }
00064 sgiTessEndContour(tessellator);
00065
00066
00067 for(face::holes_t::const_iterator hole = Face.holes.begin(); hole != Face.holes.end(); ++hole)
00068 {
00069 sgiTessBeginContour(tessellator);
00070 for(split_edge* edge = *hole; edge && edge->face_clockwise; edge = edge->face_clockwise)
00071 {
00072 sgiTessVertex(tessellator, edge->vertex->position.n, edge->vertex);
00073 if(edge->face_clockwise == *hole)
00074 break;
00075 }
00076 sgiTessEndContour(tessellator);
00077 }
00078
00079 sgiTessEndPolygon(tessellator);
00080 }
00081
00082 private:
00083 void begin(GLenum Mode)
00084 {
00085 mode = Mode;
00086 v0 = v1 = v2 = 0;
00087 flip_strip = false;
00088 }
00089
00090 void vertex(void* VertexData)
00091 {
00092 if(!v0)
00093 {
00094 v0 = v1;
00095 v1 = v2;
00096 }
00097 v2 = reinterpret_cast<point*>(VertexData);
00098
00099 if(!v0)
00100 return;
00101
00102 std::vector<split_edge*> new_edges;
00103 switch(mode)
00104 {
00105 case GL_TRIANGLE_FAN:
00106 new_edges.push_back(new split_edge(v0));
00107 new_edges.push_back(new split_edge(v1));
00108 new_edges.push_back(new split_edge(v2));
00109 break;
00110 case GL_TRIANGLE_STRIP:
00111 new_edges.push_back(new split_edge(v0));
00112 new_edges.push_back(new split_edge(v1));
00113 new_edges.push_back(new split_edge(v2));
00114 if(flip_strip)
00115 std::reverse(new_edges.begin(), new_edges.end());
00116 break;
00117 case GL_TRIANGLES:
00118 new_edges.push_back(new split_edge(v0));
00119 new_edges.push_back(new split_edge(v1));
00120 new_edges.push_back(new split_edge(v2));
00121 break;
00122 }
00123 loop_edges(new_edges.begin(), new_edges.end());
00124
00125 face* const new_face = new face(*current_face);
00126 new_face->holes.clear();
00127 new_face->first_edge = new_edges.front();
00128 *output_faces++ = new_face;
00129
00130 switch(mode)
00131 {
00132 case GL_TRIANGLE_FAN:
00133 v1 = v2;
00134 break;
00135 case GL_TRIANGLE_STRIP:
00136 v0 = v1;
00137 v1 = v2;
00138 flip_strip = !flip_strip;
00139 break;
00140 case GL_TRIANGLES:
00141 v0 = v1 = v2 = 0;
00142 break;
00143 }
00144 }
00145
00146 void combine(GLdouble Coords[3], void* [4], GLfloat [4], void** OutputData)
00147 {
00148 point* const new_point = new point(point3(Coords[0], Coords[1], Coords[2]));
00149 *OutputData = new_point;
00150 *output_points++ = new_point;
00151 }
00152
00153 void end()
00154 {
00155 }
00156
00157 void error(GLenum ErrorNumber)
00158 {
00159 log() << k3d::error << k3d_file_reference << " " << gluErrorString(ErrorNumber) << std::endl;
00160 }
00161
00162 static glu_triangulator_t* instance(void* UserData)
00163 {
00164 return reinterpret_cast<glu_triangulator_t*>(UserData);
00165 }
00166
00167 static void raw_begin(GLenum Mode, void* UserData)
00168 {
00169 instance(UserData)->begin(Mode);
00170 }
00171
00172 static void raw_vertex(void* VertexData, void* UserData)
00173 {
00174 instance(UserData)->vertex(VertexData);
00175 }
00176
00177 static void raw_combine(GLdouble Coords[3], void* VertexData[4], GLfloat Weight[4], void** OutputData, void* UserData)
00178 {
00179 instance(UserData)->combine(Coords, VertexData, Weight, OutputData);
00180 }
00181
00182 static void raw_end(void* UserData)
00183 {
00184 instance(UserData)->end();
00185 }
00186
00187 static void raw_error(GLenum ErrorNumber, void* UserData)
00188 {
00189 instance(UserData)->error(ErrorNumber);
00190 }
00191
00192 SGItesselator* const tessellator;
00193 OutputFaceIterator output_faces;
00194 OutputPointIterator output_points;
00195
00196 GLenum mode;
00197 point* v0;
00198 point* v1;
00199 point* v2;
00200 bool flip_strip;
00201
00203 face* current_face;
00204 };
00205
00206 }
00207
00208 #endif // !K3DSDK_MESH_TRIANGULATE_DETAIL_H
00209