Updated GLCanvas3D to use the tesselator through libslic3r
This commit is contained in:
parent
2a7e5bc0ae
commit
3dc6e266ed
2 changed files with 7 additions and 228 deletions
|
@ -154,6 +154,8 @@ add_library(libslic3r STATIC
|
||||||
SVG.cpp
|
SVG.cpp
|
||||||
SVG.hpp
|
SVG.hpp
|
||||||
Technologies.hpp
|
Technologies.hpp
|
||||||
|
Tesselate.cpp
|
||||||
|
Tesselate.hpp
|
||||||
TriangleMesh.cpp
|
TriangleMesh.cpp
|
||||||
TriangleMesh.hpp
|
TriangleMesh.hpp
|
||||||
utils.cpp
|
utils.cpp
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "libslic3r/Geometry.hpp"
|
#include "libslic3r/Geometry.hpp"
|
||||||
#include "libslic3r/Utils.hpp"
|
#include "libslic3r/Utils.hpp"
|
||||||
#include "libslic3r/Technologies.hpp"
|
#include "libslic3r/Technologies.hpp"
|
||||||
|
#include "libslic3r/Tesselate.hpp"
|
||||||
#include "slic3r/GUI/3DScene.hpp"
|
#include "slic3r/GUI/3DScene.hpp"
|
||||||
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
|
#include "slic3r/GUI/BackgroundSlicingProcess.hpp"
|
||||||
#include "slic3r/GUI/GLShader.hpp"
|
#include "slic3r/GUI/GLShader.hpp"
|
||||||
|
@ -6737,230 +6738,6 @@ void GLCanvas3D::_render_camera_target() const
|
||||||
}
|
}
|
||||||
#endif // ENABLE_SHOW_CAMERA_TARGET
|
#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<GLdouble> 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<double>(pt[0]));
|
|
||||||
coords.emplace_back(unscale<double>(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<double>(pt[0]));
|
|
||||||
coords.emplace_back(unscale<double>(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<Vec3d> 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<Vec3d> 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<TPPLPoly> input = expoly_to_polypartition_input(poly);
|
|
||||||
std::list<TPPLPoly> 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<double>(pt2->x), unscale<double>(pt2->y), z);
|
|
||||||
triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
|
|
||||||
triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
|
|
||||||
} else {
|
|
||||||
triangles.emplace_back(unscale<double>(pt0->x), unscale<double>(pt0->y), z);
|
|
||||||
triangles.emplace_back(unscale<double>(pt1->x), unscale<double>(pt1->y), z);
|
|
||||||
triangles.emplace_back(unscale<double>(pt2->x), unscale<double>(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
|
void GLCanvas3D::_render_sla_slices() const
|
||||||
{
|
{
|
||||||
if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
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
|
// calculate model bottom cap
|
||||||
if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
|
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
|
// calculate support bottom cap
|
||||||
if (bottom_sup_triangles.empty() && (it_min_z->second.support_slices_idx < support_slices.size()))
|
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())
|
if (it_max_z != index.end())
|
||||||
{
|
{
|
||||||
// calculate model top cap
|
// calculate model top cap
|
||||||
if (top_obj_triangles.empty() && (it_max_z->second.model_slices_idx < model_slices.size()))
|
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
|
// calculate support top cap
|
||||||
if (top_sup_triangles.empty() && (it_max_z->second.support_slices_idx < support_slices.size()))
|
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);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue