Holes are now visible on slices in preview.
This commit is contained in:
parent
97811130a1
commit
d4d037792d
@ -283,9 +283,9 @@ endif()
|
|||||||
macro(just_fail msg)
|
macro(just_fail msg)
|
||||||
set(OpenVDB_FOUND FALSE)
|
set(OpenVDB_FOUND FALSE)
|
||||||
if(OpenVDB_FIND_REQUIRED)
|
if(OpenVDB_FIND_REQUIRED)
|
||||||
message(FATAL_ERROR msg)
|
message(FATAL_ERROR ${msg})
|
||||||
elseif(NOT OpenVDB_FIND_QUIETLY)
|
elseif(NOT OpenVDB_FIND_QUIETLY)
|
||||||
message(ERROR msg)
|
message(WARNING ${msg})
|
||||||
endif()
|
endif()
|
||||||
return()
|
return()
|
||||||
endmacro()
|
endmacro()
|
||||||
|
@ -199,13 +199,13 @@ public:
|
|||||||
// This vector holds position of selected support points for SLA. The data are
|
// This vector holds position of selected support points for SLA. The data are
|
||||||
// saved in mesh coordinates to allow using them for several instances.
|
// saved in mesh coordinates to allow using them for several instances.
|
||||||
// The format is (x, y, z, point_size, supports_island)
|
// The format is (x, y, z, point_size, supports_island)
|
||||||
std::vector<sla::SupportPoint> sla_support_points;
|
sla::SupportPoints sla_support_points;
|
||||||
// To keep track of where the points came from (used for synchronization between
|
// To keep track of where the points came from (used for synchronization between
|
||||||
// the SLA gizmo and the backend).
|
// the SLA gizmo and the backend).
|
||||||
sla::PointsStatus sla_points_status = sla::PointsStatus::NoPoints;
|
sla::PointsStatus sla_points_status = sla::PointsStatus::NoPoints;
|
||||||
|
|
||||||
// Holes to be drilled into the object so resin can flow out
|
// Holes to be drilled into the object so resin can flow out
|
||||||
std::vector<sla::DrainHole> sla_drain_holes;
|
sla::DrainHoles sla_drain_holes;
|
||||||
|
|
||||||
/* This vector accumulates the total translation applied to the object by the
|
/* This vector accumulates the total translation applied to the object by the
|
||||||
center_around_origin() method. Callers might want to apply the same translation
|
center_around_origin() method. Callers might want to apply the same translation
|
||||||
|
@ -74,7 +74,7 @@ Contour3D sphere(double rho, Portion portion = make_portion(0.0, 2.0*PI),
|
|||||||
// h: Height
|
// h: Height
|
||||||
// ssteps: how many edges will create the base circle
|
// ssteps: how many edges will create the base circle
|
||||||
// sp: starting point
|
// sp: starting point
|
||||||
Contour3D cylinder(double r, double h, size_t ssteps, const Vec3d &sp = {0,0,0});
|
Contour3D cylinder(double r, double h, size_t ssteps = 45, const Vec3d &sp = {0,0,0});
|
||||||
|
|
||||||
const constexpr long ID_UNSET = -1;
|
const constexpr long ID_UNSET = -1;
|
||||||
|
|
||||||
|
@ -414,6 +414,12 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||||||
model_object.sla_support_points = model_object_new.sla_support_points;
|
model_object.sla_support_points = model_object_new.sla_support_points;
|
||||||
}
|
}
|
||||||
model_object.sla_points_status = model_object_new.sla_points_status;
|
model_object.sla_points_status = model_object_new.sla_points_status;
|
||||||
|
|
||||||
|
if (model_object.sla_drain_holes.size() != model_object_new.sla_drain_holes.size())
|
||||||
|
{
|
||||||
|
model_object.sla_drain_holes = model_object_new.sla_drain_holes;
|
||||||
|
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposHollowing));
|
||||||
|
}
|
||||||
|
|
||||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||||
model_object.name = model_object_new.name;
|
model_object.name = model_object_new.name;
|
||||||
@ -1154,21 +1160,30 @@ const TriangleMesh &SLAPrintObject::transformed_mesh() const {
|
|||||||
return m_transformed_rmesh.get();
|
return m_transformed_rmesh.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<sla::SupportPoint> SLAPrintObject::transformed_support_points() const
|
template<class It, class Trafo, class V = typename std::iterator_traits<It>::value_type>
|
||||||
|
std::vector<V> transform_pts(It from, It to, Trafo &&tr)
|
||||||
|
{
|
||||||
|
auto ret = reserve_vector<V>(to - from);
|
||||||
|
for(auto it = from; it != to; ++it) {
|
||||||
|
V v = *it;
|
||||||
|
v.pos = tr * it->pos;
|
||||||
|
ret.emplace_back(std::move(v));
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
sla::SupportPoints SLAPrintObject::transformed_support_points() const
|
||||||
{
|
{
|
||||||
assert(m_model_object != nullptr);
|
assert(m_model_object != nullptr);
|
||||||
std::vector<sla::SupportPoint>& spts = m_model_object->sla_support_points;
|
auto& spts = m_model_object->sla_support_points;
|
||||||
|
return transform_pts(spts.begin(), spts.end(), trafo().cast<float>());
|
||||||
|
}
|
||||||
|
|
||||||
// this could be cached as well
|
sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const
|
||||||
std::vector<sla::SupportPoint> ret;
|
{
|
||||||
ret.reserve(spts.size());
|
assert(m_model_object != nullptr);
|
||||||
|
auto& spts = m_model_object->sla_drain_holes;
|
||||||
for(sla::SupportPoint& sp : spts) {
|
return transform_pts(spts.begin(), spts.end(), trafo().cast<float>());
|
||||||
Vec3f transformed_pos = trafo().cast<float>() * sp.pos;
|
|
||||||
ret.emplace_back(transformed_pos, sp.head_front_radius, sp.is_new_island);
|
|
||||||
}
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
DynamicConfig SLAPrintStatistics::config() const
|
DynamicConfig SLAPrintStatistics::config() const
|
||||||
|
@ -83,7 +83,8 @@ public:
|
|||||||
// This will return the transformed mesh which is cached
|
// This will return the transformed mesh which is cached
|
||||||
const TriangleMesh& transformed_mesh() const;
|
const TriangleMesh& transformed_mesh() const;
|
||||||
|
|
||||||
std::vector<sla::SupportPoint> transformed_support_points() const;
|
sla::SupportPoints transformed_support_points() const;
|
||||||
|
sla::DrainHoles transformed_drainhole_points() const;
|
||||||
|
|
||||||
// Get the needed Z elevation for the model geometry if supports should be
|
// Get the needed Z elevation for the model geometry if supports should be
|
||||||
// displayed. This Z offset should also be applied to the support
|
// displayed. This Z offset should also be applied to the support
|
||||||
|
@ -1,5 +1,9 @@
|
|||||||
#include <libslic3r/SLAPrintSteps.hpp>
|
#include <libslic3r/SLAPrintSteps.hpp>
|
||||||
|
|
||||||
|
|
||||||
|
// Need the cylinder method for the the drainholes in hollowing step
|
||||||
|
#include <libslic3r/SLA/SupportTreeBuilder.hpp>
|
||||||
|
|
||||||
#include <libslic3r/SLA/Concurrency.hpp>
|
#include <libslic3r/SLA/Concurrency.hpp>
|
||||||
#include <libslic3r/SLA/Pad.hpp>
|
#include <libslic3r/SLA/Pad.hpp>
|
||||||
#include <libslic3r/SLA/SupportPointGenerator.hpp>
|
#include <libslic3r/SLA/SupportPointGenerator.hpp>
|
||||||
@ -98,6 +102,42 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
|
|||||||
BOOST_LOG_TRIVIAL(warning) << "Hollowed interior is empty!";
|
BOOST_LOG_TRIVIAL(warning) << "Hollowed interior is empty!";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void cut_drainholes(std::vector<ExPolygons> & obj_slices,
|
||||||
|
const std::vector<float> &slicegrid,
|
||||||
|
float closing_radius,
|
||||||
|
const sla::DrainHoles & holes,
|
||||||
|
std::function<void(void)> thr)
|
||||||
|
{
|
||||||
|
TriangleMesh mesh;
|
||||||
|
for (const sla::DrainHole &holept : holes) {
|
||||||
|
auto r = double(holept.radius);
|
||||||
|
auto h = double(holept.height);
|
||||||
|
sla::Contour3D hole = sla::cylinder(r, h);
|
||||||
|
Eigen::Quaterniond q;
|
||||||
|
q.setFromTwoVectors(Vec3d{0., 0., 1.}, holept.normal.cast<double>());
|
||||||
|
for(auto& p : hole.points) p = q * p + holept.pos.cast<double>();
|
||||||
|
mesh.merge(sla::to_triangle_mesh(hole));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mesh.empty()) return;
|
||||||
|
|
||||||
|
mesh.require_shared_vertices();
|
||||||
|
|
||||||
|
TriangleMeshSlicer slicer(&mesh);
|
||||||
|
|
||||||
|
std::vector<ExPolygons> hole_slices;
|
||||||
|
slicer.slice(slicegrid, closing_radius, &hole_slices, thr);
|
||||||
|
|
||||||
|
if (obj_slices.size() != hole_slices.size())
|
||||||
|
BOOST_LOG_TRIVIAL(warning)
|
||||||
|
<< "Sliced object and drain-holes layer count does not match!";
|
||||||
|
|
||||||
|
size_t until = std::min(obj_slices.size(), hole_slices.size());
|
||||||
|
|
||||||
|
for (size_t i = 0; i < until; ++i)
|
||||||
|
obj_slices[i] = diff_ex(obj_slices[i], hole_slices[i]);
|
||||||
|
}
|
||||||
|
|
||||||
// The slicing will be performed on an imaginary 1D grid which starts from
|
// The slicing will be performed on an imaginary 1D grid which starts from
|
||||||
// the bottom of the bounding box created around the supported model. So
|
// the bottom of the bounding box created around the supported model. So
|
||||||
// the first layer which is usually thicker will be part of the supports
|
// the first layer which is usually thicker will be part of the supports
|
||||||
@ -107,12 +147,10 @@ void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
|
|||||||
// of it. In any case, the model and the supports have to be sliced in the
|
// of it. In any case, the model and the supports have to be sliced in the
|
||||||
// same imaginary grid (the height vector argument to TriangleMeshSlicer).
|
// same imaginary grid (the height vector argument to TriangleMeshSlicer).
|
||||||
void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
||||||
{
|
{
|
||||||
|
|
||||||
TriangleMesh hollowed_mesh;
|
TriangleMesh hollowed_mesh;
|
||||||
|
|
||||||
bool is_hollowing = po.m_config.hollowing_enable.getBool() &&
|
bool is_hollowing = po.m_config.hollowing_enable.getBool() && po.m_hollowing_data;
|
||||||
po.m_hollowing_data;
|
|
||||||
|
|
||||||
if (is_hollowing) {
|
if (is_hollowing) {
|
||||||
hollowed_mesh = po.transformed_mesh();
|
hollowed_mesh = po.transformed_mesh();
|
||||||
@ -120,8 +158,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||||||
hollowed_mesh.require_shared_vertices();
|
hollowed_mesh.require_shared_vertices();
|
||||||
}
|
}
|
||||||
|
|
||||||
const TriangleMesh &mesh = is_hollowing ? hollowed_mesh :
|
const TriangleMesh &mesh = is_hollowing ? hollowed_mesh : po.transformed_mesh();
|
||||||
po.transformed_mesh();
|
|
||||||
|
|
||||||
// We need to prepare the slice index...
|
// We need to prepare the slice index...
|
||||||
|
|
||||||
@ -163,10 +200,13 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||||||
TriangleMeshSlicer slicer(&mesh);
|
TriangleMeshSlicer slicer(&mesh);
|
||||||
|
|
||||||
po.m_model_slices.clear();
|
po.m_model_slices.clear();
|
||||||
slicer.slice(po.m_model_height_levels,
|
float closing_r = float(po.config().slice_closing_radius.value);
|
||||||
float(po.config().slice_closing_radius.value),
|
auto thr = [this]() { m_print->throw_if_canceled(); };
|
||||||
&po.m_model_slices,
|
auto &slice_grid = po.m_model_height_levels;
|
||||||
[this](){ m_print->throw_if_canceled(); });
|
slicer.slice(slice_grid, closing_r, &po.m_model_slices, thr);
|
||||||
|
|
||||||
|
sla::DrainHoles drainholes = po.transformed_drainhole_points();
|
||||||
|
cut_drainholes(po.m_model_slices, slice_grid, closing_r, drainholes, thr);
|
||||||
|
|
||||||
auto mit = slindex_it;
|
auto mit = slindex_it;
|
||||||
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
|
double doffs = m_print->m_printer_config.absolute_correction.getFloat();
|
||||||
@ -183,8 +223,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||||||
mit->set_model_slice_idx(po, id); ++mit;
|
mit->set_model_slice_idx(po, id); ++mit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(po.m_config.supports_enable.getBool() ||
|
if(po.m_config.supports_enable.getBool() || po.m_config.pad_enable.getBool())
|
||||||
po.m_config.pad_enable.getBool())
|
|
||||||
{
|
{
|
||||||
po.m_supportdata.reset(
|
po.m_supportdata.reset(
|
||||||
new SLAPrintObject::SupportData(po.transformed_mesh()) );
|
new SLAPrintObject::SupportData(po.transformed_mesh()) );
|
||||||
@ -324,8 +363,7 @@ void SLAPrint::Steps::generate_pad(SLAPrintObject &po) {
|
|||||||
// and before the supports had been sliced. (or the slicing has to be
|
// and before the supports had been sliced. (or the slicing has to be
|
||||||
// repeated)
|
// repeated)
|
||||||
|
|
||||||
if(po.m_config.pad_enable.getBool())
|
if(po.m_config.pad_enable.getBool()) {
|
||||||
{
|
|
||||||
// Get the distilled pad configuration from the config
|
// Get the distilled pad configuration from the config
|
||||||
sla::PadConfig pcfg = make_pad_cfg(po.m_config);
|
sla::PadConfig pcfg = make_pad_cfg(po.m_config);
|
||||||
|
|
||||||
@ -368,13 +406,11 @@ void SLAPrint::Steps::slice_supports(SLAPrintObject &po) {
|
|||||||
if(sd) sd->support_slices.clear();
|
if(sd) sd->support_slices.clear();
|
||||||
|
|
||||||
// Don't bother if no supports and no pad is present.
|
// Don't bother if no supports and no pad is present.
|
||||||
if (!po.m_config.supports_enable.getBool() &&
|
if (!po.m_config.supports_enable.getBool() && !po.m_config.pad_enable.getBool())
|
||||||
!po.m_config.pad_enable.getBool())
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(sd && sd->support_tree_ptr) {
|
if(sd && sd->support_tree_ptr) {
|
||||||
|
auto heights = reserve_vector<float>(po.m_slice_index.size());
|
||||||
std::vector<float> heights; heights.reserve(po.m_slice_index.size());
|
|
||||||
|
|
||||||
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
|
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
|
||||||
|
|
||||||
|
@ -250,7 +250,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
const sla::DrainHole& drain_hole = m_model_object->sla_drain_holes[i];
|
const sla::DrainHole& drain_hole = m_model_object->sla_drain_holes[i];
|
||||||
const bool& point_selected = m_selected[i];
|
const bool& point_selected = m_selected[i];
|
||||||
|
|
||||||
if (is_mesh_point_clipped(drain_hole.m_pos.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.
|
||||||
@ -281,7 +281,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
|
|
||||||
// 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.
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(drain_hole.m_pos(0), drain_hole.m_pos(1), drain_hole.m_pos(2)));
|
glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2)));
|
||||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
@ -290,17 +290,17 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||||||
// Matrices set, we can render the point mark now.
|
// Matrices set, we can render the point mark now.
|
||||||
|
|
||||||
Eigen::Quaterniond q;
|
Eigen::Quaterniond q;
|
||||||
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.m_normal).cast<double>());
|
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||||
Eigen::AngleAxisd aa(q);
|
Eigen::AngleAxisd aa(q);
|
||||||
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.m_height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
::gluCylinder(m_quadric, drain_hole.m_radius, drain_hole.m_radius, drain_hole.m_height, 24, 1);
|
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., drain_hole.m_height));
|
glsafe(::glTranslated(0., 0., drain_hole.height));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.m_radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.m_height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
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.m_radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
@ -433,7 +433,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||||||
m_model_object->sla_drain_holes.emplace_back(pos_and_normal.first + HoleStickOutLength * pos_and_normal.second,
|
m_model_object->sla_drain_holes.emplace_back(pos_and_normal.first + HoleStickOutLength * pos_and_normal.second,
|
||||||
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height+HoleStickOutLength);
|
-pos_and_normal.second, m_new_hole_radius, m_new_hole_height+HoleStickOutLength);
|
||||||
m_selected.push_back(false);
|
m_selected.push_back(false);
|
||||||
assert(m_selected.size == m_model_object->sla_drain_holes.size());
|
assert(m_selected.size() == m_model_object->sla_drain_holes.size());
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
m_wait_for_up_event = true;
|
m_wait_for_up_event = true;
|
||||||
}
|
}
|
||||||
@ -456,7 +456,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_z_shift));
|
||||||
std::vector<Vec3d> points;
|
std::vector<Vec3d> points;
|
||||||
for (unsigned int i=0; i<m_model_object->sla_drain_holes.size(); ++i)
|
for (unsigned int i=0; i<m_model_object->sla_drain_holes.size(); ++i)
|
||||||
points.push_back(trafo.get_matrix() * m_model_object->sla_drain_holes[i].m_pos.cast<double>());
|
points.push_back(trafo.get_matrix() * m_model_object->sla_drain_holes[i].pos.cast<double>());
|
||||||
|
|
||||||
// Now ask the rectangle which of the points are inside.
|
// Now ask the rectangle which of the points are inside.
|
||||||
std::vector<Vec3f> points_inside;
|
std::vector<Vec3f> points_inside;
|
||||||
@ -558,8 +558,8 @@ 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;
|
||||||
m_model_object->sla_drain_holes[m_hover_id].m_pos = pos_and_normal.first + HoleStickOutLength * pos_and_normal.second;
|
m_model_object->sla_drain_holes[m_hover_id].pos = pos_and_normal.first + HoleStickOutLength * pos_and_normal.second;
|
||||||
m_model_object->sla_drain_holes[m_hover_id].m_normal = -pos_and_normal.second;
|
m_model_object->sla_drain_holes[m_hover_id].normal = -pos_and_normal.second;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -688,20 +688,20 @@ RENDER_AGAIN:
|
|||||||
if (ImGui::IsItemEdited()) {
|
if (ImGui::IsItemEdited()) {
|
||||||
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
||||||
if (m_selected[idx])
|
if (m_selected[idx])
|
||||||
m_model_object->sla_drain_holes[idx].m_radius = m_new_hole_radius;
|
m_model_object->sla_drain_holes[idx].radius = m_new_hole_radius;
|
||||||
}
|
}
|
||||||
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
if (ImGui::IsItemDeactivatedAfterEdit()) {
|
||||||
// momentarily restore the old value to take snapshot
|
// momentarily restore the old value to take snapshot
|
||||||
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
||||||
if (m_selected[idx])
|
if (m_selected[idx])
|
||||||
m_model_object->sla_drain_holes[idx].m_radius = m_old_hole_radius;
|
m_model_object->sla_drain_holes[idx].radius = m_old_hole_radius;
|
||||||
float backup = m_new_hole_radius;
|
float backup = m_new_hole_radius;
|
||||||
m_new_hole_radius = m_old_hole_radius;
|
m_new_hole_radius = m_old_hole_radius;
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Change drainage hole diameter")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Change drainage hole diameter")));
|
||||||
m_new_hole_radius = backup;
|
m_new_hole_radius = backup;
|
||||||
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
for (size_t idx=0; idx<m_selected.size(); ++idx)
|
||||||
if (m_selected[idx])
|
if (m_selected[idx])
|
||||||
m_model_object->sla_drain_holes[idx].m_radius = m_new_hole_radius;
|
m_model_object->sla_drain_holes[idx].radius = m_new_hole_radius;
|
||||||
m_old_hole_radius = 0.f;
|
m_old_hole_radius = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -863,7 +863,7 @@ void GLGizmoHollow::on_start_dragging()
|
|||||||
if (m_hover_id != -1) {
|
if (m_hover_id != -1) {
|
||||||
select_point(NoPoints);
|
select_point(NoPoints);
|
||||||
select_point(m_hover_id);
|
select_point(m_hover_id);
|
||||||
m_hole_before_drag = m_model_object->sla_drain_holes[m_hover_id].m_pos;
|
m_hole_before_drag = m_model_object->sla_drain_holes[m_hover_id].pos;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
m_hole_before_drag = Vec3f::Zero();
|
m_hole_before_drag = Vec3f::Zero();
|
||||||
@ -873,14 +873,14 @@ void GLGizmoHollow::on_start_dragging()
|
|||||||
void GLGizmoHollow::on_stop_dragging()
|
void GLGizmoHollow::on_stop_dragging()
|
||||||
{
|
{
|
||||||
if (m_hover_id != -1) {
|
if (m_hover_id != -1) {
|
||||||
Vec3f backup = m_model_object->sla_drain_holes[m_hover_id].m_pos;
|
Vec3f backup = m_model_object->sla_drain_holes[m_hover_id].pos;
|
||||||
|
|
||||||
if (m_hole_before_drag != Vec3f::Zero() // some point was touched
|
if (m_hole_before_drag != Vec3f::Zero() // some point was touched
|
||||||
&& backup != m_hole_before_drag) // and it was moved, not just selected
|
&& backup != m_hole_before_drag) // and it was moved, not just selected
|
||||||
{
|
{
|
||||||
m_model_object->sla_drain_holes[m_hover_id].m_pos = m_hole_before_drag;
|
m_model_object->sla_drain_holes[m_hover_id].pos = m_hole_before_drag;
|
||||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Move drainage hole")));
|
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("Move drainage hole")));
|
||||||
m_model_object->sla_drain_holes[m_hover_id].m_pos = backup;
|
m_model_object->sla_drain_holes[m_hover_id].pos = backup;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
m_hole_before_drag = Vec3f::Zero();
|
m_hole_before_drag = Vec3f::Zero();
|
||||||
@ -921,14 +921,14 @@ void GLGizmoHollow::select_point(int i)
|
|||||||
m_selection_empty = (i == NoPoints);
|
m_selection_empty = (i == NoPoints);
|
||||||
|
|
||||||
if (i == AllPoints)
|
if (i == AllPoints)
|
||||||
m_new_hole_radius = m_model_object->sla_drain_holes[0].m_radius;
|
m_new_hole_radius = m_model_object->sla_drain_holes[0].radius;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
while (size_t(i) >= m_selected.size())
|
while (size_t(i) >= m_selected.size())
|
||||||
m_selected.push_back(false);
|
m_selected.push_back(false);
|
||||||
m_selected[i] = true;
|
m_selected[i] = true;
|
||||||
m_selection_empty = false;
|
m_selection_empty = false;
|
||||||
m_new_hole_radius = m_model_object->sla_drain_holes[i].m_radius;
|
m_new_hole_radius = m_model_object->sla_drain_holes[i].radius;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -336,7 +336,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
for (const sla::DrainHole& drain_hole : m_model_object->sla_drain_holes) {
|
for (const sla::DrainHole& drain_hole : m_model_object->sla_drain_holes) {
|
||||||
// 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.
|
||||||
glsafe(::glPushMatrix());
|
glsafe(::glPushMatrix());
|
||||||
glsafe(::glTranslatef(drain_hole.m_pos(0), drain_hole.m_pos(1), drain_hole.m_pos(2)));
|
glsafe(::glTranslatef(drain_hole.pos(0), drain_hole.pos(1), drain_hole.pos(2)));
|
||||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
@ -345,17 +345,17 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||||||
// Matrices set, we can render the point mark now.
|
// Matrices set, we can render the point mark now.
|
||||||
|
|
||||||
Eigen::Quaterniond q;
|
Eigen::Quaterniond q;
|
||||||
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.m_normal).cast<double>());
|
q.setFromTwoVectors(Vec3d{0., 0., 1.}, instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||||
Eigen::AngleAxisd aa(q);
|
Eigen::AngleAxisd aa(q);
|
||||||
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.m_height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
::gluCylinder(m_quadric, drain_hole.m_radius, drain_hole.m_radius, drain_hole.m_height, 24, 1);
|
::gluCylinder(m_quadric, drain_hole.radius, drain_hole.radius, drain_hole.height, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., drain_hole.m_height));
|
glsafe(::glTranslated(0., 0., drain_hole.height));
|
||||||
::gluDisk(m_quadric, 0.0, drain_hole.m_radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glTranslated(0., 0., -drain_hole.m_height));
|
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||||
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.m_radius, 24, 1);
|
::gluDisk(m_quadric, 0.0, drain_hole.radius, 24, 1);
|
||||||
glsafe(::glPopMatrix());
|
glsafe(::glPopMatrix());
|
||||||
|
|
||||||
if (vol->is_left_handed())
|
if (vol->is_left_handed())
|
||||||
@ -421,10 +421,10 @@ bool GLGizmoSlaSupports::is_point_in_hole(const Vec3f& pt) const
|
|||||||
|
|
||||||
|
|
||||||
for (const sla::DrainHole& hole : m_model_object->sla_drain_holes) {
|
for (const sla::DrainHole& hole : m_model_object->sla_drain_holes) {
|
||||||
if ( hole.m_normal.dot(pt-hole.m_pos) < EPSILON
|
if ( hole.normal.dot(pt-hole.pos) < EPSILON
|
||||||
|| hole.m_normal.dot(pt-(hole.m_pos+hole.m_height * hole.m_normal)) > 0.f)
|
|| hole.normal.dot(pt-(hole.pos+hole.height * hole.normal)) > 0.f)
|
||||||
continue;
|
continue;
|
||||||
if ( squared_distance_from_line(pt, hole.m_pos, hole.m_normal) < pow(hole.m_radius, 2.f))
|
if ( squared_distance_from_line(pt, hole.pos, hole.normal) < pow(hole.radius, 2.f))
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -47,7 +47,7 @@ public:
|
|||||||
bool operator!=(const ClippingPlane& cp) const { return ! (*this==cp); }
|
bool operator!=(const ClippingPlane& cp) const { return ! (*this==cp); }
|
||||||
|
|
||||||
double distance(const Vec3d& pt) const {
|
double distance(const Vec3d& pt) const {
|
||||||
assert(is_approx(get_normal().norm(), 1.));
|
// FIXME: this fails: assert(is_approx(get_normal().norm(), 1.));
|
||||||
return (-get_normal().dot(pt) + m_data[3]);
|
return (-get_normal().dot(pt) + m_data[3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user