Custom supports data are saved into ModelObject and propagate to the backend
Invalidation of supports after they change is not implemented yet.
This commit is contained in:
parent
46ade45ced
commit
546b0702f9
5 changed files with 118 additions and 24 deletions
src
|
@ -1149,6 +1149,8 @@ ModelObjectPtrs ModelObject::cut(size_t instance, coordf_t z, bool keep_upper, b
|
||||||
for (ModelVolume *volume : volumes) {
|
for (ModelVolume *volume : volumes) {
|
||||||
const auto volume_matrix = volume->get_matrix();
|
const auto volume_matrix = volume->get_matrix();
|
||||||
|
|
||||||
|
volume->m_supported_facets.clear();
|
||||||
|
|
||||||
if (! volume->is_model_part()) {
|
if (! volume->is_model_part()) {
|
||||||
// Modifiers are not cut, but we still need to add the instance transformation
|
// Modifiers are not cut, but we still need to add the instance transformation
|
||||||
// to the modifier volume transformation to preserve their shape properly.
|
// to the modifier volume transformation to preserve their shape properly.
|
||||||
|
@ -1848,6 +1850,41 @@ arrangement::ArrangePolygon ModelInstance::get_arrange_polygon() const
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<int> FacetsAnnotation::get_facets(FacetSupportType type) const
|
||||||
|
{
|
||||||
|
std::vector<int> out;
|
||||||
|
for (auto& [facet_idx, this_type] : m_data)
|
||||||
|
if (this_type == type)
|
||||||
|
out.push_back(facet_idx);
|
||||||
|
return out;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FacetsAnnotation::set_facet(int idx, FacetSupportType type)
|
||||||
|
{
|
||||||
|
bool changed = true;
|
||||||
|
|
||||||
|
if (type == FacetSupportType::NONE)
|
||||||
|
changed = m_data.erase(idx) != 0;
|
||||||
|
else
|
||||||
|
m_data[idx] = type;
|
||||||
|
|
||||||
|
if (changed)
|
||||||
|
update_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
void FacetsAnnotation::clear()
|
||||||
|
{
|
||||||
|
m_data.clear();
|
||||||
|
update_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
// Test whether the two models contain the same number of ModelObjects with the same set of IDs
|
||||||
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
// ordered in the same order. In that case it is not necessary to kill the background processing.
|
||||||
bool model_object_list_equal(const Model &model_old, const Model &model_new)
|
bool model_object_list_equal(const Model &model_old, const Model &model_new)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
#include <chrono>
|
||||||
|
|
||||||
namespace cereal {
|
namespace cereal {
|
||||||
class BinaryInputArchive;
|
class BinaryInputArchive;
|
||||||
|
@ -391,6 +392,35 @@ enum class ModelVolumeType : int {
|
||||||
SUPPORT_BLOCKER,
|
SUPPORT_BLOCKER,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum class FacetSupportType : int8_t {
|
||||||
|
NONE = 0,
|
||||||
|
ENFORCER = 1,
|
||||||
|
BLOCKER = 2
|
||||||
|
};
|
||||||
|
|
||||||
|
class FacetsAnnotation {
|
||||||
|
public:
|
||||||
|
using ClockType = std::chrono::steady_clock;
|
||||||
|
|
||||||
|
|
||||||
|
std::vector<int> get_facets(FacetSupportType type) const;
|
||||||
|
void set_facet(int idx, FacetSupportType type);
|
||||||
|
void clear();
|
||||||
|
|
||||||
|
ClockType::time_point get_timestamp() const { return timestamp; }
|
||||||
|
bool is_newer_than(const FacetsAnnotation& other) const {
|
||||||
|
return timestamp > other.get_timestamp();
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::map<int, FacetSupportType> m_data;
|
||||||
|
|
||||||
|
ClockType::time_point timestamp;
|
||||||
|
void update_timestamp() {
|
||||||
|
timestamp = ClockType::now();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
// An object STL, or a modifier volume, over which a different set of parameters shall be applied.
|
||||||
// ModelVolume instances are owned by a ModelObject.
|
// ModelVolume instances are owned by a ModelObject.
|
||||||
class ModelVolume final : public ObjectBase
|
class ModelVolume final : public ObjectBase
|
||||||
|
@ -421,6 +451,9 @@ public:
|
||||||
// overriding the global Slic3r settings and the ModelObject settings.
|
// overriding the global Slic3r settings and the ModelObject settings.
|
||||||
ModelConfig config;
|
ModelConfig config;
|
||||||
|
|
||||||
|
// List of mesh facets to be supported/unsupported.
|
||||||
|
FacetsAnnotation m_supported_facets;
|
||||||
|
|
||||||
// A parent object owning this modifier volume.
|
// A parent object owning this modifier volume.
|
||||||
ModelObject* get_object() const { return this->object; };
|
ModelObject* get_object() const { return this->object; };
|
||||||
ModelVolumeType type() const { return m_type; }
|
ModelVolumeType type() const { return m_type; }
|
||||||
|
@ -548,7 +581,9 @@ private:
|
||||||
// Copying an existing volume, therefore this volume will get a copy of the ID assigned.
|
// Copying an existing volume, therefore this volume will get a copy of the ID assigned.
|
||||||
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
ModelVolume(ModelObject *object, const ModelVolume &other) :
|
||||||
ObjectBase(other),
|
ObjectBase(other),
|
||||||
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull), config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation)
|
name(other.name), source(other.source), m_mesh(other.m_mesh), m_convex_hull(other.m_convex_hull),
|
||||||
|
config(other.config), m_type(other.m_type), object(object), m_transformation(other.m_transformation),
|
||||||
|
m_supported_facets(other.m_supported_facets)
|
||||||
{
|
{
|
||||||
assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
|
assert(this->id().valid()); assert(this->config.id().valid()); assert(this->id() != this->config.id());
|
||||||
assert(this->id() == other.id() && this->config.id() == other.config.id());
|
assert(this->id() == other.id() && this->config.id() == other.config.id());
|
||||||
|
@ -565,6 +600,8 @@ private:
|
||||||
if (mesh.stl.stats.number_of_facets > 1)
|
if (mesh.stl.stats.number_of_facets > 1)
|
||||||
calculate_convex_hull();
|
calculate_convex_hull();
|
||||||
assert(this->config.id().valid()); assert(this->config.id() != other.config.id()); assert(this->id() != this->config.id());
|
assert(this->config.id().valid()); assert(this->config.id() != other.config.id()); assert(this->id() != this->config.id());
|
||||||
|
|
||||||
|
m_supported_facets.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
ModelVolume& operator=(ModelVolume &rhs) = delete;
|
||||||
|
|
|
@ -404,6 +404,7 @@ static inline void model_volume_list_copy_configs(ModelObject &model_object_dst,
|
||||||
// Copy the ModelVolume data.
|
// Copy the ModelVolume data.
|
||||||
mv_dst.name = mv_src.name;
|
mv_dst.name = mv_src.name;
|
||||||
static_cast<DynamicPrintConfig&>(mv_dst.config) = static_cast<const DynamicPrintConfig&>(mv_src.config);
|
static_cast<DynamicPrintConfig&>(mv_dst.config) = static_cast<const DynamicPrintConfig&>(mv_src.config);
|
||||||
|
mv_dst.m_supported_facets = mv_src.m_supported_facets;
|
||||||
//FIXME what to do with the materials?
|
//FIXME what to do with the materials?
|
||||||
// mv_dst.m_material_id = mv_src.m_material_id;
|
// mv_dst.m_material_id = mv_src.m_material_id;
|
||||||
++ i_src;
|
++ i_src;
|
||||||
|
@ -881,7 +882,7 @@ Print::ApplyStatus Print::apply(const Model &model, DynamicPrintConfig new_full_
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Synchronize (just copy) the remaining data of ModelVolumes (name, config).
|
// Synchronize (just copy) the remaining data of ModelVolumes (name, config, custom supports data).
|
||||||
//FIXME What to do with m_material_id?
|
//FIXME What to do with m_material_id?
|
||||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
|
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::MODEL_PART);
|
||||||
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
|
model_volume_list_copy_configs(model_object /* dst */, model_object_new /* src */, ModelVolumeType::PARAMETER_MODIFIER);
|
||||||
|
|
|
@ -8,6 +8,7 @@
|
||||||
#include "slic3r/GUI/GUI_App.hpp"
|
#include "slic3r/GUI/GUI_App.hpp"
|
||||||
#include "slic3r/GUI/PresetBundle.hpp"
|
#include "slic3r/GUI/PresetBundle.hpp"
|
||||||
#include "slic3r/GUI/Camera.hpp"
|
#include "slic3r/GUI/Camera.hpp"
|
||||||
|
#include "libslic3r/Model.hpp"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@ -187,7 +188,16 @@ void GLGizmoFdmSupports::update_mesh()
|
||||||
// This mesh does not account for the possible Z up SLA offset.
|
// This mesh does not account for the possible Z up SLA offset.
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
const TriangleMesh* mesh = &mv->mesh();
|
||||||
|
|
||||||
m_selected_facets[volume_id].assign(mesh->its.indices.size(), SelType::NONE);
|
m_selected_facets[volume_id].assign(mesh->its.indices.size(), FacetSupportType::NONE);
|
||||||
|
|
||||||
|
// Load current state from ModelVolume.
|
||||||
|
for (FacetSupportType type : {FacetSupportType::ENFORCER, FacetSupportType::BLOCKER}) {
|
||||||
|
const std::vector<int>& list = mv->m_supported_facets.get_facets(type);
|
||||||
|
for (int i : list)
|
||||||
|
m_selected_facets[volume_id][i] = type;
|
||||||
|
}
|
||||||
|
update_vertex_buffers(mv, volume_id, true, true);
|
||||||
|
|
||||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||||
|
|
||||||
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
// Prepare vector of vertex_index - facet_index pairs to quickly find adjacent facets
|
||||||
|
@ -243,16 +253,16 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
|| action == SLAGizmoEventType::RightDown
|
|| action == SLAGizmoEventType::RightDown
|
||||||
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
|
|| (action == SLAGizmoEventType::Dragging && m_button_down != Button::None)) {
|
||||||
|
|
||||||
SelType new_state = SelType::NONE;
|
FacetSupportType new_state = FacetSupportType::NONE;
|
||||||
if (! shift_down) {
|
if (! shift_down) {
|
||||||
if (action == SLAGizmoEventType::Dragging)
|
if (action == SLAGizmoEventType::Dragging)
|
||||||
new_state = m_button_down == Button::Left
|
new_state = m_button_down == Button::Left
|
||||||
? SelType::ENFORCER
|
? FacetSupportType::ENFORCER
|
||||||
: SelType::BLOCKER;
|
: FacetSupportType::BLOCKER;
|
||||||
else
|
else
|
||||||
new_state = action == SLAGizmoEventType::LeftDown
|
new_state = action == SLAGizmoEventType::LeftDown
|
||||||
? SelType::ENFORCER
|
? FacetSupportType::ENFORCER
|
||||||
: SelType::BLOCKER;
|
: FacetSupportType::BLOCKER;
|
||||||
}
|
}
|
||||||
|
|
||||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||||
|
@ -379,9 +389,9 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
|
|
||||||
// Now just select all facets that passed.
|
// Now just select all facets that passed.
|
||||||
for (size_t next_facet : facets_to_select) {
|
for (size_t next_facet : facets_to_select) {
|
||||||
SelType& facet = m_selected_facets[mesh_id][next_facet];
|
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||||
|
|
||||||
if (facet != new_state && facet != SelType::NONE) {
|
if (facet != new_state && facet != FacetSupportType::NONE) {
|
||||||
// this triangle is currently in the other VBA.
|
// this triangle is currently in the other VBA.
|
||||||
// Both VBAs need to be refreshed.
|
// Both VBAs need to be refreshed.
|
||||||
update_both = true;
|
update_both = true;
|
||||||
|
@ -391,8 +401,8 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
|
|
||||||
update_vertex_buffers(mv, mesh_id,
|
update_vertex_buffers(mv, mesh_id,
|
||||||
new_state == SelType::ENFORCER || update_both,
|
new_state == FacetSupportType::ENFORCER || update_both,
|
||||||
new_state == SelType::BLOCKER || update_both
|
new_state == FacetSupportType::BLOCKER || update_both
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -416,6 +426,18 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
if ((action == SLAGizmoEventType::LeftUp || action == SLAGizmoEventType::RightUp)
|
||||||
&& m_button_down != Button::None) {
|
&& m_button_down != Button::None) {
|
||||||
m_button_down = Button::None;
|
m_button_down = Button::None;
|
||||||
|
|
||||||
|
// Synchronize gizmo with ModelVolume data.
|
||||||
|
ModelObject* mo = m_c->selection_info()->model_object();
|
||||||
|
int idx = -1;
|
||||||
|
for (ModelVolume* mv : mo->volumes) {
|
||||||
|
++idx;
|
||||||
|
if (! mv->is_model_part())
|
||||||
|
continue;
|
||||||
|
for (int i=0; i<int(m_selected_facets[idx].size()); ++i)
|
||||||
|
mv->m_supported_facets.set_facet(i, m_selected_facets[idx][i]);
|
||||||
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -430,16 +452,16 @@ void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
||||||
{
|
{
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
const TriangleMesh* mesh = &mv->mesh();
|
||||||
|
|
||||||
for (SelType type : {SelType::ENFORCER, SelType::BLOCKER}) {
|
for (FacetSupportType type : {FacetSupportType::ENFORCER, FacetSupportType::BLOCKER}) {
|
||||||
if ((type == SelType::ENFORCER && ! update_enforcers)
|
if ((type == FacetSupportType::ENFORCER && ! update_enforcers)
|
||||||
|| (type == SelType::BLOCKER && ! update_blockers))
|
|| (type == FacetSupportType::BLOCKER && ! update_blockers))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==SelType::ENFORCER ? 0 : 1];
|
GLIndexedVertexArray& iva = m_ivas[mesh_id][type==FacetSupportType::ENFORCER ? 0 : 1];
|
||||||
iva.release_geometry();
|
iva.release_geometry();
|
||||||
size_t triangle_cnt=0;
|
size_t triangle_cnt=0;
|
||||||
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
for (size_t facet_idx=0; facet_idx<m_selected_facets[mesh_id].size(); ++facet_idx) {
|
||||||
SelType status = m_selected_facets[mesh_id][facet_idx];
|
FacetSupportType status = m_selected_facets[mesh_id][facet_idx];
|
||||||
if (status != type)
|
if (status != type)
|
||||||
continue;
|
continue;
|
||||||
for (int i=0; i<3; ++i)
|
for (int i=0; i<3; ++i)
|
||||||
|
|
|
@ -9,6 +9,9 @@
|
||||||
|
|
||||||
|
|
||||||
namespace Slic3r {
|
namespace Slic3r {
|
||||||
|
|
||||||
|
enum class FacetSupportType : int8_t;
|
||||||
|
|
||||||
namespace GUI {
|
namespace GUI {
|
||||||
|
|
||||||
enum class SLAGizmoEventType : unsigned char;
|
enum class SLAGizmoEventType : unsigned char;
|
||||||
|
@ -26,15 +29,9 @@ private:
|
||||||
static constexpr float CursorRadiusMax = 8.f;
|
static constexpr float CursorRadiusMax = 8.f;
|
||||||
static constexpr float CursorRadiusStep = 0.2f;
|
static constexpr float CursorRadiusStep = 0.2f;
|
||||||
|
|
||||||
enum class SelType : int8_t {
|
|
||||||
NONE,
|
|
||||||
ENFORCER,
|
|
||||||
BLOCKER
|
|
||||||
};
|
|
||||||
|
|
||||||
// For each model-part volume, store a list of statuses of
|
// For each model-part volume, store a list of statuses of
|
||||||
// individual facets (one of the enum values above).
|
// individual facets (one of the enum values above).
|
||||||
std::vector<std::vector<SelType>> m_selected_facets;
|
std::vector<std::vector<FacetSupportType>> m_selected_facets;
|
||||||
|
|
||||||
// Store two vertex buffer arrays (for enforcers/blockers)
|
// Store two vertex buffer arrays (for enforcers/blockers)
|
||||||
// for each model-part volume.
|
// for each model-part volume.
|
||||||
|
|
Loading…
Add table
Reference in a new issue