Calculating the transformations is now only performed by the MeshClipper
Attempted to get mirroring right (that never worked correctly with the clipping plane in the sla gizmo) The transformation of the support mesh is kind of a mystery to me, hopefully it is right Also cleaned the code a bit (removed commented-out code, unused variables, etc)
This commit is contained in:
parent
546917830b
commit
9782701dd4
4 changed files with 85 additions and 117 deletions
|
@ -28,7 +28,6 @@ GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& ic
|
||||||
, m_its(nullptr)
|
, m_its(nullptr)
|
||||||
{
|
{
|
||||||
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||||
m_old_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
|
||||||
m_quadric = ::gluNewQuadric();
|
m_quadric = ::gluNewQuadric();
|
||||||
if (m_quadric != nullptr)
|
if (m_quadric != nullptr)
|
||||||
// using GLU_FILL does not work when the instance's transformation
|
// using GLU_FILL does not work when the instance's transformation
|
||||||
|
@ -140,34 +139,19 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
if (m_clipping_plane_distance == 0.f)
|
if (m_clipping_plane_distance == 0.f)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
const Vec3d& center = m_model_object->instances[m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift);
|
// Get transformation of the instance
|
||||||
|
|
||||||
// First cache instance transformation to be used later.
|
|
||||||
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
const GLVolume* vol = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||||
Geometry::Transformation trafo = vol->get_instance_transformation();
|
Geometry::Transformation trafo = vol->get_instance_transformation();
|
||||||
Transform3f instance_matrix = trafo.get_matrix().cast<float>();
|
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
||||||
Transform3f instance_matrix_no_translation_no_scaling = trafo.get_matrix(true,false,true).cast<float>();
|
|
||||||
Vec3f scaling = vol->get_instance_scaling_factor().cast<float>();
|
|
||||||
Vec3d instance_offset = vol->get_instance_offset();
|
|
||||||
// Calculate distance from mesh origin to the clipping plane (in mesh coordinates).
|
|
||||||
Vec3f up_noscale = instance_matrix_no_translation_no_scaling.inverse() * m_clipping_plane->get_normal().cast<float>();
|
|
||||||
Vec3f up = Vec3f(up_noscale(0)*scaling(0), up_noscale(1)*scaling(1), up_noscale(2)*scaling(2));
|
|
||||||
float height_mesh = m_clipping_plane->distance(center) * (up_noscale.norm()/up.norm());
|
|
||||||
|
|
||||||
|
// Get transformation of supports
|
||||||
// Get transformation of the supports and calculate how far from its origin the clipping plane is.
|
Geometry::Transformation supports_trafo;
|
||||||
Transform3d supports_trafo = Transform3d::Identity();
|
supports_trafo.set_offset(Vec3d(trafo.get_offset()(0), trafo.get_offset()(1), vol->get_sla_shift_z()));
|
||||||
supports_trafo = supports_trafo.rotate(Eigen::AngleAxisd(vol->get_instance_rotation()(2), Vec3d::UnitZ()));
|
supports_trafo.set_rotation(Vec3d(0., 0., trafo.get_rotation()(2)));
|
||||||
Vec3f up_supports = (supports_trafo.inverse() * m_clipping_plane->get_normal()).cast<float>();
|
// I don't know why, but following seems to be correct.
|
||||||
supports_trafo = supports_trafo.pretranslate(Vec3d(instance_offset(0), instance_offset(1), vol->get_sla_shift_z()));
|
supports_trafo.set_mirror(Vec3d(trafo.get_mirror()(0) * trafo.get_mirror()(1) * trafo.get_mirror()(2),
|
||||||
// Instance and supports origin do not coincide, so the following is quite messy:
|
1,
|
||||||
float height_supports = height_mesh * (up.norm() / up_supports.norm()) + instance_offset(2) * (m_clipping_plane->get_normal()(2));
|
1.));
|
||||||
|
|
||||||
// In case either of these was recently changed, the cached triangulated ExPolygons are invalid now.
|
|
||||||
// We are gonna recalculate them both for the object and for the support structures.
|
|
||||||
if (*m_old_clipping_plane != *m_clipping_plane) {
|
|
||||||
|
|
||||||
*m_old_clipping_plane = *m_clipping_plane;
|
|
||||||
|
|
||||||
// Now initialize the TMS for the object, perform the cut and save the result.
|
// Now initialize the TMS for the object, perform the cut and save the result.
|
||||||
if (! m_object_clipper) {
|
if (! m_object_clipper) {
|
||||||
|
@ -175,7 +159,6 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
m_object_clipper->set_mesh(*m_mesh);
|
m_object_clipper->set_mesh(*m_mesh);
|
||||||
}
|
}
|
||||||
m_object_clipper->set_plane(*m_clipping_plane);
|
m_object_clipper->set_plane(*m_clipping_plane);
|
||||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
|
||||||
m_object_clipper->set_transformation(trafo);
|
m_object_clipper->set_transformation(trafo);
|
||||||
|
|
||||||
|
|
||||||
|
@ -200,39 +183,27 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp;
|
size_t timestamp = print_object->step_state_with_timestamp(slaposSupportTree).timestamp;
|
||||||
|
|
||||||
if (! m_supports_clipper || (int)timestamp != m_old_timestamp) {
|
if (! m_supports_clipper || (int)timestamp != m_old_timestamp) {
|
||||||
// The timestamp has changed - stash the mesh and initialize the TMS.
|
// The timestamp has changed.
|
||||||
m_supports_mesh = &print_object->support_mesh();
|
|
||||||
m_supports_clipper.reset(new MeshClipper);
|
m_supports_clipper.reset(new MeshClipper);
|
||||||
// The mesh should already have the shared vertices calculated.
|
// The mesh should already have the shared vertices calculated.
|
||||||
m_supports_clipper->set_mesh(*m_supports_mesh);
|
m_supports_clipper->set_mesh(print_object->support_mesh());
|
||||||
m_old_timestamp = timestamp;
|
m_old_timestamp = timestamp;
|
||||||
}
|
}
|
||||||
|
|
||||||
// The TMS is initialized - let's do the cutting:
|
|
||||||
m_supports_clipper->set_plane(*m_clipping_plane);
|
m_supports_clipper->set_plane(*m_clipping_plane);
|
||||||
m_supports_clipper->set_transformation(Geometry::Transformation(supports_trafo));
|
m_supports_clipper->set_transformation(supports_trafo);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
// The supports are not valid. We better dump the cached data.
|
// The supports are not valid. We better dump the cached data.
|
||||||
m_supports_clipper.reset();
|
m_supports_clipper.reset();
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
// At this point we have the triangulated cuts for both the object and supports - let's render.
|
// At this point we have the triangulated cuts for both the object and supports - let's render.
|
||||||
if (! m_object_clipper->get_triangles().empty()) {
|
if (! m_object_clipper->get_triangles().empty()) {
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glTranslated(0.0, 0.0, m_z_shift);
|
|
||||||
::glMultMatrixf(instance_matrix.data());
|
|
||||||
Eigen::Quaternionf q;
|
|
||||||
q.setFromTwoVectors(Vec3f::UnitZ(), up);
|
|
||||||
Eigen::AngleAxisf aa(q);
|
|
||||||
::glRotatef(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2));
|
|
||||||
::glTranslatef(0.f, 0.f, 0.01f); // to make sure the cut does not intersect the structure itself
|
|
||||||
::glColor3f(1.0f, 0.37f, 0.0f);
|
::glColor3f(1.0f, 0.37f, 0.0f);
|
||||||
::glBegin(GL_TRIANGLES);
|
::glBegin(GL_TRIANGLES);
|
||||||
for (const Vec2f& point : m_object_clipper->get_triangles())
|
for (const Vec3f& point : m_object_clipper->get_triangles())
|
||||||
::glVertex3f(point(0), point(1), height_mesh);
|
::glVertex3f(point(0), point(1), point(2));
|
||||||
|
|
||||||
::glEnd();
|
::glEnd();
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
@ -240,17 +211,10 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||||
if (m_supports_clipper && ! m_supports_clipper->get_triangles().empty() && !m_editing_mode) {
|
if (m_supports_clipper && ! m_supports_clipper->get_triangles().empty() && !m_editing_mode) {
|
||||||
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
// The supports are hidden in the editing mode, so it makes no sense to render the cuts.
|
||||||
::glPushMatrix();
|
::glPushMatrix();
|
||||||
::glMultMatrixd(supports_trafo.data());
|
|
||||||
Eigen::Quaternionf q;
|
|
||||||
q.setFromTwoVectors(Vec3f::UnitZ(), up_supports);
|
|
||||||
Eigen::AngleAxisf aa(q);
|
|
||||||
::glRotatef(aa.angle() * (180./M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2));
|
|
||||||
::glTranslatef(0.f, 0.f, 0.01f);
|
|
||||||
::glColor3f(1.0f, 0.f, 0.37f);
|
::glColor3f(1.0f, 0.f, 0.37f);
|
||||||
::glBegin(GL_TRIANGLES);
|
::glBegin(GL_TRIANGLES);
|
||||||
for (const Vec2f& point : m_supports_clipper->get_triangles())
|
for (const Vec3f& point : m_supports_clipper->get_triangles())
|
||||||
::glVertex3f(point(0), point(1), height_supports);
|
::glVertex3f(point(0), point(1), point(2));
|
||||||
|
|
||||||
::glEnd();
|
::glEnd();
|
||||||
::glPopMatrix();
|
::glPopMatrix();
|
||||||
}
|
}
|
||||||
|
|
|
@ -115,7 +115,6 @@ private:
|
||||||
|
|
||||||
float m_clipping_plane_distance = 0.f;
|
float m_clipping_plane_distance = 0.f;
|
||||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||||
std::unique_ptr<ClippingPlane> m_old_clipping_plane;
|
|
||||||
|
|
||||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||||
|
|
|
@ -18,7 +18,8 @@ void MeshClipper::set_mesh(const TriangleMesh& mesh)
|
||||||
if (m_mesh != &mesh) {
|
if (m_mesh != &mesh) {
|
||||||
m_mesh = &mesh;
|
m_mesh = &mesh;
|
||||||
m_triangles_valid = false;
|
m_triangles_valid = false;
|
||||||
m_triangles.resize(0);
|
m_triangles2d.resize(0);
|
||||||
|
m_triangles3d.resize(0);
|
||||||
m_tms.reset(nullptr);
|
m_tms.reset(nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -28,17 +29,19 @@ void MeshClipper::set_transformation(const Geometry::Transformation& trafo)
|
||||||
if (! m_trafo.get_matrix().isApprox(trafo.get_matrix())) {
|
if (! m_trafo.get_matrix().isApprox(trafo.get_matrix())) {
|
||||||
m_trafo = trafo;
|
m_trafo = trafo;
|
||||||
m_triangles_valid = false;
|
m_triangles_valid = false;
|
||||||
m_triangles.resize(0);
|
m_triangles2d.resize(0);
|
||||||
|
m_triangles3d.resize(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
const std::vector<Vec2f>& MeshClipper::get_triangles()
|
|
||||||
|
const std::vector<Vec3f>& MeshClipper::get_triangles()
|
||||||
{
|
{
|
||||||
if (! m_triangles_valid)
|
if (! m_triangles_valid)
|
||||||
recalculate_triangles();
|
recalculate_triangles();
|
||||||
|
|
||||||
return m_triangles;
|
return m_triangles3d;
|
||||||
}
|
}
|
||||||
|
|
||||||
void MeshClipper::recalculate_triangles()
|
void MeshClipper::recalculate_triangles()
|
||||||
|
@ -49,34 +52,37 @@ void MeshClipper::recalculate_triangles()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
auto up_and_height = get_mesh_cut_normal();
|
const Transform3f& instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
|
||||||
Vec3f up = up_and_height.first;
|
const Vec3f& scaling = m_trafo.get_scaling_factor().cast<float>();
|
||||||
float height_mesh = up_and_height.second;
|
// 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));
|
||||||
|
// 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;
|
std::vector<ExPolygons> list_of_expolys;
|
||||||
m_tms->set_up_direction(up);
|
m_tms->set_up_direction(up);
|
||||||
m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){});
|
m_tms->slice(std::vector<float>{height_mesh}, 0.f, &list_of_expolys, [](){});
|
||||||
m_triangles = triangulate_expolygons_2f(list_of_expolys[0]);
|
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();
|
||||||
|
tr.rotate(q);
|
||||||
|
tr = m_trafo.get_matrix().cast<float>() * 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();
|
||||||
|
}
|
||||||
|
|
||||||
m_triangles_valid = true;
|
m_triangles_valid = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
std::pair<Vec3f, float> MeshClipper::get_mesh_cut_normal() const
|
|
||||||
{
|
|
||||||
Transform3f instance_matrix_no_translation_no_scaling = m_trafo.get_matrix(true,false,true).cast<float>();
|
|
||||||
Vec3f scaling = m_trafo.get_scaling_factor().cast<float>();
|
|
||||||
|
|
||||||
// Calculate distance from mesh origin to the clipping plane (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));
|
|
||||||
|
|
||||||
float height_mesh = m_plane.distance(m_trafo.get_offset()) * (up_noscale.norm()/up.norm());
|
|
||||||
|
|
||||||
|
|
||||||
return std::make_pair(up, height_mesh);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
} // namespace GUI
|
} // namespace GUI
|
||||||
|
|
|
@ -13,17 +13,16 @@ public:
|
||||||
void set_mesh(const TriangleMesh& mesh);
|
void set_mesh(const TriangleMesh& mesh);
|
||||||
void set_transformation(const Geometry::Transformation& trafo);
|
void set_transformation(const Geometry::Transformation& trafo);
|
||||||
|
|
||||||
const std::vector<Vec2f>& get_triangles();
|
const std::vector<Vec3f>& get_triangles();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void recalculate_triangles();
|
void recalculate_triangles();
|
||||||
std::pair<Vec3f, float> get_mesh_cut_normal() const;
|
|
||||||
|
|
||||||
|
|
||||||
Geometry::Transformation m_trafo;
|
Geometry::Transformation m_trafo;
|
||||||
const TriangleMesh* m_mesh = nullptr;
|
const TriangleMesh* m_mesh = nullptr;
|
||||||
ClippingPlane m_plane;
|
ClippingPlane m_plane;
|
||||||
std::vector<Vec2f> m_triangles;
|
std::vector<Vec2f> m_triangles2d;
|
||||||
|
std::vector<Vec3f> m_triangles3d;
|
||||||
bool m_triangles_valid = false;
|
bool m_triangles_valid = false;
|
||||||
std::unique_ptr<TriangleMeshSlicer> m_tms;
|
std::unique_ptr<TriangleMeshSlicer> m_tms;
|
||||||
};
|
};
|
||||||
|
|
Loading…
Add table
Reference in a new issue