From 3dc6e266edfac82847baf99048bbe7a5d8124fe9 Mon Sep 17 00:00:00 2001 From: bubnikv Date: Tue, 5 Feb 2019 19:45:52 +0100 Subject: [PATCH] Updated GLCanvas3D to use the tesselator through libslic3r --- src/libslic3r/CMakeLists.txt | 2 + src/slic3r/GUI/GLCanvas3D.cpp | 233 +--------------------------------- 2 files changed, 7 insertions(+), 228 deletions(-) diff --git a/src/libslic3r/CMakeLists.txt b/src/libslic3r/CMakeLists.txt index 909db2a38..2502c1b3e 100644 --- a/src/libslic3r/CMakeLists.txt +++ b/src/libslic3r/CMakeLists.txt @@ -154,6 +154,8 @@ add_library(libslic3r STATIC SVG.cpp SVG.hpp Technologies.hpp + Tesselate.cpp + Tesselate.hpp TriangleMesh.cpp TriangleMesh.hpp utils.cpp diff --git a/src/slic3r/GUI/GLCanvas3D.cpp b/src/slic3r/GUI/GLCanvas3D.cpp index f043deda5..4473e4d75 100644 --- a/src/slic3r/GUI/GLCanvas3D.cpp +++ b/src/slic3r/GUI/GLCanvas3D.cpp @@ -10,6 +10,7 @@ #include "libslic3r/Geometry.hpp" #include "libslic3r/Utils.hpp" #include "libslic3r/Technologies.hpp" +#include "libslic3r/Tesselate.hpp" #include "slic3r/GUI/3DScene.hpp" #include "slic3r/GUI/BackgroundSlicingProcess.hpp" #include "slic3r/GUI/GLShader.hpp" @@ -6737,230 +6738,6 @@ void GLCanvas3D::_render_camera_target() const } #endif // ENABLE_SHOW_CAMERA_TARGET -class TessWrapper { -public: - static Pointf3s tesselate(const ExPolygon &expoly, double z_, bool flipped_) - { - z = z_; - flipped = flipped_; - triangles.clear(); - intersection_points.clear(); - std::vector coords; - { - size_t num_coords = expoly.contour.points.size(); - for (const Polygon &poly : expoly.holes) - num_coords += poly.points.size(); - coords.reserve(num_coords * 3); - } - 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, (_GLUfuncptr)tessBeginCB); - gluTessCallback(tess, GLU_TESS_END, (_GLUfuncptr)tessEndCB); - gluTessCallback(tess, GLU_TESS_ERROR, (_GLUfuncptr)tessErrorCB); - gluTessCallback(tess, GLU_TESS_VERTEX, (_GLUfuncptr)tessVertexCB); - gluTessCallback(tess, GLU_TESS_COMBINE, (_GLUfuncptr)tessCombineCB); - gluTessBeginPolygon(tess, 0); // with NULL data - gluTessBeginContour(tess); - for (const Point &pt : expoly.contour.points) { - coords.emplace_back(unscale(pt[0])); - coords.emplace_back(unscale(pt[1])); - coords.emplace_back(0.); - gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]); - } - gluTessEndContour(tess); - for (const Polygon &poly : expoly.holes) { - gluTessBeginContour(tess); - for (const Point &pt : poly.points) { - coords.emplace_back(unscale(pt[0])); - coords.emplace_back(unscale(pt[1])); - coords.emplace_back(0.); - gluTessVertex(tess, &coords[coords.size() - 3], &coords[coords.size() - 3]); - } - gluTessEndContour(tess); - } - gluTessEndPolygon(tess); - gluDeleteTess(tess); - return std::move(triangles); - } - -private: - static void tessBeginCB(GLenum which) - { - assert(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP); - if (!(which == GL_TRIANGLES || which == GL_TRIANGLE_FAN || which == GL_TRIANGLE_STRIP)) - printf("Co je to za haluz!?\n"); - primitive_type = which; - num_points = 0; - } - - static void tessEndCB() - { - num_points = 0; - } - - static void tessVertexCB(const GLvoid *data) - { - if (data == nullptr) - return; - const GLdouble *ptr = (const GLdouble*)data; - ++ num_points; - if (num_points == 1) { - memcpy(pt0, ptr, sizeof(GLdouble) * 3); - } else if (num_points == 2) { - memcpy(pt1, ptr, sizeof(GLdouble) * 3); - } else { - bool flip = flipped; - if (primitive_type == GL_TRIANGLE_STRIP && num_points == 4) { - flip = !flip; - num_points = 2; - } - triangles.emplace_back(pt0[0], pt0[1], z); - if (flip) { - triangles.emplace_back(ptr[0], ptr[1], z); - triangles.emplace_back(pt1[0], pt1[1], z); - } else { - triangles.emplace_back(pt1[0], pt1[1], z); - triangles.emplace_back(ptr[0], ptr[1], z); - } - if (primitive_type == GL_TRIANGLE_STRIP) { - memcpy(pt0, pt1, sizeof(GLdouble) * 3); - memcpy(pt1, ptr, sizeof(GLdouble) * 3); - } else if (primitive_type == GL_TRIANGLE_FAN) { - memcpy(pt1, ptr, sizeof(GLdouble) * 3); - } else { - assert(primitive_type == GL_TRIANGLES); - assert(num_points == 3); - num_points = 0; - } - } - } - - static void tessCombineCB(const GLdouble newVertex[3], const GLdouble *neighborVertex[4], const GLfloat neighborWeight[4], GLdouble **outData) - { - intersection_points.emplace_back(newVertex[0], newVertex[1], newVertex[2]); - *outData = intersection_points.back().data(); - } - - static void tessErrorCB(GLenum errorCode) - { - const GLubyte *errorStr; - errorStr = gluErrorString(errorCode); - printf("Error: %s\n", (const char*)errorStr); - } - - static GLenum primitive_type; - static GLdouble pt0[3]; - static GLdouble pt1[3]; - static int num_points; - static Pointf3s triangles; - static std::deque intersection_points; - static double z; - static bool flipped; -}; - -GLenum TessWrapper::primitive_type; -GLdouble TessWrapper::pt0[3]; -GLdouble TessWrapper::pt1[3]; -int TessWrapper::num_points; -Pointf3s TessWrapper::triangles; -std::deque TessWrapper::intersection_points; -double TessWrapper::z; -bool TessWrapper::flipped; - -static Pointf3s triangulate_expolygons(const ExPolygons &polys, coordf_t z, bool flip) -{ - Pointf3s triangles; -#if 0 - for (const ExPolygon& poly : polys) { - Polygons poly_triangles; - // poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon! - poly.triangulate(&poly_triangles); - // poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow! - // poly.triangulate_p2t(&poly_triangles); - for (const Polygon &t : poly_triangles) - if (flip) { - triangles.emplace_back(to_3d(unscale(t.points[2]), z)); - triangles.emplace_back(to_3d(unscale(t.points[1]), z)); - triangles.emplace_back(to_3d(unscale(t.points[0]), z)); - } else { - triangles.emplace_back(to_3d(unscale(t.points[0]), z)); - triangles.emplace_back(to_3d(unscale(t.points[1]), z)); - triangles.emplace_back(to_3d(unscale(t.points[2]), z)); - } - } -#else - -// for (const ExPolygon &poly : union_ex(simplify_polygons(to_polygons(polys), true))) { - for (const ExPolygon &poly : polys) { - append(triangles, TessWrapper::tesselate(poly, z, flip)); - continue; - - std::list input = expoly_to_polypartition_input(poly); - std::list output; - // int res = TPPLPartition().Triangulate_MONO(&input, &output); - int res = TPPLPartition().Triangulate_EC(&input, &output); - if (res == 1) { - // Triangulation succeeded. Convert to triangles. - size_t num_triangles = 0; - for (const TPPLPoly &poly : output) - if (poly.GetNumPoints() >= 3) - num_triangles += (size_t)poly.GetNumPoints() - 2; - triangles.reserve(triangles.size() + num_triangles * 3); - for (const TPPLPoly &poly : output) { - long num_points = poly.GetNumPoints(); - if (num_points >= 3) { - const TPPLPoint *pt0 = &poly[0]; - const TPPLPoint *pt1 = nullptr; - const TPPLPoint *pt2 = &poly[1]; - for (long i = 2; i < num_points; ++i) { - pt1 = pt2; - pt2 = &poly[i]; - if (flip) { - triangles.emplace_back(unscale(pt2->x), unscale(pt2->y), z); - triangles.emplace_back(unscale(pt1->x), unscale(pt1->y), z); - triangles.emplace_back(unscale(pt0->x), unscale(pt0->y), z); - } else { - triangles.emplace_back(unscale(pt0->x), unscale(pt0->y), z); - triangles.emplace_back(unscale(pt1->x), unscale(pt1->y), z); - triangles.emplace_back(unscale(pt2->x), unscale(pt2->y), z); - } - } - } - } - } else { - // Triangulation by polypartition failed. Use the expensive slow implementation. - Polygons poly_triangles; - // poly.triangulate() is based on a trapezoidal decomposition implemented in an extremely expensive way by clipping the whole input contour with a polygon! - poly.triangulate(&poly_triangles); - // poly.triangulate_p2t() is based on the poly2tri library, which is not quite stable, it often ends up in a nice stack overflow! - // poly.triangulate_p2t(&poly_triangles); - for (const Polygon &t : poly_triangles) - if (flip) { - triangles.emplace_back(to_3d(unscale(t.points[2]), z)); - triangles.emplace_back(to_3d(unscale(t.points[1]), z)); - triangles.emplace_back(to_3d(unscale(t.points[0]), z)); - } else { - triangles.emplace_back(to_3d(unscale(t.points[0]), z)); - triangles.emplace_back(to_3d(unscale(t.points[1]), z)); - triangles.emplace_back(to_3d(unscale(t.points[2]), z)); - } - } - } -#endif - return triangles; -} - void GLCanvas3D::_render_sla_slices() const { if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA) @@ -7031,20 +6808,20 @@ void GLCanvas3D::_render_sla_slices() const { // calculate model bottom cap if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size())) - bottom_obj_triangles = triangulate_expolygons(model_slices[it_min_z->second.model_slices_idx], min_z, true); + bottom_obj_triangles = triangulate_expolygons_3df(model_slices[it_min_z->second.model_slices_idx], min_z, true); // calculate support bottom cap if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size())) - bottom_sup_triangles = triangulate_expolygons(support_slices[it_min_z->second.support_slices_idx], min_z, true); + bottom_sup_triangles = triangulate_expolygons_3df(support_slices[it_min_z->second.support_slices_idx], min_z, true); } if (it_max_z != index.end()) { // calculate model top cap if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size())) - top_obj_triangles = triangulate_expolygons(model_slices[it_max_z->second.model_slices_idx], max_z, false); + top_obj_triangles = triangulate_expolygons_3df(model_slices[it_max_z->second.model_slices_idx], max_z, false); // calculate support top cap if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size())) - top_sup_triangles = triangulate_expolygons(support_slices[it_max_z->second.support_slices_idx], max_z, false); + top_sup_triangles = triangulate_expolygons_3df(support_slices[it_max_z->second.support_slices_idx], max_z, false); } }