mirror of
https://github.com/SoftFever/OrcaSlicer.git
synced 2025-10-28 19:21:20 -06:00
Merge branch 'tm_openvdb_integration' into lm_tm_hollowing
This commit is contained in:
commit
673549d608
11 changed files with 138 additions and 88 deletions
|
|
@ -199,13 +199,13 @@ public:
|
|||
// This vector holds position of selected support points for SLA. The data are
|
||||
// saved in mesh coordinates to allow using them for several instances.
|
||||
// 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
|
||||
// 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
|
||||
std::vector<sla::DrainHole> sla_drain_holes;
|
||||
sla::DrainHoles sla_drain_holes;
|
||||
|
||||
/* This vector accumulates the total translation applied to the object by the
|
||||
center_around_origin() method. Callers might want to apply the same translation
|
||||
|
|
|
|||
|
|
@ -121,9 +121,9 @@ std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh & mesh,
|
|||
|
||||
bool DrainHole::operator==(const DrainHole &sp) const
|
||||
{
|
||||
return (m_pos == sp.m_pos) && (m_normal == sp.m_normal) &&
|
||||
is_approx(m_radius, sp.m_radius) &&
|
||||
is_approx(m_height, sp.m_height);
|
||||
return (pos == sp.pos) && (normal == sp.normal) &&
|
||||
is_approx(radius, sp.radius) &&
|
||||
is_approx(height, sp.height);
|
||||
}
|
||||
|
||||
}} // namespace Slic3r::sla
|
||||
|
|
|
|||
|
|
@ -20,21 +20,17 @@ struct HollowingConfig
|
|||
|
||||
struct DrainHole
|
||||
{
|
||||
Vec3f m_pos;
|
||||
Vec3f m_normal;
|
||||
float m_radius;
|
||||
float m_height;
|
||||
|
||||
Vec3f pos;
|
||||
Vec3f normal;
|
||||
float radius;
|
||||
float height;
|
||||
|
||||
DrainHole()
|
||||
: m_pos(Vec3f::Zero()), m_normal(Vec3f::UnitZ()), m_radius(5.f),
|
||||
m_height(10.f)
|
||||
: pos(Vec3f::Zero()), normal(Vec3f::UnitZ()), radius(5.f), height(10.f)
|
||||
{}
|
||||
|
||||
DrainHole(Vec3f position, Vec3f normal, float radius, float height)
|
||||
: m_pos(position)
|
||||
, m_normal(normal)
|
||||
, m_radius(radius)
|
||||
, m_height(height)
|
||||
|
||||
DrainHole(Vec3f p, Vec3f n, float r, float h)
|
||||
: pos(p), normal(n), radius(r), height(h)
|
||||
{}
|
||||
|
||||
bool operator==(const DrainHole &sp) const;
|
||||
|
|
@ -43,10 +39,12 @@ struct DrainHole
|
|||
|
||||
template<class Archive> inline void serialize(Archive &ar)
|
||||
{
|
||||
ar(m_pos, m_normal, m_radius, m_height);
|
||||
ar(pos, normal, radius, height);
|
||||
}
|
||||
};
|
||||
|
||||
using DrainHoles = std::vector<DrainHole>;
|
||||
|
||||
std::unique_ptr<TriangleMesh> generate_interior(const TriangleMesh &mesh,
|
||||
const HollowingConfig & = {},
|
||||
const JobController &ctl = {});
|
||||
|
|
|
|||
|
|
@ -74,7 +74,7 @@ Contour3D sphere(double rho, Portion portion = make_portion(0.0, 2.0*PI),
|
|||
// h: Height
|
||||
// ssteps: how many edges will create the base circle
|
||||
// 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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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_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.
|
||||
model_object.name = model_object_new.name;
|
||||
|
|
@ -1154,21 +1160,30 @@ const TriangleMesh &SLAPrintObject::transformed_mesh() const {
|
|||
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);
|
||||
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
|
||||
std::vector<sla::SupportPoint> ret;
|
||||
ret.reserve(spts.size());
|
||||
|
||||
for(sla::SupportPoint& sp : spts) {
|
||||
Vec3f transformed_pos = trafo().cast<float>() * sp.pos;
|
||||
ret.emplace_back(transformed_pos, sp.head_front_radius, sp.is_new_island);
|
||||
}
|
||||
|
||||
return ret;
|
||||
sla::DrainHoles SLAPrintObject::transformed_drainhole_points() const
|
||||
{
|
||||
assert(m_model_object != nullptr);
|
||||
auto& spts = m_model_object->sla_drain_holes;
|
||||
return transform_pts(spts.begin(), spts.end(), trafo().cast<float>());
|
||||
}
|
||||
|
||||
DynamicConfig SLAPrintStatistics::config() const
|
||||
|
|
|
|||
|
|
@ -83,7 +83,8 @@ public:
|
|||
// This will return the transformed mesh which is cached
|
||||
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
|
||||
// displayed. This Z offset should also be applied to the support
|
||||
|
|
|
|||
|
|
@ -1,5 +1,9 @@
|
|||
#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/Pad.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!";
|
||||
}
|
||||
|
||||
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 bottom of the bounding box created around the supported model. So
|
||||
// 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
|
||||
// same imaginary grid (the height vector argument to TriangleMeshSlicer).
|
||||
void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
||||
{
|
||||
|
||||
{
|
||||
TriangleMesh hollowed_mesh;
|
||||
|
||||
bool is_hollowing = po.m_config.hollowing_enable.getBool() &&
|
||||
po.m_hollowing_data;
|
||||
bool is_hollowing = po.m_config.hollowing_enable.getBool() && po.m_hollowing_data;
|
||||
|
||||
if (is_hollowing) {
|
||||
hollowed_mesh = po.transformed_mesh();
|
||||
|
|
@ -120,8 +158,7 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||
hollowed_mesh.require_shared_vertices();
|
||||
}
|
||||
|
||||
const TriangleMesh &mesh = is_hollowing ? hollowed_mesh :
|
||||
po.transformed_mesh();
|
||||
const TriangleMesh &mesh = is_hollowing ? hollowed_mesh : po.transformed_mesh();
|
||||
|
||||
// We need to prepare the slice index...
|
||||
|
||||
|
|
@ -163,10 +200,13 @@ void SLAPrint::Steps::slice_model(SLAPrintObject &po)
|
|||
TriangleMeshSlicer slicer(&mesh);
|
||||
|
||||
po.m_model_slices.clear();
|
||||
slicer.slice(po.m_model_height_levels,
|
||||
float(po.config().slice_closing_radius.value),
|
||||
&po.m_model_slices,
|
||||
[this](){ m_print->throw_if_canceled(); });
|
||||
float closing_r = float(po.config().slice_closing_radius.value);
|
||||
auto thr = [this]() { m_print->throw_if_canceled(); };
|
||||
auto &slice_grid = po.m_model_height_levels;
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
if(po.m_config.supports_enable.getBool() ||
|
||||
po.m_config.pad_enable.getBool())
|
||||
if(po.m_config.supports_enable.getBool() || po.m_config.pad_enable.getBool())
|
||||
{
|
||||
po.m_supportdata.reset(
|
||||
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
|
||||
// repeated)
|
||||
|
||||
if(po.m_config.pad_enable.getBool())
|
||||
{
|
||||
if(po.m_config.pad_enable.getBool()) {
|
||||
// Get the distilled pad configuration from the 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();
|
||||
|
||||
// Don't bother if no supports and no pad is present.
|
||||
if (!po.m_config.supports_enable.getBool() &&
|
||||
!po.m_config.pad_enable.getBool())
|
||||
if (!po.m_config.supports_enable.getBool() && !po.m_config.pad_enable.getBool())
|
||||
return;
|
||||
|
||||
if(sd && sd->support_tree_ptr) {
|
||||
|
||||
std::vector<float> heights; heights.reserve(po.m_slice_index.size());
|
||||
auto heights = reserve_vector<float>(po.m_slice_index.size());
|
||||
|
||||
for(auto& rec : po.m_slice_index) heights.emplace_back(rec.slice_level());
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue