mirror of
https://git.mirrors.martin98.com/https://github.com/prusa3d/PrusaSlicer.git
synced 2025-05-20 09:38:07 +08:00
Changed internal coordinates of drain holes
Drain holes reference position was saved slightly above the mesh to avoid problem when the hole is placed on flat or nearly flat surface The depth of the hole was internally bigger than what the user has set to compensato for it However, this leads to problem with scaling and makes reprojection of the holes on the mesh complicated This commit changes the reference point to the point on the mesh and the extra elevation is handled when rendering and drilling the hole. The change is reflected in 3MF drain holes versioning so that old 3MFs are loaded correctly. Reprojection on the mesh after reload from disk/fix through netfabb has been enabled.
This commit is contained in:
parent
ba03429679
commit
a95509ce36
@ -1103,7 +1103,7 @@ namespace Slic3r {
|
|||||||
|
|
||||||
sla::DrainHoles sla_drain_holes;
|
sla::DrainHoles sla_drain_holes;
|
||||||
|
|
||||||
if (version == 1) {
|
if (version == 1 || version == 2) {
|
||||||
for (unsigned int i=0; i<object_data_points.size(); i+=8)
|
for (unsigned int i=0; i<object_data_points.size(); i+=8)
|
||||||
sla_drain_holes.emplace_back(Vec3f{float(std::atof(object_data_points[i+0].c_str())),
|
sla_drain_holes.emplace_back(Vec3f{float(std::atof(object_data_points[i+0].c_str())),
|
||||||
float(std::atof(object_data_points[i+1].c_str())),
|
float(std::atof(object_data_points[i+1].c_str())),
|
||||||
@ -1115,6 +1115,16 @@ namespace Slic3r {
|
|||||||
float(std::atof(object_data_points[i+7].c_str())));
|
float(std::atof(object_data_points[i+7].c_str())));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (version == 1) {
|
||||||
|
// In this version the holes were saved elevated above the mesh and deeper (bad idea indeed).
|
||||||
|
// Place the hole to the mesh and make it shallower to compensate.
|
||||||
|
// The offset was 1 mm above the mesh.
|
||||||
|
for (sla::DrainHole& hole : sla_drain_holes) {
|
||||||
|
hole.pos += hole.normal.normalized();
|
||||||
|
hole.height -= 1.f;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (!sla_drain_holes.empty())
|
if (!sla_drain_holes.empty())
|
||||||
m_sla_drain_holes.insert(IdToSlaDrainHolesMap::value_type(object_id, sla_drain_holes));
|
m_sla_drain_holes.insert(IdToSlaDrainHolesMap::value_type(object_id, sla_drain_holes));
|
||||||
}
|
}
|
||||||
|
@ -20,8 +20,15 @@ namespace Slic3r {
|
|||||||
support_points_format_version = 1
|
support_points_format_version = 1
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
|
/* The same for holes.
|
||||||
|
|
||||||
|
* version 0: undefined
|
||||||
|
* version 1: holes saved a bit above the mesh and deeper
|
||||||
|
* version 2: holes are saved on the mesh exactly
|
||||||
|
*/
|
||||||
enum {
|
enum {
|
||||||
drain_holes_format_version = 1
|
drain_holes_format_version = 2
|
||||||
};
|
};
|
||||||
|
|
||||||
class Model;
|
class Model;
|
||||||
@ -35,6 +42,6 @@ namespace Slic3r {
|
|||||||
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
// The model could be modified during the export process if meshes are not repaired or have no shared vertices
|
||||||
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data = nullptr);
|
extern bool store_3mf(const char* path, Model* model, const DynamicPrintConfig* config, bool fullpath_sources, const ThumbnailData* thumbnail_data = nullptr);
|
||||||
|
|
||||||
}; // namespace Slic3r
|
} // namespace Slic3r
|
||||||
|
|
||||||
#endif /* slic3r_Format_3mf_hpp_ */
|
#endif /* slic3r_Format_3mf_hpp_ */
|
||||||
|
@ -58,6 +58,8 @@ struct DrainHole
|
|||||||
|
|
||||||
using DrainHoles = std::vector<DrainHole>;
|
using DrainHoles = std::vector<DrainHole>;
|
||||||
|
|
||||||
|
constexpr float HoleStickOutLength = 1.f;
|
||||||
|
|
||||||
std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &mesh,
|
std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &mesh,
|
||||||
const HollowingConfig & = {},
|
const HollowingConfig & = {},
|
||||||
const JobController &ctl = {});
|
const JobController &ctl = {});
|
||||||
|
@ -28,15 +28,9 @@ void reproject_support_points(const IndexedMesh &mesh, std::vector<PointType> &p
|
|||||||
inline void reproject_points_and_holes(ModelObject *object)
|
inline void reproject_points_and_holes(ModelObject *object)
|
||||||
{
|
{
|
||||||
bool has_sppoints = !object->sla_support_points.empty();
|
bool has_sppoints = !object->sla_support_points.empty();
|
||||||
|
bool has_holes = !object->sla_drain_holes.empty();
|
||||||
|
|
||||||
// Disabling reprojection of holes as they have a significant offset away
|
if (!object || (!has_holes && !has_sppoints)) return;
|
||||||
// from the model body which tolerates minor geometrical changes.
|
|
||||||
//
|
|
||||||
// TODO: uncomment and ensure the right offset of the hole points if
|
|
||||||
// reprojection would still be necessary.
|
|
||||||
// bool has_holes = !object->sla_drain_holes.empty();
|
|
||||||
|
|
||||||
if (!object || (/*!has_holes &&*/ !has_sppoints)) return;
|
|
||||||
|
|
||||||
TriangleMesh rmsh = object->raw_mesh();
|
TriangleMesh rmsh = object->raw_mesh();
|
||||||
rmsh.require_shared_vertices();
|
rmsh.require_shared_vertices();
|
||||||
@ -45,8 +39,8 @@ inline void reproject_points_and_holes(ModelObject *object)
|
|||||||
if (has_sppoints)
|
if (has_sppoints)
|
||||||
reproject_support_points(emesh, object->sla_support_points);
|
reproject_support_points(emesh, object->sla_support_points);
|
||||||
|
|
||||||
// if (has_holes)
|
if (has_holes)
|
||||||
// reproject_support_points(emesh, object->sla_drain_holes);
|
reproject_support_points(emesh, object->sla_drain_holes);
|
||||||
}
|
}
|
||||||
|
|
||||||
}}
|
}}
|
||||||
|
@ -1181,6 +1181,12 @@ sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const
|
|||||||
hl.normal = Vec3f(hl.normal(0)/(sc(0)*sc(0)),
|
hl.normal = Vec3f(hl.normal(0)/(sc(0)*sc(0)),
|
||||||
hl.normal(1)/(sc(1)*sc(1)),
|
hl.normal(1)/(sc(1)*sc(1)),
|
||||||
hl.normal(2)/(sc(2)*sc(2)));
|
hl.normal(2)/(sc(2)*sc(2)));
|
||||||
|
|
||||||
|
// Now shift the hole a bit above the object and make it deeper to
|
||||||
|
// compensate for it. This is to avoid problems when the hole is placed
|
||||||
|
// on (nearly) flat surface.
|
||||||
|
hl.pos -= hl.normal.normalized() * sla::HoleStickOutLength;
|
||||||
|
hl.height += sla::HoleStickOutLength;
|
||||||
}
|
}
|
||||||
|
|
||||||
return pts;
|
return pts;
|
||||||
|
@ -130,7 +130,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
const sla::DrainHole& drain_hole = drain_holes[i];
|
const sla::DrainHole& drain_hole = drain_holes[i];
|
||||||
const bool& point_selected = m_selected[i];
|
const bool& point_selected = m_selected[i];
|
||||||
|
|
||||||
if (is_mesh_point_clipped((drain_hole.pos+HoleStickOutLength*drain_hole.normal).cast<double>()))
|
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// First decide about the color of the point.
|
// First decide about the color of the point.
|
||||||
@ -174,10 +174,10 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height, 24, 1);
|
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., drain_hole.height));
|
glsafe(::glTranslated(0., 0., drain_hole.height + sla::HoleStickOutLength));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height - sla::HoleStickOutLength));
|
||||||
glsafe(::glRotatef(180.f, 1.f, 0.f, 0.f));
|
glsafe(::glRotatef(180.f, 1.f, 0.f, 0.f));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
@ -307,12 +307,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||||||
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
|
if (unproject_on_mesh(mouse_position, pos_and_normal)) { // we got an intersection
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add drainage hole")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Add drainage hole")));
|
||||||
|
|
||||||
Vec3d scaling = mo->instances[active_inst]->get_scaling_factor();
|
mo->sla_drain_holes.emplace_back(pos_and_normal.first,
|
||||||
Vec3f normal_transformed(pos_and_normal.second(0)/scaling(0),
|
|
||||||
pos_and_normal.second(1)/scaling(1),
|
|
||||||
pos_and_normal.second(2)/scaling(2));
|
|
||||||
|
|
||||||
mo->sla_drain_holes.emplace_back(pos_and_normal.first + HoleStickOutLength * pos_and_normal.second/* normal_transformed.normalized()*/,
|
|
||||||
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height);
|
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height);
|
||||||
m_selected.push_back(false);
|
m_selected.push_back(false);
|
||||||
assert(m_selected.size() == mo->sla_drain_holes.size());
|
assert(m_selected.size() == mo->sla_drain_holes.size());
|
||||||
@ -447,7 +442,7 @@ void GLGizmoHollow::on_update(const UpdateData& data)
|
|||||||
std::pair<Vec3f, Vec3f> pos_and_normal;
|
std::pair<Vec3f, Vec3f> pos_and_normal;
|
||||||
if (! unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
|
if (! unproject_on_mesh(data.mouse_pos.cast<double>(), pos_and_normal))
|
||||||
return;
|
return;
|
||||||
drain_holes[m_hover_id].pos = pos_and_normal.first + HoleStickOutLength * pos_and_normal.second;
|
drain_holes[m_hover_id].pos = pos_and_normal.first;
|
||||||
drain_holes[m_hover_id].normal = -pos_and_normal.second;
|
drain_holes[m_hover_id].normal = -pos_and_normal.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -661,9 +656,7 @@ RENDER_AGAIN:
|
|||||||
|
|
||||||
m_imgui->text(m_desc["hole_depth"]);
|
m_imgui->text(m_desc["hole_depth"]);
|
||||||
ImGui::SameLine(diameter_slider_left);
|
ImGui::SameLine(diameter_slider_left);
|
||||||
m_new_hole_height -= HoleStickOutLength;
|
|
||||||
ImGui::SliderFloat(" ", &m_new_hole_height, 0.f, 10.f, "%.1f mm");
|
ImGui::SliderFloat(" ", &m_new_hole_height, 0.f, 10.f, "%.1f mm");
|
||||||
m_new_hole_height += HoleStickOutLength;
|
|
||||||
|
|
||||||
clicked |= ImGui::IsItemClicked();
|
clicked |= ImGui::IsItemClicked();
|
||||||
edited |= ImGui::IsItemEdited();
|
edited |= ImGui::IsItemEdited();
|
||||||
|
@ -222,7 +222,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
render_color[3] = 0.7f;
|
render_color[3] = 0.7f;
|
||||||
glsafe(::glColor4fv(render_color));
|
glsafe(::glColor4fv(render_color));
|
||||||
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
|
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
|
||||||
if (is_mesh_point_clipped((drain_hole.pos+HoleStickOutLength*drain_hole.normal).cast<double>()))
|
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||||
@ -241,10 +241,10 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis()(0), aa.axis()(1), aa.axis()(2)));
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height, 24, 1);
|
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., drain_hole.height));
|
glsafe(::glTranslated(0., 0., drain_hole.height + sla::HoleStickOutLength));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height - sla::HoleStickOutLength));
|
||||||
glsafe(::glRotatef(180.f, 1.f, 0.f, 0.f));
|
glsafe(::glRotatef(180.f, 1.f, 0.f, 0.f));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
|
@ -15,8 +15,6 @@ namespace GUI {
|
|||||||
|
|
||||||
class GLCanvas3D;
|
class GLCanvas3D;
|
||||||
|
|
||||||
static constexpr float HoleStickOutLength = 1.f;
|
|
||||||
|
|
||||||
enum class SLAGizmoEventType : unsigned char {
|
enum class SLAGizmoEventType : unsigned char {
|
||||||
LeftDown = 1,
|
LeftDown = 1,
|
||||||
LeftUp,
|
LeftUp,
|
||||||
|
Loading…
x
Reference in New Issue
Block a user