Improvements of the triangulation of SLA layer preview.
This commit is contained in:
parent
584e8a8490
commit
49487c16e6
7 changed files with 386 additions and 127 deletions
|
@ -310,16 +310,15 @@ ExPolygon::medial_axis(double max_width, double min_width, Polylines* polylines)
|
|||
polylines->insert(polylines->end(), tp.begin(), tp.end());
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygon::get_trapezoids(Polygons* polygons) const
|
||||
/*
|
||||
void ExPolygon::get_trapezoids(Polygons* polygons) const
|
||||
{
|
||||
ExPolygons expp;
|
||||
expp.push_back(*this);
|
||||
boost::polygon::get_trapezoids(*polygons, expp);
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
|
||||
void ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
|
||||
{
|
||||
ExPolygon clone = *this;
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
|
@ -327,12 +326,12 @@ ExPolygon::get_trapezoids(Polygons* polygons, double angle) const
|
|||
for (Polygons::iterator polygon = polygons->begin(); polygon != polygons->end(); ++polygon)
|
||||
polygon->rotate(-(PI/2 - angle), Point(0,0));
|
||||
}
|
||||
*/
|
||||
|
||||
// This algorithm may return more trapezoids than necessary
|
||||
// (i.e. it may break a single trapezoid in several because
|
||||
// other parts of the object have x coordinates in the middle)
|
||||
void
|
||||
ExPolygon::get_trapezoids2(Polygons* polygons) const
|
||||
void ExPolygon::get_trapezoids2(Polygons* polygons) const
|
||||
{
|
||||
// get all points of this ExPolygon
|
||||
Points pp = *this;
|
||||
|
@ -370,8 +369,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons) const
|
|||
}
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
|
||||
void ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
|
||||
{
|
||||
ExPolygon clone = *this;
|
||||
clone.rotate(PI/2 - angle, Point(0,0));
|
||||
|
@ -382,8 +380,7 @@ ExPolygon::get_trapezoids2(Polygons* polygons, double angle) const
|
|||
|
||||
// While this triangulates successfully, it's NOT a constrained triangulation
|
||||
// as it will create more vertices on the boundaries than the ones supplied.
|
||||
void
|
||||
ExPolygon::triangulate(Polygons* polygons) const
|
||||
void ExPolygon::triangulate(Polygons* polygons) const
|
||||
{
|
||||
// first make trapezoids
|
||||
Polygons trapezoids;
|
||||
|
@ -394,8 +391,8 @@ ExPolygon::triangulate(Polygons* polygons) const
|
|||
polygon->triangulate_convex(polygons);
|
||||
}
|
||||
|
||||
void
|
||||
ExPolygon::triangulate_pp(Polygons* polygons) const
|
||||
/*
|
||||
void ExPolygon::triangulate_pp(Polygons* polygons) const
|
||||
{
|
||||
// convert polygons
|
||||
std::list<TPPLPoly> input;
|
||||
|
@ -452,9 +449,113 @@ ExPolygon::triangulate_pp(Polygons* polygons) const
|
|||
polygons->push_back(p);
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
void
|
||||
ExPolygon::triangulate_p2t(Polygons* polygons) const
|
||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex)
|
||||
{
|
||||
std::list<TPPLPoly> input;
|
||||
// contour
|
||||
{
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(int(ex.contour.points.size()));
|
||||
for (const Point &point : ex.contour.points) {
|
||||
size_t i = &point - &ex.contour.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(false);
|
||||
}
|
||||
// holes
|
||||
for (const Polygon &hole : ex.holes) {
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(hole.points.size());
|
||||
for (const Point &point : hole.points) {
|
||||
size_t i = &point - &hole.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(true);
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expps)
|
||||
{
|
||||
std::list<TPPLPoly> input;
|
||||
for (const ExPolygon &ex : expps) {
|
||||
// contour
|
||||
{
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(int(ex.contour.points.size()));
|
||||
for (const Point &point : ex.contour.points) {
|
||||
size_t i = &point - &ex.contour.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(false);
|
||||
}
|
||||
// holes
|
||||
for (const Polygon &hole : ex.holes) {
|
||||
input.emplace_back();
|
||||
TPPLPoly &p = input.back();
|
||||
p.Init(hole.points.size());
|
||||
for (const Point &point : hole.points) {
|
||||
size_t i = &point - &hole.points.front();
|
||||
p[i].x = point(0);
|
||||
p[i].y = point(1);
|
||||
}
|
||||
p.SetHole(true);
|
||||
}
|
||||
}
|
||||
return input;
|
||||
}
|
||||
|
||||
std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output)
|
||||
{
|
||||
size_t num_triangles = 0;
|
||||
for (const TPPLPoly &poly : output)
|
||||
if (poly.GetNumPoints() >= 3)
|
||||
num_triangles += (size_t)poly.GetNumPoints() - 2;
|
||||
std::vector<Point> triangles;
|
||||
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];
|
||||
triangles.emplace_back(coord_t(pt0->x), coord_t(pt0->y));
|
||||
triangles.emplace_back(coord_t(pt1->x), coord_t(pt1->y));
|
||||
triangles.emplace_back(coord_t(pt2->x), coord_t(pt2->y));
|
||||
}
|
||||
}
|
||||
}
|
||||
return triangles;
|
||||
}
|
||||
|
||||
void ExPolygon::triangulate_pp(Points *triangles) const
|
||||
{
|
||||
ExPolygons expp = union_ex(simplify_polygons(to_polygons(*this), true));
|
||||
std::list<TPPLPoly> input = expoly_to_polypartition_input(expp);
|
||||
// perform triangulation
|
||||
std::list<TPPLPoly> output;
|
||||
int res = TPPLPartition().Triangulate_MONO(&input, &output);
|
||||
// int TPPLPartition::Triangulate_EC(TPPLPolyList *inpolys, TPPLPolyList *triangles) {
|
||||
if (res != 1)
|
||||
throw std::runtime_error("Triangulation failed");
|
||||
*triangles = polypartition_output_to_triangles(output);
|
||||
}
|
||||
|
||||
// Uses the Poly2tri library maintained by Jan Niklas Hasse @jhasse // https://github.com/jhasse/poly2tri
|
||||
// See https://github.com/jhasse/poly2tri/blob/master/README.md for the limitations of the library!
|
||||
// No duplicate points are allowed, no very close points, holes must not touch outer contour etc.
|
||||
void ExPolygon::triangulate_p2t(Polygons* polygons) const
|
||||
{
|
||||
ExPolygons expp = simplify_polygons_ex(*this, true);
|
||||
|
||||
|
@ -478,16 +579,21 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const
|
|||
}
|
||||
|
||||
// perform triangulation
|
||||
cdt.Triangulate();
|
||||
std::vector<p2t::Triangle*> triangles = cdt.GetTriangles();
|
||||
|
||||
for (std::vector<p2t::Triangle*>::const_iterator triangle = triangles.begin(); triangle != triangles.end(); ++triangle) {
|
||||
Polygon p;
|
||||
for (int i = 0; i <= 2; ++i) {
|
||||
p2t::Point* point = (*triangle)->GetPoint(i);
|
||||
p.points.push_back(Point(point->x, point->y));
|
||||
try {
|
||||
cdt.Triangulate();
|
||||
std::vector<p2t::Triangle*> triangles = cdt.GetTriangles();
|
||||
|
||||
for (std::vector<p2t::Triangle*>::const_iterator triangle = triangles.begin(); triangle != triangles.end(); ++triangle) {
|
||||
Polygon p;
|
||||
for (int i = 0; i <= 2; ++i) {
|
||||
p2t::Point* point = (*triangle)->GetPoint(i);
|
||||
p.points.push_back(Point(point->x, point->y));
|
||||
}
|
||||
polygons->push_back(p);
|
||||
}
|
||||
polygons->push_back(p);
|
||||
} catch (const std::runtime_error & /* err */) {
|
||||
assert(false);
|
||||
// just ignore, don't triangulate
|
||||
}
|
||||
|
||||
for (p2t::Point *ptr : ContourPoints)
|
||||
|
@ -495,8 +601,7 @@ ExPolygon::triangulate_p2t(Polygons* polygons) const
|
|||
}
|
||||
}
|
||||
|
||||
Lines
|
||||
ExPolygon::lines() const
|
||||
Lines ExPolygon::lines() const
|
||||
{
|
||||
Lines lines = this->contour.lines();
|
||||
for (Polygons::const_iterator h = this->holes.begin(); h != this->holes.end(); ++h) {
|
||||
|
|
|
@ -6,6 +6,9 @@
|
|||
#include "Polyline.hpp"
|
||||
#include <vector>
|
||||
|
||||
// polygon class of the polypartition library
|
||||
class TPPLPoly;
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
class ExPolygon;
|
||||
|
@ -55,12 +58,13 @@ public:
|
|||
void simplify(double tolerance, ExPolygons* expolygons) const;
|
||||
void medial_axis(double max_width, double min_width, ThickPolylines* polylines) const;
|
||||
void medial_axis(double max_width, double min_width, Polylines* polylines) const;
|
||||
void get_trapezoids(Polygons* polygons) const;
|
||||
void get_trapezoids(Polygons* polygons, double angle) const;
|
||||
// void get_trapezoids(Polygons* polygons) const;
|
||||
// void get_trapezoids(Polygons* polygons, double angle) const;
|
||||
void get_trapezoids2(Polygons* polygons) const;
|
||||
void get_trapezoids2(Polygons* polygons, double angle) const;
|
||||
void triangulate(Polygons* polygons) const;
|
||||
void triangulate_pp(Polygons* polygons) const;
|
||||
// Triangulate into triples of points.
|
||||
void triangulate_pp(Points *triangles) const;
|
||||
void triangulate_p2t(Polygons* polygons) const;
|
||||
Lines lines() const;
|
||||
};
|
||||
|
@ -297,6 +301,10 @@ extern std::vector<BoundingBox> get_extents_vector(const ExPolygons &polygons);
|
|||
|
||||
extern bool remove_sticks(ExPolygon &poly);
|
||||
|
||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygons &expp);
|
||||
extern std::list<TPPLPoly> expoly_to_polypartition_input(const ExPolygon &ex);
|
||||
extern std::vector<Point> polypartition_output_to_triangles(const std::list<TPPLPoly> &output);
|
||||
|
||||
} // namespace Slic3r
|
||||
|
||||
// start Boost
|
||||
|
|
|
@ -41,7 +41,7 @@
|
|||
|
||||
namespace Slic3r {
|
||||
|
||||
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets )
|
||||
TriangleMesh::TriangleMesh(const Pointf3s &points, const std::vector<Vec3crd>& facets)
|
||||
: repaired(false)
|
||||
{
|
||||
stl_initialize(&this->stl);
|
||||
|
|
|
@ -1995,7 +1995,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
|
|||
{
|
||||
model = Model::read_from_file(filename);
|
||||
}
|
||||
catch (std::exception &e)
|
||||
catch (std::exception & /* ex */)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
@ -2014,7 +2014,7 @@ bool GLBed::on_init_from_file(const std::string& filename, bool useVBOs)
|
|||
else
|
||||
m_volume.indexed_vertex_array.load_mesh_flat_shading(mesh);
|
||||
|
||||
float color[4] = { 0.235f, 0.235, 0.235f, 1.0f };
|
||||
float color[4] = { 0.235f, 0.235f, 0.235f, 1.0f };
|
||||
set_color(color, 4);
|
||||
|
||||
m_volume.bounding_box = m_volume.indexed_vertex_array.bounding_box();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#include "GLCanvas3D.hpp"
|
||||
|
||||
#include "admesh/stl.h"
|
||||
#include "polypartition.h"
|
||||
#include "libslic3r/libslic3r.h"
|
||||
#include "libslic3r/ClipperUtils.hpp"
|
||||
#include "libslic3r/PrintConfig.hpp"
|
||||
|
@ -6538,6 +6539,219 @@ 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<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
|
||||
gluTessCallback(tess, GLU_TESS_BEGIN, (void(__stdcall*)(void))tessBeginCB);
|
||||
gluTessCallback(tess, GLU_TESS_END, (void(__stdcall*)(void))tessEndCB);
|
||||
gluTessCallback(tess, GLU_TESS_ERROR, (void(__stdcall*)(void))tessErrorCB);
|
||||
gluTessCallback(tess, GLU_TESS_VERTEX, (void(__stdcall*)())tessVertexCB);
|
||||
gluTessCallback(tess, GLU_TESS_COMBINE, (void (__stdcall*)(void))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(which == 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
|
||||
{
|
||||
if (!m_use_clipping_planes || wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA)
|
||||
|
@ -6555,34 +6769,32 @@ void GLCanvas3D::_render_sla_slices() const
|
|||
{
|
||||
const SLAPrintObject* obj = print_objects[i];
|
||||
|
||||
Pointf3s bottom_obj_triangles;
|
||||
Pointf3s bottom_sup_triangles;
|
||||
Pointf3s top_obj_triangles;
|
||||
Pointf3s top_sup_triangles;
|
||||
|
||||
double shift_z = obj->get_current_elevation();
|
||||
double min_z = clip_min_z - shift_z;
|
||||
double max_z = clip_max_z - shift_z;
|
||||
|
||||
if (m_sla_caps[0].matches(min_z))
|
||||
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_bottom = m_sla_caps[0].triangles.find(i);
|
||||
SlaCap::ObjectIdToTrianglesMap::iterator it_caps_top = m_sla_caps[1].triangles.find(i);
|
||||
{
|
||||
SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[0].triangles.find(i);
|
||||
if (it != m_sla_caps[0].triangles.end())
|
||||
{
|
||||
bottom_obj_triangles = it->second.object;
|
||||
bottom_sup_triangles = it->second.suppports;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_sla_caps[1].matches(max_z))
|
||||
{
|
||||
SlaCap::ObjectIdToTrianglesMap::const_iterator it = m_sla_caps[1].triangles.find(i);
|
||||
if (it != m_sla_caps[1].triangles.end())
|
||||
{
|
||||
top_obj_triangles = it->second.object;
|
||||
top_sup_triangles = it->second.suppports;
|
||||
if (it_caps_bottom == m_sla_caps[0].triangles.end())
|
||||
it_caps_bottom = m_sla_caps[0].triangles.emplace(i, SlaCap::Triangles()).first;
|
||||
if (! m_sla_caps[0].matches(min_z)) {
|
||||
m_sla_caps[0].z = min_z;
|
||||
it_caps_bottom->second.object.clear();
|
||||
it_caps_bottom->second.supports.clear();
|
||||
}
|
||||
if (it_caps_top == m_sla_caps[1].triangles.end())
|
||||
it_caps_top = m_sla_caps[1].triangles.emplace(i, SlaCap::Triangles()).first;
|
||||
if (! m_sla_caps[1].matches(max_z)) {
|
||||
m_sla_caps[1].z = max_z;
|
||||
it_caps_top->second.object.clear();
|
||||
it_caps_top->second.supports.clear();
|
||||
}
|
||||
}
|
||||
Pointf3s &bottom_obj_triangles = it_caps_bottom->second.object;
|
||||
Pointf3s &bottom_sup_triangles = it_caps_bottom->second.supports;
|
||||
Pointf3s &top_obj_triangles = it_caps_top->second.object;
|
||||
Pointf3s &top_sup_triangles = it_caps_top->second.supports;
|
||||
|
||||
const std::vector<SLAPrintObject::Instance>& instances = obj->instances();
|
||||
struct InstanceTransform
|
||||
|
@ -6608,86 +6820,22 @@ void GLCanvas3D::_render_sla_slices() const
|
|||
|
||||
if (it_min_z != index.end())
|
||||
{
|
||||
// calculate model bottom cap
|
||||
if (bottom_obj_triangles.empty() && (it_min_z->second.model_slices_idx < model_slices.size()))
|
||||
{
|
||||
// calculate model bottom cap
|
||||
const ExPolygons& polys = model_slices[it_min_z->second.model_slices_idx];
|
||||
for (const ExPolygon& poly : polys)
|
||||
{
|
||||
Polygons poly_triangles;
|
||||
poly.triangulate(&poly_triangles);
|
||||
for (const Polygon& t : poly_triangles)
|
||||
{
|
||||
for (int v = 2; v >= 0; --v)
|
||||
{
|
||||
bottom_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bottom_obj_triangles = triangulate_expolygons(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()))
|
||||
{
|
||||
// calculate support bottom cap
|
||||
const ExPolygons& polys = support_slices[it_min_z->second.support_slices_idx];
|
||||
for (const ExPolygon& poly : polys)
|
||||
{
|
||||
Polygons poly_triangles;
|
||||
poly.triangulate(&poly_triangles);
|
||||
for (const Polygon& t : poly_triangles)
|
||||
{
|
||||
for (int v = 2; v >= 0; --v)
|
||||
{
|
||||
bottom_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), min_z));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_sla_caps[0].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { bottom_obj_triangles, bottom_sup_triangles }));
|
||||
m_sla_caps[0].z = min_z;
|
||||
}
|
||||
bottom_sup_triangles = triangulate_expolygons(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()))
|
||||
{
|
||||
// calculate model top cap
|
||||
const ExPolygons& polys = model_slices[it_max_z->second.model_slices_idx];
|
||||
for (const ExPolygon& poly : polys)
|
||||
{
|
||||
Polygons poly_triangles;
|
||||
poly.triangulate(&poly_triangles);
|
||||
for (const Polygon& t : poly_triangles)
|
||||
{
|
||||
for (int v = 0; v < 3; ++v)
|
||||
{
|
||||
top_obj_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
top_obj_triangles = triangulate_expolygons(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()))
|
||||
{
|
||||
// calculate support top cap
|
||||
const ExPolygons& polys = support_slices[it_max_z->second.support_slices_idx];
|
||||
for (const ExPolygon& poly : polys)
|
||||
{
|
||||
Polygons poly_triangles;
|
||||
poly.triangulate(&poly_triangles);
|
||||
for (const Polygon& t : poly_triangles)
|
||||
{
|
||||
for (int v = 0; v < 3; ++v)
|
||||
{
|
||||
top_sup_triangles.emplace_back(to_3d(unscale(t.points[v]), max_z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m_sla_caps[1].triangles.insert(SlaCap::ObjectIdToTrianglesMap::value_type(i, { top_obj_triangles, top_sup_triangles }));
|
||||
m_sla_caps[1].z = max_z;
|
||||
top_sup_triangles = triangulate_expolygons(support_slices[it_max_z->second.support_slices_idx], max_z, false);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -790,7 +790,7 @@ private:
|
|||
struct Triangles
|
||||
{
|
||||
Pointf3s object;
|
||||
Pointf3s suppports;
|
||||
Pointf3s supports;
|
||||
};
|
||||
typedef std::map<unsigned int, Triangles> ObjectIdToTrianglesMap;
|
||||
double z;
|
||||
|
|
|
@ -245,8 +245,6 @@ void show_info(wxWindow* parent, const wxString& message, const wxString& title)
|
|||
|
||||
void warning_catcher(wxWindow* parent, const wxString& message)
|
||||
{
|
||||
if (message == "GLUquadricObjPtr | " + _(L("Attempt to free unreferenced scalar")) )
|
||||
return;
|
||||
wxMessageDialog msg(parent, message, _(L("Warning")), wxOK | wxICON_WARNING);
|
||||
msg.ShowModal();
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue