Change to return const references for TriangleMesh return values in SLAPrintObject's methods

This commit is contained in:
tamasmeszaros 2018-11-21 15:21:57 +01:00
parent 9996369e2c
commit 3667fc7894
6 changed files with 111 additions and 43 deletions

View file

@ -156,6 +156,7 @@ add_library(libslic3r STATIC
TriangleMesh.hpp TriangleMesh.hpp
utils.cpp utils.cpp
Utils.hpp Utils.hpp
MTUtils.hpp
SLA/SLABoilerPlate.hpp SLA/SLABoilerPlate.hpp
SLA/SLABasePool.hpp SLA/SLABasePool.hpp
SLA/SLABasePool.cpp SLA/SLABasePool.cpp

63
src/libslic3r/MTUtils.hpp Normal file
View file

@ -0,0 +1,63 @@
#ifndef MTUTILS_HPP
#define MTUTILS_HPP
#include <atomic> // for std::atomic_flag
#include <mutex> // for std::lock_guard
#include <functional> // for std::function
#include <utility> // for std::forward
namespace Slic3r {
// TODO: these classes are untested
/// Handy little spin mutex for the cached meshes.
/// Implements the "Lockable" concept
class SpinMutex {
std::atomic_flag m_flg;
static const /*constexpr*/ auto MO_ACQ = std::memory_order_acquire;
static const /*constexpr*/ auto MO_REL = std::memory_order_release;
public:
inline SpinMutex() { m_flg.clear(MO_REL); }
inline void lock() { while(m_flg.test_and_set(MO_ACQ)); }
inline bool try_lock() { return !m_flg.test_and_set(MO_ACQ); }
inline void unlock() { m_flg.clear(MO_REL); }
};
/// A wrapper class around arbitrary object that needs thread safe caching.
template<class T> class CachedObject {
public:
// Method type which refreshes the object when it has been invalidated
using Setter = std::function<void(T&)>;
private:
T m_obj; // the object itself
bool m_valid; // invalidation flag
SpinMutex m_lck; // to make the caching thread safe
// the setter will be called just before the object's const value is about
// to be retrieved.
std::function<void(T&)> m_setter;
public:
// Forwarded constructor
template<class...Args> inline CachedObject(Setter fn, Args&&...args):
m_obj(std::forward<Args>(args)...), m_valid(false), m_setter(fn) {}
// invalidate the value of the object. The object will be refreshed at the
// next retrieval (Setter will be called). The data that is used in
// the setter function should be guarded as well if it is modified so the
// modification has to take place in fn.
inline void invalidate(std::function<void()> fn) {
std::lock_guard<SpinMutex> lck(m_lck); fn(); m_valid = false;
}
// Get the const object properly updated.
inline const T& get() {
std::lock_guard<SpinMutex> lck(m_lck);
if(!m_valid) { m_setter(m_obj); m_valid = true; }
return m_obj;
}
};
}
#endif // MTUTILS_HPP

View file

@ -730,6 +730,9 @@ public:
meshcache.merge(mesh(bs.mesh)); meshcache.merge(mesh(bs.mesh));
} }
// TODO: Is this necessary?
meshcache.repair();
BoundingBoxf3&& bb = meshcache.bounding_box(); BoundingBoxf3&& bb = meshcache.bounding_box();
model_height = bb.max(Z) - bb.min(Z); model_height = bb.max(Z) - bb.min(Z);
@ -1616,13 +1619,13 @@ bool SLASupportTree::generate(const PointSet &points,
return pc == ABORT; return pc == ABORT;
} }
void SLASupportTree::merged_mesh(TriangleMesh &outmesh) const const TriangleMesh &SLASupportTree::merged_mesh() const
{ {
outmesh.merge(get().merged_mesh()); return get().merged_mesh();
} }
void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const { void SLASupportTree::merged_mesh_with_pad(TriangleMesh &outmesh) const {
merged_mesh(outmesh); outmesh.merge(merged_mesh());
outmesh.merge(get_pad()); outmesh.merge(get_pad());
} }
@ -1658,14 +1661,12 @@ const TriangleMesh &SLASupportTree::add_pad(const SliceLayer& baseplate,
double max_merge_distance_mm, double max_merge_distance_mm,
double edge_radius_mm) const double edge_radius_mm) const
{ {
TriangleMesh mm;
merged_mesh(mm);
PoolConfig pcfg; PoolConfig pcfg;
pcfg.min_wall_thickness_mm = min_wall_thickness_mm; pcfg.min_wall_thickness_mm = min_wall_thickness_mm;
pcfg.min_wall_height_mm = min_wall_height_mm; pcfg.min_wall_height_mm = min_wall_height_mm;
pcfg.max_merge_distance_mm = max_merge_distance_mm; pcfg.max_merge_distance_mm = max_merge_distance_mm;
pcfg.edge_radius_mm = edge_radius_mm; pcfg.edge_radius_mm = edge_radius_mm;
return m_impl->create_pad(mm, baseplate, pcfg).tmesh; return m_impl->create_pad(merged_mesh(), baseplate, pcfg).tmesh;
} }
const TriangleMesh &SLASupportTree::get_pad() const const TriangleMesh &SLASupportTree::get_pad() const

View file

@ -144,7 +144,7 @@ public:
/// Get the whole mesh united into the output TriangleMesh /// Get the whole mesh united into the output TriangleMesh
/// WITHOUT THE PAD /// WITHOUT THE PAD
void merged_mesh(TriangleMesh& outmesh) const; const TriangleMesh& merged_mesh() const;
void merged_mesh_with_pad(TriangleMesh&) const; void merged_mesh_with_pad(TriangleMesh&) const;

View file

@ -500,7 +500,10 @@ void SLAPrint::process()
SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object): SLAPrintObject::SLAPrintObject(SLAPrint *print, ModelObject *model_object):
Inherited(print, model_object), Inherited(print, model_object),
m_stepmask(slaposCount, true) m_stepmask(slaposCount, true),
m_transformed_rmesh( [this](TriangleMesh& obj){
obj = m_model_object->raw_mesh(); obj.transform(m_trafo);
})
{ {
} }
@ -526,28 +529,29 @@ double SLAPrintObject::get_elevation() const {
return ret; return ret;
} }
//const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const namespace { // dummy empty static containers for return values in some methods
//{ const std::vector<ExPolygons> EMPTY_SLICES;
// // I don't want to return a copy but the points may not exist, so ... const TriangleMesh EMPTY_MESH;
// static const std::vector<ExPolygons> dummy_empty; }
// if(!m_supportdata) return dummy_empty; const std::vector<ExPolygons> &SLAPrintObject::get_support_slices() const
// return m_supportdata->support_slices; {
//} if(!is_step_done(slaposSliceSupports) || !m_supportdata) return EMPTY_SLICES;
return m_supportdata->support_slices;
}
//const std::vector<ExPolygons> &SLAPrintObject::get_model_slices() const const std::vector<ExPolygons> &SLAPrintObject::get_model_slices() const
//{ {
// return m_model_slices; if(!is_step_done(slaposObjectSlice)) return EMPTY_SLICES;
//} return m_model_slices;
}
bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const
{ {
switch (step) { switch (step) {
case slaposSupportTree: case slaposSupportTree:
// return m_supportdata && m_supportdata->support_tree_ptr && ! m_supportdata->support_tree_ptr->get().merged_mesh().empty();
return ! this->support_mesh().empty(); return ! this->support_mesh().empty();
case slaposBasePool: case slaposBasePool:
// return m_supportdata && m_supportdata->support_tree_ptr && ! m_supportdata->support_tree_ptr->get_pad().empty();
return ! this->pad_mesh().empty(); return ! this->pad_mesh().empty();
default: default:
return false; return false;
@ -566,22 +570,19 @@ TriangleMesh SLAPrintObject::get_mesh(SLAPrintObjectStep step) const
} }
} }
TriangleMesh SLAPrintObject::support_mesh() const
const TriangleMesh& SLAPrintObject::support_mesh() const
{ {
TriangleMesh trm;
if(m_supportdata && m_supportdata->support_tree_ptr) if(m_supportdata && m_supportdata->support_tree_ptr)
m_supportdata->support_tree_ptr->merged_mesh(trm); return m_supportdata->support_tree_ptr->merged_mesh();
// TODO: is this necessary? return EMPTY_MESH;
trm.repair();
return trm;
} }
TriangleMesh SLAPrintObject::pad_mesh() const const TriangleMesh& SLAPrintObject::pad_mesh() const
{ {
if(!m_supportdata || !m_supportdata->support_tree_ptr) return {}; if(!m_supportdata || !m_supportdata->support_tree_ptr) return EMPTY_MESH;
return m_supportdata->support_tree_ptr->get_pad(); return m_supportdata->support_tree_ptr->get_pad();
} }
@ -596,11 +597,7 @@ const TriangleMesh &SLAPrintObject::transformed_mesh() const {
// or apply an inverse transformation on the support structure after it // or apply an inverse transformation on the support structure after it
// has been created. // has been created.
if(m_trmesh_valid) return m_transformed_rmesh; return m_transformed_rmesh.get();
m_transformed_rmesh = m_model_object->raw_mesh();
m_transformed_rmesh.transform(m_trafo);
m_trmesh_valid = true;
return m_transformed_rmesh;
} }
std::vector<Vec3d> SLAPrintObject::transformed_support_points() const std::vector<Vec3d> SLAPrintObject::transformed_support_points() const

View file

@ -1,9 +1,12 @@
#ifndef slic3r_SLAPrint_hpp_ #ifndef slic3r_SLAPrint_hpp_
#define slic3r_SLAPrint_hpp_ #define slic3r_SLAPrint_hpp_
#include <mutex>
#include "PrintBase.hpp" #include "PrintBase.hpp"
#include "PrintExport.hpp" #include "PrintExport.hpp"
#include "Point.hpp" #include "Point.hpp"
#include "MTUtils.hpp"
namespace Slic3r { namespace Slic3r {
@ -53,10 +56,10 @@ public:
// Get a support mesh centered around origin in XY, and with zero rotation around Z applied. // Get a support mesh centered around origin in XY, and with zero rotation around Z applied.
// Support mesh is only valid if this->is_step_done(slaposSupportTree) is true. // Support mesh is only valid if this->is_step_done(slaposSupportTree) is true.
TriangleMesh support_mesh() const; const TriangleMesh& support_mesh() const;
// Get a pad mesh centered around origin in XY, and with zero rotation around Z applied. // Get a pad mesh centered around origin in XY, and with zero rotation around Z applied.
// Support mesh is only valid if this->is_step_done(slaposPad) is true. // Support mesh is only valid if this->is_step_done(slaposPad) is true.
TriangleMesh pad_mesh() const; const TriangleMesh& pad_mesh() const;
// 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;
@ -69,8 +72,9 @@ public:
// as the pad height also needs to be considered. // as the pad height also needs to be considered.
double get_elevation() const; double get_elevation() const;
// const std::vector<ExPolygons>& get_support_slices() const; // Should be obvious
// const std::vector<ExPolygons>& get_model_slices() const; const std::vector<ExPolygons>& get_support_slices() const;
const std::vector<ExPolygons>& get_model_slices() const;
// I refuse to grantee copying (Tamas) // I refuse to grantee copying (Tamas)
SLAPrintObject(const SLAPrintObject&) = delete; SLAPrintObject(const SLAPrintObject&) = delete;
@ -86,7 +90,10 @@ protected:
void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); } void config_apply(const ConfigBase &other, bool ignore_nonexistent = false) { this->m_config.apply(other, ignore_nonexistent); }
void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false) void config_apply_only(const ConfigBase &other, const t_config_option_keys &keys, bool ignore_nonexistent = false)
{ this->m_config.apply_only(other, keys, ignore_nonexistent); } { this->m_config.apply_only(other, keys, ignore_nonexistent); }
void set_trafo(const Transform3d& trafo) { m_trafo = trafo; m_trmesh_valid = false; }
void set_trafo(const Transform3d& trafo) {
m_transformed_rmesh.invalidate([this, &trafo](){ m_trafo = trafo; });
}
bool set_instances(const std::vector<Instance> &instances); bool set_instances(const std::vector<Instance> &instances);
// Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint. // Invalidates the step, and its depending steps in SLAPrintObject and SLAPrint.
@ -105,8 +112,7 @@ private:
std::vector<ExPolygons> m_model_slices; std::vector<ExPolygons> m_model_slices;
// Caching the transformed (m_trafo) raw mesh of the object // Caching the transformed (m_trafo) raw mesh of the object
mutable TriangleMesh m_transformed_rmesh; mutable CachedObject<TriangleMesh> m_transformed_rmesh;
mutable bool m_trmesh_valid = false;
class SupportData; class SupportData;
std::unique_ptr<SupportData> m_supportdata; std::unique_ptr<SupportData> m_supportdata;