Polished up the tesselator.

This commit is contained in:
bubnikv 2019-02-05 20:49:09 +01:00
parent e3ed05491e
commit f22926649c

View File

@ -8,12 +8,22 @@ namespace Slic3r {
class GluTessWrapper { class GluTessWrapper {
public: public:
GluTessWrapper() : m_tesselator(gluNewTess()) {
// register callback functions
gluTessCallback(m_tesselator, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)tessBeginCB);
gluTessCallback(m_tesselator, GLU_TESS_END_DATA, (_GLUfuncptr)tessEndCB);
gluTessCallback(m_tesselator, GLU_TESS_ERROR_DATA, (_GLUfuncptr)tessErrorCB);
gluTessCallback(m_tesselator, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)tessVertexCB);
gluTessCallback(m_tesselator, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)tessCombineCB);
}
~GluTessWrapper() {
gluDeleteTess(m_tesselator);
}
Pointf3s tesselate(const ExPolygon &expoly, double z_, bool flipped_) Pointf3s tesselate(const ExPolygon &expoly, double z_, bool flipped_)
{ {
z = z_; m_z = z_;
flipped = flipped_; m_flipped = flipped_;
triangles.clear();
intersection_points.clear();
std::vector<GLdouble> coords; std::vector<GLdouble> coords;
{ {
size_t num_coords = expoly.contour.points.size(); size_t num_coords = expoly.contour.points.size();
@ -21,54 +31,35 @@ public:
num_coords += poly.points.size(); num_coords += poly.points.size();
coords.reserve(num_coords * 3); coords.reserve(num_coords * 3);
} }
GLUtesselator *tess = gluNewTess(); // create a tessellator gluTessBeginPolygon(m_tesselator, (void*)this);
// register callback functions gluTessBeginContour(m_tesselator);
#ifndef _GLUfuncptr
#ifdef _MSC_VER
typedef void (__stdcall *_GLUfuncptr)(void);
#else /* _MSC_VER */
#ifdef GLAPIENTRYP
typedef void (GLAPIENTRYP _GLUfuncptr)(void);
#else /* GLAPIENTRYP */
typedef void (*_GLUfuncptr)(void);
#endif
#endif /* _MSC_VER */
#endif /* _GLUfuncptr */
gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)tessBeginCB);
gluTessCallback(tess, GLU_TESS_END_DATA, (_GLUfuncptr)tessEndCB);
gluTessCallback(tess, GLU_TESS_ERROR_DATA, (_GLUfuncptr)tessErrorCB);
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)tessVertexCB);
gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)tessCombineCB);
gluTessBeginPolygon(tess, (void*)this);
gluTessBeginContour(tess);
for (const Point &pt : expoly.contour.points) { for (const Point &pt : expoly.contour.points) {
coords.emplace_back(unscale<double>(pt[0])); coords.emplace_back(unscale<double>(pt[0]));
coords.emplace_back(unscale<double>(pt[1])); coords.emplace_back(unscale<double>(pt[1]));
coords.emplace_back(0.); coords.emplace_back(0.);
gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]); gluTessVertex(m_tesselator, &coords[coords.size() - 3], &coords[coords.size() - 3]);
} }
gluTessEndContour(tess); gluTessEndContour(m_tesselator);
for (const Polygon &poly : expoly.holes) { for (const Polygon &poly : expoly.holes) {
gluTessBeginContour(tess); gluTessBeginContour(m_tesselator);
for (const Point &pt : poly.points) { for (const Point &pt : poly.points) {
coords.emplace_back(unscale<double>(pt[0])); coords.emplace_back(unscale<double>(pt[0]));
coords.emplace_back(unscale<double>(pt[1])); coords.emplace_back(unscale<double>(pt[1]));
coords.emplace_back(0.); coords.emplace_back(0.);
gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]); gluTessVertex(m_tesselator, &coords[coords.size() - 3], &coords[coords.size() - 3]);
} }
gluTessEndContour(tess); gluTessEndContour(m_tesselator);
} }
gluTessEndPolygon(tess); gluTessEndPolygon(m_tesselator);
gluDeleteTess(tess); m_output_triangles.clear();
return std::move(triangles); m_intersection_points.clear();
return std::move(m_output_triangles);
} }
Pointf3s tesselate(const ExPolygons &expolygons, double z_, bool flipped_) Pointf3s tesselate(const ExPolygons &expolygons, double z_, bool flipped_)
{ {
z = z_; m_z = z_;
flipped = flipped_; m_flipped = flipped_;
triangles.clear();
intersection_points.clear();
std::vector<GLdouble> coords; std::vector<GLdouble> coords;
{ {
size_t num_coords = 0; size_t num_coords = 0;
@ -80,49 +71,32 @@ public:
} }
coords.assign(num_coords * 3, 0); coords.assign(num_coords * 3, 0);
} }
GLUtesselator *tess = gluNewTess(); // create a tessellator
// register callback functions
#ifndef _GLUfuncptr
#ifdef _MSC_VER
typedef void (__stdcall *_GLUfuncptr)(void);
#else /* _MSC_VER */
#ifdef GLAPIENTRYP
typedef void (GLAPIENTRYP _GLUfuncptr)(void);
#else /* GLAPIENTRYP */
typedef void (*_GLUfuncptr)(void);
#endif
#endif /* _MSC_VER */
#endif /* _GLUfuncptr */
gluTessCallback(tess, GLU_TESS_BEGIN_DATA, (_GLUfuncptr)tessBeginCB);
gluTessCallback(tess, GLU_TESS_END_DATA, (_GLUfuncptr)tessEndCB);
gluTessCallback(tess, GLU_TESS_ERROR_DATA, (_GLUfuncptr)tessErrorCB);
gluTessCallback(tess, GLU_TESS_VERTEX_DATA, (_GLUfuncptr)tessVertexCB);
gluTessCallback(tess, GLU_TESS_COMBINE_DATA, (_GLUfuncptr)tessCombineCB);
for (const ExPolygon &expoly : expolygons) { for (const ExPolygon &expoly : expolygons) {
gluTessBeginPolygon(tess, (void*)this); gluTessBeginPolygon(m_tesselator, (void*)this);
gluTessBeginContour(tess); gluTessBeginContour(m_tesselator);
size_t idx = 0; size_t idx = 0;
for (const Point &pt : expoly.contour.points) { for (const Point &pt : expoly.contour.points) {
coords[idx ++] = unscale<double>(pt[0]); coords[idx ++] = unscale<double>(pt[0]);
coords[idx ++] = unscale<double>(pt[1]); coords[idx ++] = unscale<double>(pt[1]);
coords[idx ++] = 0.; coords[idx ++] = 0.;
gluTessVertex(tess, &coords[idx - 3], &coords[idx - 3]); gluTessVertex(m_tesselator, &coords[idx - 3], &coords[idx - 3]);
} }
gluTessEndContour(tess); gluTessEndContour(m_tesselator);
for (const Polygon &poly : expoly.holes) { for (const Polygon &poly : expoly.holes) {
gluTessBeginContour(tess); gluTessBeginContour(m_tesselator);
for (const Point &pt : poly.points) { for (const Point &pt : poly.points) {
coords[idx ++] = unscale<double>(pt[0]); coords[idx ++] = unscale<double>(pt[0]);
coords[idx ++] = unscale<double>(pt[1]); coords[idx ++] = unscale<double>(pt[1]);
coords[idx ++] = 0.; coords[idx ++] = 0.;
gluTessVertex(tess, &coords[idx - 3], &coords[idx - 3]); gluTessVertex(m_tesselator, &coords[idx - 3], &coords[idx - 3]);
} }
gluTessEndContour(tess); gluTessEndContour(m_tesselator);
} }
gluTessEndPolygon(tess); gluTessEndPolygon(m_tesselator);
} }
gluDeleteTess(tess); m_output_triangles.clear();
return std::move(triangles); m_intersection_points.clear();
return std::move(m_output_triangles);
} }
private: private:
@ -136,15 +110,13 @@ private:
void tessBegin(GLenum which) void tessBegin(GLenum which)
{ {
assert(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP); assert(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP);
if (!(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP)) m_primitive_type = which;
printf("Co je to za haluz!?\n"); m_num_points = 0;
primitive_type = which;
num_points = 0;
} }
void tessEnd() void tessEnd()
{ {
num_points = 0; m_num_points = 0;
} }
void tessVertex(const GLvoid *data) void tessVertex(const GLvoid *data)
@ -152,42 +124,42 @@ private:
if (data == nullptr) if (data == nullptr)
return; return;
const GLdouble *ptr = (const GLdouble*)data; const GLdouble *ptr = (const GLdouble*)data;
++ num_points; ++ m_num_points;
if (num_points == 1) { if (m_num_points == 1) {
memcpy(pt0, ptr, sizeof(GLdouble) * 3); memcpy(m_pt0, ptr, sizeof(GLdouble) * 3);
} else if (num_points == 2) { } else if (m_num_points == 2) {
memcpy(pt1, ptr, sizeof(GLdouble) * 3); memcpy(m_pt1, ptr, sizeof(GLdouble) * 3);
} else { } else {
bool flip = flipped; bool flip = m_flipped;
if (primitive_type == GL_TRIANGLE_STRIP && num_points == 4) { if (m_primitive_type == GL_TRIANGLE_STRIP && m_num_points == 4) {
flip = !flip; flip = !flip;
num_points = 2; m_num_points = 2;
} }
triangles.emplace_back(pt0[0], pt0[1], z); m_output_triangles.emplace_back(m_pt0[0], m_pt0[1], m_z);
if (flip) { if (flip) {
triangles.emplace_back(ptr[0], ptr[1], z); m_output_triangles.emplace_back(ptr[0], ptr[1], m_z);
triangles.emplace_back(pt1[0], pt1[1], z); m_output_triangles.emplace_back(m_pt1[0], m_pt1[1], m_z);
} else { } else {
triangles.emplace_back(pt1[0], pt1[1], z); m_output_triangles.emplace_back(m_pt1[0], m_pt1[1], m_z);
triangles.emplace_back(ptr[0], ptr[1], z); m_output_triangles.emplace_back(ptr[0], ptr[1], m_z);
} }
if (primitive_type == GL_TRIANGLE_STRIP) { if (m_primitive_type == GL_TRIANGLE_STRIP) {
memcpy(pt0, pt1, sizeof(GLdouble) * 3); memcpy(m_pt0, m_pt1, sizeof(GLdouble) * 3);
memcpy(pt1, ptr, sizeof(GLdouble) * 3); memcpy(m_pt1, ptr, sizeof(GLdouble) * 3);
} else if (primitive_type == GL_TRIANGLE_FAN) { } else if (m_primitive_type == GL_TRIANGLE_FAN) {
memcpy(pt1, ptr, sizeof(GLdouble) * 3); memcpy(m_pt1, ptr, sizeof(GLdouble) * 3);
} else { } else {
assert(primitive_type == GL_TRIANGLES); assert(m_primitive_type == GL_TRIANGLES);
assert(num_points == 3); assert(m_num_points == 3);
num_points = 0; m_num_points = 0;
} }
} }
} }
void tessCombine(const GLdouble newVertex[3], const GLdouble *neighborVertex[4], const GLfloat neighborWeight[4], GLdouble **outData) void tessCombine(const GLdouble newVertex[3], const GLdouble *neighborVertex[4], const GLfloat neighborWeight[4], GLdouble **outData)
{ {
intersection_points.emplace_back(newVertex[0], newVertex[1], newVertex[2]); m_intersection_points.emplace_back(newVertex[0], newVertex[1], m_z);
*outData = intersection_points.back().data(); *outData = m_intersection_points.back().data();
} }
static void tessError(GLenum errorCode) static void tessError(GLenum errorCode)
@ -197,14 +169,24 @@ private:
// printf("Error: %s\n", (const char*)errorStr); // printf("Error: %s\n", (const char*)errorStr);
} }
GLenum primitive_type; // Instance owned over the life time of this wrapper.
GLdouble pt0[3]; GLUtesselator *m_tesselator;
GLdouble pt1[3];
int num_points; // Currently processed primitive type.
Pointf3s triangles; GLenum m_primitive_type;
std::deque<Vec3d> intersection_points; // Two last vertices received for m_primitive_type. Used for processing triangle strips, fans etc.
double z; GLdouble m_pt0[3];
bool flipped; GLdouble m_pt1[3];
// Number of points processed over m_primitive_type.
int m_num_points;
// Triangles generated by the tesselator.
Pointf3s m_output_triangles;
// Intersection points generated by tessCombine callback. There should be none if the input contour is not self intersecting.
std::deque<Vec3d> m_intersection_points;
// Fixed third coordinate.
double m_z;
// Output triangles shall be flipped (normal points down).
bool m_flipped;
}; };
Pointf3s triangulate_expolygons_3df(const ExPolygon &poly, coordf_t z, bool flip) Pointf3s triangulate_expolygons_3df(const ExPolygon &poly, coordf_t z, bool flip)