Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer into et_gcode_viewer
This commit is contained in:
commit
4f5aefc919
@ -120,6 +120,10 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||
mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() *
|
||||
mv->get_matrix();
|
||||
|
||||
bool is_left_handed = trafo_matrix.matrix().determinant() < 0.;
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glMultMatrixd(trafo_matrix.data()));
|
||||
|
||||
@ -130,6 +134,8 @@ void GLGizmoFdmSupports::render_triangles(const Selection& selection) const
|
||||
iva.render();
|
||||
}
|
||||
glsafe(::glPopMatrix());
|
||||
if (is_left_handed)
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
}
|
||||
if (clipping_plane_active)
|
||||
glsafe(::glDisable(GL_CLIP_PLANE0));
|
||||
@ -205,7 +211,6 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||
if (mv->is_model_part())
|
||||
++num_of_volumes;
|
||||
m_selected_facets.resize(num_of_volumes);
|
||||
m_neighbors.resize(num_of_volumes);
|
||||
|
||||
m_ivas.clear();
|
||||
m_ivas.resize(num_of_volumes);
|
||||
@ -235,17 +240,6 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||
}
|
||||
update_vertex_buffers(mesh, volume_id, FacetSupportType::ENFORCER);
|
||||
update_vertex_buffers(mesh, volume_id, FacetSupportType::BLOCKER);
|
||||
|
||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||
|
||||
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
||||
for (size_t i=0; i<mesh->its.indices.size(); ++i) {
|
||||
const stl_triangle_vertex_indices& ind = mesh->its.indices[i];
|
||||
m_neighbors[volume_id][3*i] = std::make_pair(ind(0), i);
|
||||
m_neighbors[volume_id][3*i+1] = std::make_pair(ind(1), i);
|
||||
m_neighbors[volume_id][3*i+2] = std::make_pair(ind(2), i);
|
||||
}
|
||||
std::sort(m_neighbors[volume_id].begin(), m_neighbors[volume_id].end());
|
||||
}
|
||||
}
|
||||
|
||||
@ -267,11 +261,6 @@ bool GLGizmoFdmSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||
}
|
||||
|
||||
|
||||
bool operator<(const GLGizmoFdmSupports::NeighborData& a, const GLGizmoFdmSupports::NeighborData& b) {
|
||||
return a.first < b.first;
|
||||
}
|
||||
|
||||
|
||||
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
||||
// The gizmo has an opportunity to react - if it does, it should return true so that the Canvas3D is
|
||||
// aware that the event was reacted to and stops trying to make different sense of it. If the gizmo
|
||||
@ -325,7 +314,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
const Transform3d& instance_trafo = mi->get_transformation().get_matrix();
|
||||
|
||||
std::vector<std::vector<std::pair<Vec3f, size_t>>> hit_positions_and_facet_ids;
|
||||
bool some_mesh_was_hit = false;
|
||||
bool clipped_mesh_was_hit = false;
|
||||
|
||||
Vec3f normal = Vec3f::Zero();
|
||||
Vec3f hit = Vec3f::Zero();
|
||||
@ -360,7 +349,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
{
|
||||
// In case this hit is clipped, skip it.
|
||||
if (is_mesh_point_clipped(hit.cast<double>())) {
|
||||
some_mesh_was_hit = true;
|
||||
clipped_mesh_was_hit = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -374,124 +363,119 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
}
|
||||
}
|
||||
}
|
||||
// We now know where the ray hit, let's save it and cast another ray
|
||||
if (closest_hit_mesh_id != size_t(-1)) // only if there is at least one hit
|
||||
some_mesh_was_hit = true;
|
||||
|
||||
if (some_mesh_was_hit) {
|
||||
// Now propagate the hits
|
||||
mesh_id = -1;
|
||||
const TriangleMesh* mesh = nullptr;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
++mesh_id;
|
||||
if (mesh_id == closest_hit_mesh_id) {
|
||||
mesh = &mv->mesh();
|
||||
break;
|
||||
}
|
||||
if (closest_hit_mesh_id == -1) {
|
||||
// In case we have no valid hit, we can return. The event will
|
||||
// be stopped in following two cases:
|
||||
// 1. clicking the clipping plane
|
||||
// 2. dragging while painting (to prevent scene rotations and moving the object)
|
||||
return clipped_mesh_was_hit
|
||||
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None);
|
||||
}
|
||||
|
||||
// Now propagate the hits
|
||||
mesh_id = -1;
|
||||
const TriangleMesh* mesh = nullptr;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
if (! mv->is_model_part())
|
||||
continue;
|
||||
++mesh_id;
|
||||
if (mesh_id == closest_hit_mesh_id) {
|
||||
mesh = &mv->mesh();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
bool update_both = false;
|
||||
bool update_both = false;
|
||||
|
||||
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
||||
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
||||
|
||||
// Calculate how far can a point be from the line (in mesh coords).
|
||||
// FIXME: The scaling of the mesh can be non-uniform.
|
||||
const Vec3d sf = Geometry::Transformation(trafo_matrix).get_scaling_factor();
|
||||
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
||||
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
||||
// Calculate how far can a point be from the line (in mesh coords).
|
||||
// FIXME: The scaling of the mesh can be non-uniform.
|
||||
const Vec3d sf = Geometry::Transformation(trafo_matrix).get_scaling_factor();
|
||||
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
||||
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
||||
|
||||
const std::pair<Vec3f, size_t>& hit_and_facet = { closest_hit, closest_facet };
|
||||
const std::pair<Vec3f, size_t>& hit_and_facet = { closest_hit, closest_facet };
|
||||
|
||||
const std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
||||
// Calculate direction from camera to the hit (in mesh coords):
|
||||
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
||||
|
||||
// Calculate direction from camera to the hit (in mesh coords):
|
||||
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
||||
// A lambda to calculate distance from the centerline:
|
||||
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float {
|
||||
Vec3f diff = hit_and_facet.first - point;
|
||||
return (diff - diff.dot(dir) * dir).squaredNorm();
|
||||
};
|
||||
|
||||
// A lambda to calculate distance from the centerline:
|
||||
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float {
|
||||
Vec3f diff = hit_and_facet.first - point;
|
||||
return (diff - diff.dot(dir) * dir).squaredNorm();
|
||||
};
|
||||
|
||||
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
||||
auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool {
|
||||
return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.);
|
||||
};
|
||||
// Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores
|
||||
// pairs of vertex_idx - facet_idx and is sorted with respect to the former. Neighboring facet index can be
|
||||
// quickly found by finding a vertex in the list and read the respective facet ids.
|
||||
std::vector<size_t> facets_to_select{hit_and_facet.second};
|
||||
NeighborData vertex = std::make_pair(0, 0);
|
||||
std::vector<bool> visited(m_selected_facets[mesh_id].size(), false); // keep track of facets we already processed
|
||||
size_t facet_idx = 0; // index into facets_to_select
|
||||
auto it = neighbors.end();
|
||||
while (facet_idx < facets_to_select.size()) {
|
||||
size_t facet = facets_to_select[facet_idx];
|
||||
if (! visited[facet]) {
|
||||
// check all three vertices and in case they're close enough, find the remaining facets
|
||||
// and add them to the list to be proccessed later
|
||||
for (size_t i=0; i<3; ++i) {
|
||||
vertex.first = mesh->its.indices[facet](i); // vertex index
|
||||
float dist = squared_distance_from_line(mesh->its.vertices[vertex.first]);
|
||||
if (dist < limit) {
|
||||
it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex);
|
||||
while (it != neighbors.end() && it->first == vertex.first) {
|
||||
if (it->second != facet && faces_camera(it->second))
|
||||
facets_to_select.push_back(it->second);
|
||||
++it;
|
||||
}
|
||||
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
||||
auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool {
|
||||
return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.);
|
||||
};
|
||||
// Now start with the facet the pointer points to and check all adjacent facets.
|
||||
std::vector<size_t> facets_to_select{hit_and_facet.second};
|
||||
std::vector<bool> visited(m_selected_facets[mesh_id].size(), false); // keep track of facets we already processed
|
||||
size_t facet_idx = 0; // index into facets_to_select
|
||||
while (facet_idx < facets_to_select.size()) {
|
||||
size_t facet = facets_to_select[facet_idx];
|
||||
if (! visited[facet]) {
|
||||
// check all three vertices and in case they're close enough,
|
||||
// add neighboring facets to be proccessed later
|
||||
for (size_t i=0; i<3; ++i) {
|
||||
float dist = squared_distance_from_line(
|
||||
mesh->its.vertices[mesh->its.indices[facet](i)]);
|
||||
if (dist < limit) {
|
||||
for (int n=0; n<3; ++n) {
|
||||
if (faces_camera(mesh->stl.neighbors_start[facet].neighbor[n]))
|
||||
facets_to_select.push_back(mesh->stl.neighbors_start[facet].neighbor[n]);
|
||||
}
|
||||
}
|
||||
visited[facet] = true;
|
||||
}
|
||||
++facet_idx;
|
||||
visited[facet] = true;
|
||||
}
|
||||
|
||||
std::vector<size_t> new_facets;
|
||||
new_facets.reserve(facets_to_select.size());
|
||||
|
||||
// Now just select all facets that passed and remember which
|
||||
// ones have really changed state.
|
||||
for (size_t next_facet : facets_to_select) {
|
||||
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||
|
||||
if (facet != new_state) {
|
||||
if (facet != FacetSupportType::NONE) {
|
||||
// this triangle is currently in the other VBA.
|
||||
// Both VBAs need to be refreshed.
|
||||
update_both = true;
|
||||
}
|
||||
facet = new_state;
|
||||
new_facets.push_back(next_facet);
|
||||
}
|
||||
}
|
||||
|
||||
if (! new_facets.empty()) {
|
||||
if (new_state != FacetSupportType::NONE) {
|
||||
// append triangles into the respective VBA
|
||||
update_vertex_buffers(mesh, mesh_id, new_state, &new_facets);
|
||||
if (update_both) {
|
||||
auto other = new_state == FacetSupportType::ENFORCER
|
||||
? FacetSupportType::BLOCKER
|
||||
: FacetSupportType::ENFORCER;
|
||||
update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA
|
||||
}
|
||||
}
|
||||
else {
|
||||
update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER);
|
||||
update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_button_down == Button::None)
|
||||
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
||||
return true;
|
||||
++facet_idx;
|
||||
}
|
||||
if (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)
|
||||
return true;
|
||||
|
||||
std::vector<size_t> new_facets;
|
||||
new_facets.reserve(facets_to_select.size());
|
||||
|
||||
// Now just select all facets that passed and remember which
|
||||
// ones have really changed state.
|
||||
for (size_t next_facet : facets_to_select) {
|
||||
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||
|
||||
if (facet != new_state) {
|
||||
if (facet != FacetSupportType::NONE) {
|
||||
// this triangle is currently in the other VBA.
|
||||
// Both VBAs need to be refreshed.
|
||||
update_both = true;
|
||||
}
|
||||
facet = new_state;
|
||||
new_facets.push_back(next_facet);
|
||||
}
|
||||
}
|
||||
|
||||
if (! new_facets.empty()) {
|
||||
if (new_state != FacetSupportType::NONE) {
|
||||
// append triangles into the respective VBA
|
||||
update_vertex_buffers(mesh, mesh_id, new_state, &new_facets);
|
||||
if (update_both) {
|
||||
auto other = new_state == FacetSupportType::ENFORCER
|
||||
? FacetSupportType::BLOCKER
|
||||
: FacetSupportType::ENFORCER;
|
||||
update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA
|
||||
}
|
||||
}
|
||||
else {
|
||||
update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER);
|
||||
update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (m_button_down == Button::None)
|
||||
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
||||
@ -809,7 +793,6 @@ void GLGizmoFdmSupports::on_set_state()
|
||||
}
|
||||
m_old_mo_id = -1;
|
||||
m_ivas.clear();
|
||||
m_neighbors.clear();
|
||||
m_selected_facets.clear();
|
||||
}
|
||||
m_old_state = m_state;
|
||||
|
@ -49,7 +49,6 @@ public:
|
||||
~GLGizmoFdmSupports() override;
|
||||
void set_fdm_support_data(ModelObject* model_object, const Selection& selection);
|
||||
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
|
||||
using NeighborData = std::pair<size_t, size_t>;
|
||||
|
||||
|
||||
private:
|
||||
@ -86,8 +85,6 @@ private:
|
||||
Button m_button_down = Button::None;
|
||||
EState m_old_state = Off; // to be able to see that the gizmo has just been closed (see on_set_state)
|
||||
|
||||
std::vector<std::vector<NeighborData>> m_neighbors; // pairs of vertex_index - facet_index for each mesh
|
||||
|
||||
protected:
|
||||
void on_set_state() override;
|
||||
void on_start_dragging() override;
|
||||
|
@ -1,7 +1,6 @@
|
||||
// Include GLGizmoBase.hpp before I18N.hpp as it includes some libigl code, which overrides our localization "L" macro.
|
||||
#include "GLGizmoFlatten.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Gizmos/GLGizmosCommon.hpp"
|
||||
|
||||
#include <numeric>
|
||||
@ -80,12 +79,7 @@ void GLGizmoFlatten::on_render() const
|
||||
else
|
||||
glsafe(::glColor4f(0.9f, 0.9f, 0.9f, 0.5f));
|
||||
|
||||
::glBegin(GL_POLYGON);
|
||||
for (const Vec3d& vertex : m_planes[i].vertices)
|
||||
{
|
||||
::glVertex3dv(vertex.data());
|
||||
}
|
||||
glsafe(::glEnd());
|
||||
m_planes[i].vbo.render();
|
||||
}
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
@ -112,12 +106,7 @@ void GLGizmoFlatten::on_render_for_picking() const
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i)
|
||||
{
|
||||
glsafe(::glColor4fv(picking_color_component(i).data()));
|
||||
::glBegin(GL_POLYGON);
|
||||
for (const Vec3d& vertex : m_planes[i].vertices)
|
||||
{
|
||||
::glVertex3dv(vertex.data());
|
||||
}
|
||||
glsafe(::glEnd());
|
||||
m_planes[i].vbo.render();
|
||||
}
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
@ -181,7 +170,7 @@ void GLGizmoFlatten::update_planes()
|
||||
if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) {
|
||||
stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex;
|
||||
for (int j=0; j<3; ++j)
|
||||
m_planes.back().vertices.emplace_back((double)first_vertex[j](0), (double)first_vertex[j](1), (double)first_vertex[j](2));
|
||||
m_planes.back().vertices.emplace_back(first_vertex[j].cast<double>());
|
||||
|
||||
facet_visited[facet_idx] = true;
|
||||
for (int j = 0; j < 3; ++ j) {
|
||||
@ -193,15 +182,16 @@ void GLGizmoFlatten::update_planes()
|
||||
}
|
||||
m_planes.back().normal = normal_ptr->cast<double>();
|
||||
|
||||
Pointf3s& verts = m_planes.back().vertices;
|
||||
// Now we'll transform all the points into world coordinates, so that the areas, angles and distances
|
||||
// make real sense.
|
||||
m_planes.back().vertices = transform(m_planes.back().vertices, inst_matrix);
|
||||
verts = transform(verts, inst_matrix);
|
||||
|
||||
// if this is a just a very small triangle, remove it to speed up further calculations (it would be rejected later anyway):
|
||||
if (m_planes.back().vertices.size() == 3 &&
|
||||
((m_planes.back().vertices[0] - m_planes.back().vertices[1]).norm() < minimal_side
|
||||
|| (m_planes.back().vertices[0] - m_planes.back().vertices[2]).norm() < minimal_side
|
||||
|| (m_planes.back().vertices[1] - m_planes.back().vertices[2]).norm() < minimal_side))
|
||||
if (verts.size() == 3 &&
|
||||
((verts[0] - verts[1]).norm() < minimal_side
|
||||
|| (verts[0] - verts[2]).norm() < minimal_side
|
||||
|| (verts[1] - verts[2]).norm() < minimal_side))
|
||||
m_planes.pop_back();
|
||||
}
|
||||
|
||||
@ -246,7 +236,7 @@ void GLGizmoFlatten::update_planes()
|
||||
discard = true;
|
||||
else {
|
||||
// We also check the inner angles and discard polygons with angles smaller than the following threshold
|
||||
const double angle_threshold = ::cos(10.0 * (double)PI / 180.0);
|
||||
constexpr double angle_threshold = ::cos(10.0 * (double)PI / 180.0);
|
||||
|
||||
for (unsigned int i = 0; i < polygon.size(); ++i) {
|
||||
const Vec3d& prec = polygon[(i == 0) ? polygon.size() - 1 : i - 1];
|
||||
@ -334,6 +324,21 @@ void GLGizmoFlatten::update_planes()
|
||||
m_first_instance_mirror = mo->instances.front()->get_mirror();
|
||||
m_old_model_object = mo;
|
||||
|
||||
// And finally create respective VBOs. The polygon is convex with
|
||||
// the vertices in order, so triangulation is trivial.
|
||||
for (auto& plane : m_planes) {
|
||||
plane.vbo.reserve(plane.vertices.size());
|
||||
for (const auto& vert : plane.vertices)
|
||||
plane.vbo.push_geometry(vert, plane.normal);
|
||||
for (size_t i=1; i<plane.vertices.size()-1; ++i)
|
||||
plane.vbo.push_triangle(0, i, i+1); // triangle fan
|
||||
plane.vbo.finalize_geometry(true);
|
||||
// FIXME: vertices should really be local, they need not
|
||||
// persist now when we use VBOs
|
||||
plane.vertices.clear();
|
||||
plane.vertices.shrink_to_fit();
|
||||
}
|
||||
|
||||
m_planes_valid = true;
|
||||
}
|
||||
|
||||
|
@ -16,7 +16,8 @@ private:
|
||||
mutable Vec3d m_normal;
|
||||
|
||||
struct PlaneData {
|
||||
std::vector<Vec3d> vertices;
|
||||
std::vector<Vec3d> vertices; // should be in fact local in update_planes()
|
||||
GLIndexedVertexArray vbo;
|
||||
Vec3d normal;
|
||||
float area;
|
||||
};
|
||||
|
@ -898,6 +898,7 @@ void GLGizmoSlaSupports::on_set_state()
|
||||
// Set default head diameter from config.
|
||||
const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
m_new_point_head_diameter = static_cast<const ConfigOptionFloat*>(cfg.option("support_head_front_diameter"))->value;
|
||||
m_c->instances_hider()->show_supports(true);
|
||||
}
|
||||
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
||||
bool will_ask = mo && m_editing_mode && unsaved_changes();
|
||||
|
@ -342,15 +342,11 @@ void ObjectClipper::render_cut() const
|
||||
clipper->set_plane(*m_clp);
|
||||
clipper->set_transformation(trafo);
|
||||
|
||||
if (! clipper->get_triangles().empty()) {
|
||||
::glPushMatrix();
|
||||
::glColor3f(1.0f, 0.37f, 0.0f);
|
||||
::glBegin(GL_TRIANGLES);
|
||||
for (const Vec3f& point : clipper->get_triangles())
|
||||
::glVertex3f(point(0), point(1), point(2));
|
||||
::glEnd();
|
||||
::glPopMatrix();
|
||||
}
|
||||
::glPushMatrix();
|
||||
::glColor3f(1.0f, 0.37f, 0.0f);
|
||||
clipper->render_cut();
|
||||
::glPopMatrix();
|
||||
|
||||
++clipper_id;
|
||||
}
|
||||
}
|
||||
@ -457,15 +453,10 @@ void SupportsClipper::render_cut() const
|
||||
m_clipper->set_plane(*ocl->get_clipping_plane());
|
||||
m_clipper->set_transformation(supports_trafo);
|
||||
|
||||
if (! m_clipper->get_triangles().empty()) {
|
||||
::glPushMatrix();
|
||||
::glColor3f(1.0f, 0.f, 0.37f);
|
||||
::glBegin(GL_TRIANGLES);
|
||||
for (const Vec3f& point : m_clipper->get_triangles())
|
||||
::glVertex3f(point(0), point(1), point(2));
|
||||
::glEnd();
|
||||
::glPopMatrix();
|
||||
}
|
||||
::glPushMatrix();
|
||||
::glColor3f(1.0f, 0.f, 0.37f);
|
||||
m_clipper->render_cut();
|
||||
::glPopMatrix();
|
||||
}
|
||||
|
||||
|
||||
|
@ -27,7 +27,6 @@ void MeshClipper::set_mesh(const TriangleMesh& mesh)
|
||||
m_mesh = &mesh;
|
||||
m_triangles_valid = false;
|
||||
m_triangles2d.resize(0);
|
||||
m_triangles3d.resize(0);
|
||||
m_tms.reset(nullptr);
|
||||
}
|
||||
}
|
||||
@ -40,18 +39,17 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo)
|
||||
m_trafo = trafo;
|
||||
m_triangles_valid = false;
|
||||
m_triangles2d.resize(0);
|
||||
m_triangles3d.resize(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
const std::vector<Vec3f>& MeshClipper::get_triangles()
|
||||
void MeshClipper::render_cut()
|
||||
{
|
||||
if (! m_triangles_valid)
|
||||
recalculate_triangles();
|
||||
|
||||
return m_triangles3d;
|
||||
m_vertex_array.render();
|
||||
}
|
||||
|
||||
|
||||
@ -67,29 +65,35 @@ void MeshClipper::recalculate_triangles()
|
||||
const Vec3f& scaling = m_trafo.get_scaling_factor().cast<float>();
|
||||
// Calculate clipping plane normal in mesh coordinates.
|
||||
Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_plane.get_normal().cast<float>();
|
||||
Vec3f up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
||||
Vec3d up (up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
||||
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
|
||||
float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm());
|
||||
|
||||
// Now do the cutting
|
||||
std::vector<ExPolygons> list_of_expolys;
|
||||
m_tms->set_up_direction(up);
|
||||
m_tms->set_up_direction(up.cast<float>());
|
||||
m_tms->slice(std::vector<float>{height_mesh}, SlicingMode::Regular, 0.f, &list_of_expolys, [](){});
|
||||
m_triangles2d = triangulate_expolygons_2f(list_of_expolys[0], m_trafo.get_matrix().matrix().determinant() < 0.);
|
||||
|
||||
// Rotate the cut into world coords:
|
||||
Eigen::Quaternionf q;
|
||||
q.setFromTwoVectors(Vec3f::UnitZ(), up);
|
||||
Transform3f tr = Transform3f::Identity();
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), up);
|
||||
Transform3d tr = Transform3d::Identity();
|
||||
tr.rotate(q);
|
||||
tr = m_trafo.get_matrix().cast<float>() * tr;
|
||||
tr = m_trafo.get_matrix() * tr;
|
||||
|
||||
m_triangles3d.clear();
|
||||
m_triangles3d.reserve(m_triangles2d.size());
|
||||
for (const Vec2f& pt : m_triangles2d) {
|
||||
m_triangles3d.push_back(Vec3f(pt(0), pt(1), height_mesh+0.001f));
|
||||
m_triangles3d.back() = tr * m_triangles3d.back();
|
||||
}
|
||||
// to avoid z-fighting
|
||||
height_mesh += 0.001f;
|
||||
|
||||
m_vertex_array.release_geometry();
|
||||
for (auto it=m_triangles2d.cbegin(); it != m_triangles2d.cend(); it=it+3) {
|
||||
m_vertex_array.push_geometry(tr * Vec3d((*(it+0))(0), (*(it+0))(1), height_mesh), up);
|
||||
m_vertex_array.push_geometry(tr * Vec3d((*(it+1))(0), (*(it+1))(1), height_mesh), up);
|
||||
m_vertex_array.push_geometry(tr * Vec3d((*(it+2))(0), (*(it+2))(1), height_mesh), up);
|
||||
size_t idx = it - m_triangles2d.cbegin();
|
||||
m_vertex_array.push_triangle(idx, idx+1, idx+2);
|
||||
}
|
||||
m_vertex_array.finalize_geometry(true);
|
||||
|
||||
m_triangles_valid = true;
|
||||
}
|
||||
|
@ -6,7 +6,7 @@
|
||||
#include "libslic3r/SLA/EigenMesh3D.hpp"
|
||||
#include "admesh/stl.h"
|
||||
|
||||
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
#include <cfloat>
|
||||
|
||||
@ -82,9 +82,9 @@ public:
|
||||
// into world coordinates.
|
||||
void set_transformation(const Geometry::Transformation& trafo);
|
||||
|
||||
// Return the triangulated cut. The points are returned directly
|
||||
// in world coordinates.
|
||||
const std::vector<Vec3f>& get_triangles();
|
||||
// Render the triangulated cut. Transformation matrices should
|
||||
// be set in world coords.
|
||||
void render_cut();
|
||||
|
||||
private:
|
||||
void recalculate_triangles();
|
||||
@ -93,7 +93,7 @@ private:
|
||||
const TriangleMesh* m_mesh = nullptr;
|
||||
ClippingPlane m_plane;
|
||||
std::vector<Vec2f> m_triangles2d;
|
||||
std::vector<Vec3f> m_triangles3d;
|
||||
GLIndexedVertexArray m_vertex_array;
|
||||
bool m_triangles_valid = false;
|
||||
std::unique_ptr<TriangleMeshSlicer> m_tms;
|
||||
};
|
||||
|
Loading…
Reference in New Issue
Block a user