Merge branch 'master' of https://github.com/prusa3d/PrusaSlicer
This commit is contained in:
commit
f09bed32b6
14 changed files with 342 additions and 300 deletions
|
@ -150,8 +150,17 @@ void minus(TriangleMesh &A, const TriangleMesh &B)
|
|||
triangle_mesh_to_cgal(B, meshB.m);
|
||||
|
||||
CGALMesh meshResult;
|
||||
CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m);
|
||||
|
||||
bool success = false;
|
||||
try {
|
||||
success = CGALProc::corefine_and_compute_difference(meshA.m, meshB.m, meshResult.m,
|
||||
CGALParams::throw_on_self_intersection(true), CGALParams::throw_on_self_intersection(true));
|
||||
}
|
||||
catch (const CGAL::Polygon_mesh_processing::Corefinement::Self_intersection_exception&) {
|
||||
success = false;
|
||||
}
|
||||
if (! success)
|
||||
throw std::runtime_error("CGAL corefine_and_compute_difference failed");
|
||||
|
||||
A = cgal_to_triangle_mesh(meshResult.m);
|
||||
}
|
||||
|
||||
|
|
|
@ -122,10 +122,10 @@ void SLAPrint::clear()
|
|||
}
|
||||
|
||||
// Transformation without rotation around Z and without a shift by X and Y.
|
||||
static Transform3d sla_trafo(const SLAPrint& p, const ModelObject &model_object)
|
||||
Transform3d SLAPrint::sla_trafo(const ModelObject &model_object) const
|
||||
{
|
||||
|
||||
Vec3d corr = p.relative_correction();
|
||||
Vec3d corr = this->relative_correction();
|
||||
|
||||
ModelInstance &model_instance = *model_object.instances.front();
|
||||
Vec3d offset = model_instance.get_offset();
|
||||
|
@ -376,7 +376,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||
bool sla_trafo_differs =
|
||||
model_object.instances.empty() != model_object_new.instances.empty() ||
|
||||
(! model_object.instances.empty() &&
|
||||
(! sla_trafo(*this, model_object).isApprox(sla_trafo(*this, model_object_new)) ||
|
||||
(! sla_trafo(model_object).isApprox(sla_trafo(model_object_new)) ||
|
||||
model_object.instances.front()->is_left_handed() != model_object_new.instances.front()->is_left_handed()));
|
||||
if (model_parts_differ || sla_trafo_differs) {
|
||||
// The very first step (the slicing step) is invalidated. One may freely remove all associated PrintObjects.
|
||||
|
@ -419,7 +419,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||
if (model_object.sla_drain_holes != model_object_new.sla_drain_holes)
|
||||
{
|
||||
model_object.sla_drain_holes = model_object_new.sla_drain_holes;
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposHollowing));
|
||||
update_apply_status(it_print_object_status->print_object->invalidate_step(slaposDrillHoles));
|
||||
}
|
||||
|
||||
// Copy the ModelObject name, input_file and instances. The instances will compared against PrintObject instances in the next step.
|
||||
|
@ -453,7 +453,7 @@ SLAPrint::ApplyStatus SLAPrint::apply(const Model &model, DynamicPrintConfig con
|
|||
|
||||
// FIXME: this invalidates the transformed mesh in SLAPrintObject
|
||||
// which is expensive to calculate (especially the raw_mesh() call)
|
||||
print_object->set_trafo(sla_trafo(*this, model_object), model_object.instances.front()->is_left_handed());
|
||||
print_object->set_trafo(sla_trafo(model_object), model_object.instances.front()->is_left_handed());
|
||||
|
||||
print_object->set_instances(std::move(new_instances));
|
||||
|
||||
|
@ -1101,6 +1101,8 @@ const ExPolygons &SliceRecord::get_slice(SliceOrigin o) const
|
|||
bool SLAPrintObject::has_mesh(SLAPrintObjectStep step) const
|
||||
{
|
||||
switch (step) {
|
||||
case slaposDrillHoles:
|
||||
return m_hollowing_data && !m_hollowing_data->hollow_mesh_with_holes.empty();
|
||||
case slaposSupportTree:
|
||||
return ! this->support_mesh().empty();
|
||||
case slaposPad:
|
||||
|
@ -1117,7 +1119,7 @@ TriangleMesh SLAPrintObject::get_mesh(SLAPrintObjectStep step) const
|
|||
return this->support_mesh();
|
||||
case slaposPad:
|
||||
return this->pad_mesh();
|
||||
case slaposHollowing:
|
||||
case slaposDrillHoles:
|
||||
if (m_hollowing_data)
|
||||
return m_hollowing_data->hollow_mesh_with_holes;
|
||||
[[fallthrough]];
|
||||
|
|
|
@ -78,7 +78,7 @@ public:
|
|||
// Support mesh is only valid if this->is_step_done(slaposPad) is true.
|
||||
const TriangleMesh& pad_mesh() const;
|
||||
|
||||
// Ready after this->is_step_done(slaposHollowing) is true
|
||||
// Ready after this->is_step_done(slaposDrillHoles) is true
|
||||
const TriangleMesh& hollowed_interior_mesh() const;
|
||||
|
||||
// Get the mesh that is going to be printed with all the modifications
|
||||
|
@ -421,6 +421,9 @@ public:
|
|||
// Extracted value from the configuration objects
|
||||
Vec3d relative_correction() const;
|
||||
|
||||
// Return sla tansformation for a given model_object
|
||||
Transform3d sla_trafo(const ModelObject &model_object) const;
|
||||
|
||||
std::string output_filename(const std::string &filename_base = std::string()) const override;
|
||||
|
||||
const SLAPrintStatistics& print_statistics() const { return m_print_statistics; }
|
||||
|
|
|
@ -27,7 +27,7 @@ namespace {
|
|||
|
||||
const std::array<unsigned, slaposCount> OBJ_STEP_LEVELS = {
|
||||
10, // slaposHollowing,
|
||||
10, // slaposDrillHolesIfHollowed
|
||||
10, // slaposDrillHoles
|
||||
10, // slaposObjectSlice,
|
||||
20, // slaposSupportPoints,
|
||||
10, // slaposSupportTree,
|
||||
|
@ -39,7 +39,7 @@ std::string OBJ_STEP_LABELS(size_t idx)
|
|||
{
|
||||
switch (idx) {
|
||||
case slaposHollowing: return L("Hollowing model");
|
||||
case slaposDrillHoles: return L("Drilling holes into hollowed model.");
|
||||
case slaposDrillHoles: return L("Drilling holes into model.");
|
||||
case slaposObjectSlice: return L("Slicing model");
|
||||
case slaposSupportPoints: return L("Generating support points");
|
||||
case slaposSupportTree: return L("Generating support tree");
|
||||
|
@ -80,6 +80,7 @@ SLAPrint::Steps::Steps(SLAPrint *print)
|
|||
void SLAPrint::Steps::hollow_model(SLAPrintObject &po)
|
||||
{
|
||||
po.m_hollowing_data.reset();
|
||||
|
||||
if (! po.m_config.hollowing_enable.getBool()) {
|
||||
BOOST_LOG_TRIVIAL(info) << "Skipping hollowing step!";
|
||||
return;
|
||||
|
|
|
@ -313,33 +313,38 @@ public:
|
|||
// Valid geometry_id should always be positive.
|
||||
std::pair<size_t, size_t> geometry_id;
|
||||
// An ID containing the extruder ID (used to select color).
|
||||
int extruder_id;
|
||||
// Is this object selected?
|
||||
bool selected;
|
||||
// Is this object disabled from selection?
|
||||
bool disabled;
|
||||
// Is this object printable?
|
||||
bool printable;
|
||||
// Whether or not this volume is active for rendering
|
||||
bool is_active;
|
||||
// Whether or not to use this volume when applying zoom_to_volumes()
|
||||
bool zoom_to_volumes;
|
||||
// Wheter or not this volume is enabled for outside print volume detection in shader.
|
||||
bool shader_outside_printer_detection_enabled;
|
||||
// Wheter or not this volume is outside print volume.
|
||||
bool is_outside;
|
||||
int extruder_id;
|
||||
|
||||
// Various boolean flags.
|
||||
struct {
|
||||
// Is this object selected?
|
||||
bool selected : 1;
|
||||
// Is this object disabled from selection?
|
||||
bool disabled : 1;
|
||||
// Is this object printable?
|
||||
bool printable : 1;
|
||||
// Whether or not this volume is active for rendering
|
||||
bool is_active : 1;
|
||||
// Whether or not to use this volume when applying zoom_to_volumes()
|
||||
bool zoom_to_volumes : 1;
|
||||
// Wheter or not this volume is enabled for outside print volume detection in shader.
|
||||
bool shader_outside_printer_detection_enabled : 1;
|
||||
// Wheter or not this volume is outside print volume.
|
||||
bool is_outside : 1;
|
||||
// Wheter or not this volume has been generated from a modifier
|
||||
bool is_modifier : 1;
|
||||
// Wheter or not this volume has been generated from the wipe tower
|
||||
bool is_wipe_tower : 1;
|
||||
// Wheter or not this volume has been generated from an extrusion path
|
||||
bool is_extrusion_path : 1;
|
||||
// Wheter or not to always render this volume using its own alpha
|
||||
bool force_transparent : 1;
|
||||
// Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE)
|
||||
bool force_native_color : 1;
|
||||
};
|
||||
|
||||
// Is mouse or rectangle selection over this object to select/deselect it ?
|
||||
EHoverState hover;
|
||||
// Wheter or not this volume has been generated from a modifier
|
||||
bool is_modifier;
|
||||
// Wheter or not this volume has been generated from the wipe tower
|
||||
bool is_wipe_tower;
|
||||
// Wheter or not this volume has been generated from an extrusion path
|
||||
bool is_extrusion_path;
|
||||
// Wheter or not to always render this volume using its own alpha
|
||||
bool force_transparent;
|
||||
// Whether or not always use the volume's own color (not using SELECTED/HOVER/DISABLED/OUTSIDE)
|
||||
bool force_native_color;
|
||||
EHoverState hover;
|
||||
|
||||
// Interleaved triangles & normals with indexed triangles & quads.
|
||||
GLIndexedVertexArray indexed_vertex_array;
|
||||
|
|
|
@ -1977,8 +1977,8 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
};
|
||||
|
||||
// SLA steps to pull the preview meshes for.
|
||||
typedef std::array<SLAPrintObjectStep, 2> SLASteps;
|
||||
SLASteps sla_steps = { slaposSupportTree, slaposPad };
|
||||
typedef std::array<SLAPrintObjectStep, 3> SLASteps;
|
||||
SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad };
|
||||
struct SLASupportState {
|
||||
std::array<PrintStateBase::StateWithTimeStamp, std::tuple_size<SLASteps>::value> step;
|
||||
};
|
||||
|
@ -2025,7 +2025,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
// Consider the DONE step without a valid mesh as invalid for the purpose
|
||||
// of mesh visualization.
|
||||
state.step[istep].state = PrintStateBase::INVALID;
|
||||
else
|
||||
else if (sla_steps[istep] != slaposDrillHoles)
|
||||
for (const ModelInstance* model_instance : print_object->model_object()->instances)
|
||||
// Only the instances, which are currently printable, will have the SLA support structures kept.
|
||||
// The instances outside the print bed will have the GLVolumes of their support structures released.
|
||||
|
@ -2038,7 +2038,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
}
|
||||
std::sort(model_volume_state.begin(), model_volume_state.end(), model_volume_state_lower);
|
||||
std::sort(aux_volume_state.begin(), aux_volume_state.end(), model_volume_state_lower);
|
||||
// Release all ModelVolume based GLVolumes not found in the current Model.
|
||||
// Release all ModelVolume based GLVolumes not found in the current Model. Find the GLVolume of a hollowed mesh.
|
||||
for (size_t volume_id = 0; volume_id < m_volumes.volumes.size(); ++volume_id) {
|
||||
GLVolume* volume = m_volumes.volumes[volume_id];
|
||||
ModelVolumeState key(volume);
|
||||
|
@ -2120,6 +2120,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
if (it_old_volume != deleted_volumes.end() && it_old_volume->composite_id == it->composite_id)
|
||||
// If a volume changed its ObjectID, but it reuses a GLVolume's CompositeID, maintain its selection.
|
||||
map_glvolume_old_to_new[it_old_volume->volume_idx] = m_volumes.volumes.size();
|
||||
// Note the index of the loaded volume, so that we can reload the main model GLVolume with the hollowed mesh
|
||||
// later in this function.
|
||||
it->volume_idx = m_volumes.volumes.size();
|
||||
m_volumes.load_object_volume(&model_object, obj_idx, volume_idx, instance_idx, m_color_by, m_initialized);
|
||||
m_volumes.volumes.back()->geometry_id = key.geometry_id;
|
||||
update_object_list = true;
|
||||
|
@ -2148,8 +2151,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
const ModelObject *model_object = print_object->model_object();
|
||||
// Find an index of the ModelObject
|
||||
int object_idx;
|
||||
if (std::all_of(state.step.begin(), state.step.end(), [](const PrintStateBase::StateWithTimeStamp &state){ return state.state != PrintStateBase::DONE; }))
|
||||
continue;
|
||||
// There may be new SLA volumes added to the scene for this print_object.
|
||||
// Find the object index of this print_object in the Model::objects list.
|
||||
auto it = std::find(sla_print->model().objects.begin(), sla_print->model().objects.end(), model_object);
|
||||
|
@ -2168,29 +2169,53 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
|||
assert(it != model_object->instances.end());
|
||||
int instance_idx = it - model_object->instances.begin();
|
||||
for (size_t istep = 0; istep < sla_steps.size(); ++ istep)
|
||||
if (state.step[istep].state == PrintStateBase::DONE) {
|
||||
ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
|
||||
auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
|
||||
assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id);
|
||||
if (it->new_geometry()) {
|
||||
if (sla_steps[istep] == slaposDrillHoles) {
|
||||
// Hollowing is a special case, where the mesh from the backend is being loaded into the 1st volume of an instance,
|
||||
// not into its own GLVolume.
|
||||
// There shall always be such a GLVolume allocated.
|
||||
ModelVolumeState key(model_object->volumes.front()->id(), instance.instance_id);
|
||||
auto it = std::lower_bound(model_volume_state.begin(), model_volume_state.end(), key, model_volume_state_lower);
|
||||
assert(it != model_volume_state.end() && it->geometry_id == key.geometry_id);
|
||||
assert(!it->new_geometry());
|
||||
GLVolume &volume = *m_volumes.volumes[it->volume_idx];
|
||||
if (! volume.offsets.empty() && state.step[istep].timestamp != volume.offsets.front()) {
|
||||
// The backend either produced a new hollowed mesh, or it invalidated the one that the front end has seen.
|
||||
volume.indexed_vertex_array.release_geometry();
|
||||
if (state.step[istep].state == PrintStateBase::DONE) {
|
||||
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
|
||||
assert(! mesh.empty());
|
||||
mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
|
||||
volume.indexed_vertex_array.load_mesh(mesh);
|
||||
} else {
|
||||
// Reload the original volume.
|
||||
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||
}
|
||||
volume.finalize_geometry(true);
|
||||
}
|
||||
//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
|
||||
// to the GLVolume. We should refactor GLVolume significantly, so that the GLVolume will not contain member variables
|
||||
// of various concenrs (model vs. 3D print path).
|
||||
volume.offsets = { state.step[istep].timestamp };
|
||||
} else if (state.step[istep].state == PrintStateBase::DONE) {
|
||||
// Check whether there is an existing auxiliary volume to be updated, or a new auxiliary volume to be created.
|
||||
ModelVolumeState key(state.step[istep].timestamp, instance.instance_id.id);
|
||||
auto it = std::lower_bound(aux_volume_state.begin(), aux_volume_state.end(), key, model_volume_state_lower);
|
||||
assert(it != aux_volume_state.end() && it->geometry_id == key.geometry_id);
|
||||
if (it->new_geometry()) {
|
||||
// This can be an SLA support structure that should not be rendered (in case someone used undo
|
||||
// to revert to before it was generated). If that's the case, we should not generate anything.
|
||||
if (model_object->sla_points_status != sla::PointsStatus::NoPoints)
|
||||
instances[istep].emplace_back(std::pair<size_t, size_t>(instance_idx, print_instance_idx));
|
||||
else
|
||||
shift_zs[object_idx] = 0.;
|
||||
} else {
|
||||
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
||||
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
||||
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
||||
}
|
||||
else {
|
||||
// Recycling an old GLVolume. Update the Object/Instance indices into the current Model.
|
||||
m_volumes.volumes[it->volume_idx]->composite_id = GLVolume::CompositeID(object_idx, m_volumes.volumes[it->volume_idx]->volume_idx(), instance_idx);
|
||||
m_volumes.volumes[it->volume_idx]->set_instance_transformation(model_object->instances[instance_idx]->get_transformation());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// // stores the current volumes count
|
||||
// size_t volumes_count = m_volumes.volumes.size();
|
||||
|
||||
for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
||||
if (!instances[istep].empty())
|
||||
m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
|
||||
|
@ -6081,8 +6106,6 @@ void GLCanvas3D::_load_sla_shells()
|
|||
unsigned int initial_volumes_count = (unsigned int)m_volumes.volumes.size();
|
||||
for (const SLAPrintObject::Instance& instance : obj->instances()) {
|
||||
add_volume(*obj, 0, instance, obj->get_mesh_to_print(), GLVolume::MODEL_COLOR[0], true);
|
||||
// if (! obj->hollowed_interior_mesh().empty())
|
||||
// add_volume(*obj, -int(slaposHollowing), instance, obj->hollowed_interior_mesh(), GLVolume::MODEL_COLOR[0], false);
|
||||
// Set the extruder_id and volume_id to achieve the same color as in the 3D scene when
|
||||
// through the update_volumes_colors_by_extruder() call.
|
||||
m_volumes.volumes.back()->extruder_id = obj->model_object()->volumes.front()->extruder_id();
|
||||
|
|
|
@ -4,6 +4,9 @@
|
|||
#include <GL/glew.h>
|
||||
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/GLCanvas3D.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
|
||||
|
||||
|
||||
|
@ -302,5 +305,87 @@ unsigned char picking_checksum_alpha_channel(unsigned char red, unsigned char gr
|
|||
return b;
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool CommonGizmosData::update_from_backend(GLCanvas3D& canvas, ModelObject* model_object)
|
||||
{
|
||||
recent_update = false;
|
||||
|
||||
if (m_model_object != model_object
|
||||
|| (model_object && m_model_object_id != model_object->id())) {
|
||||
m_model_object = model_object;
|
||||
m_print_object_idx = -1;
|
||||
m_mesh_raycaster.reset();
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = nullptr;
|
||||
m_mesh = nullptr;
|
||||
m_backend_mesh_transformed.clear();
|
||||
if (m_model_object) {
|
||||
m_active_instance = canvas.get_selection().get_instance_idx();
|
||||
m_active_instance_bb_radius = m_model_object->instance_bounding_box(m_active_instance).radius();
|
||||
}
|
||||
|
||||
recent_update = true;
|
||||
}
|
||||
|
||||
|
||||
if (! m_model_object || ! canvas.get_selection().is_from_single_instance())
|
||||
return false;
|
||||
|
||||
int old_po_idx = m_print_object_idx;
|
||||
|
||||
// First we need a pointer to the respective SLAPrintObject. The index into objects vector is
|
||||
// cached so we don't have todo it on each render. We only search for the po if needed:
|
||||
if (m_print_object_idx < 0 || (int)canvas.sla_print()->objects().size() != m_print_objects_count) {
|
||||
m_print_objects_count = canvas.sla_print()->objects().size();
|
||||
m_print_object_idx = -1;
|
||||
for (const SLAPrintObject* po : canvas.sla_print()->objects()) {
|
||||
++m_print_object_idx;
|
||||
if (po->model_object()->id() == m_model_object->id())
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
m_mesh = nullptr;
|
||||
// Load either the model_object mesh, or one provided by the backend
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
// The backend mesh needs to be transformed and because a pointer to it is
|
||||
// saved, a copy is stored as a member (FIXME)
|
||||
if (m_print_object_idx >=0) {
|
||||
const SLAPrintObject* po = canvas.sla_print()->objects()[m_print_object_idx];
|
||||
if (po->is_step_done(slaposDrillHoles)) {
|
||||
m_backend_mesh_transformed = po->get_mesh_to_print();
|
||||
m_backend_mesh_transformed.transform(canvas.sla_print()->sla_trafo(*m_model_object).inverse());
|
||||
m_mesh = &m_backend_mesh_transformed;
|
||||
}
|
||||
}
|
||||
|
||||
if (! m_mesh) {
|
||||
m_mesh = &m_model_object->volumes.front()->mesh();
|
||||
m_backend_mesh_transformed.clear();
|
||||
}
|
||||
|
||||
m_model_object_id = m_model_object->id();
|
||||
|
||||
if (m_mesh != m_old_mesh) {
|
||||
wxBusyCursor wait;
|
||||
m_mesh_raycaster.reset(new MeshRaycaster(*m_mesh));
|
||||
m_object_clipper.reset();
|
||||
m_supports_clipper.reset();
|
||||
m_old_mesh = m_mesh;
|
||||
m_clipping_plane_distance = 0.f;
|
||||
m_clipping_plane_distance_stash = 0.f;
|
||||
recent_update = true;
|
||||
return true;
|
||||
}
|
||||
if (! recent_update)
|
||||
recent_update = m_print_object_idx < 0 && old_po_idx >= 0;
|
||||
|
||||
return m_print_object_idx < 0 ? old_po_idx >=0 : false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
} // namespace GUI
|
||||
} // namespace Slic3r
|
||||
|
|
|
@ -31,6 +31,8 @@ static const float CONSTRAINED_COLOR[4] = { 0.5f, 0.5f, 0.5f, 1.0f };
|
|||
|
||||
class ImGuiWrapper;
|
||||
class CommonGizmosData;
|
||||
class GLCanvas3D;
|
||||
class ClippingPlane;
|
||||
|
||||
class GLGizmoBase
|
||||
{
|
||||
|
@ -189,9 +191,13 @@ class MeshClipper;
|
|||
class CommonGizmosData {
|
||||
public:
|
||||
const TriangleMesh* mesh() const {
|
||||
return (! m_mesh ? nullptr : (m_cavity_mesh ? m_cavity_mesh.get() : m_mesh));
|
||||
return (! m_mesh ? nullptr : m_mesh); //(m_cavity_mesh ? m_cavity_mesh.get() : m_mesh));
|
||||
}
|
||||
|
||||
bool update_from_backend(GLCanvas3D& canvas, ModelObject* model_object);
|
||||
|
||||
bool recent_update = false;
|
||||
|
||||
|
||||
|
||||
ModelObject* m_model_object = nullptr;
|
||||
|
@ -200,8 +206,8 @@ public:
|
|||
std::unique_ptr<MeshClipper> m_object_clipper;
|
||||
std::unique_ptr<MeshClipper> m_supports_clipper;
|
||||
|
||||
std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
||||
std::unique_ptr<GLVolume> m_volume_with_cavity;
|
||||
//std::unique_ptr<TriangleMesh> m_cavity_mesh;
|
||||
//std::unique_ptr<GLVolume> m_volume_with_cavity;
|
||||
|
||||
int m_active_instance = -1;
|
||||
float m_active_instance_bb_radius = 0;
|
||||
|
@ -209,6 +215,22 @@ public:
|
|||
int m_print_object_idx = -1;
|
||||
int m_print_objects_count = -1;
|
||||
int m_old_timestamp = -1;
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
|
||||
void stash_clipping_plane() {
|
||||
m_clipping_plane_distance_stash = m_clipping_plane_distance;
|
||||
}
|
||||
|
||||
void unstash_clipping_plane() {
|
||||
m_clipping_plane_distance = m_clipping_plane_distance_stash;
|
||||
}
|
||||
|
||||
private:
|
||||
const TriangleMesh* m_old_mesh;
|
||||
TriangleMesh m_backend_mesh_transformed;
|
||||
float m_clipping_plane_distance_stash = 0.f;
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -22,7 +22,7 @@ GLGizmoHollow::GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filenam
|
|||
: GLGizmoBase(parent, icon_filename, sprite_id, cd)
|
||||
, m_quadric(nullptr)
|
||||
{
|
||||
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
// using GLU_FILL does not work when the instance's transformation
|
||||
|
@ -40,7 +40,7 @@ bool GLGizmoHollow::on_init()
|
|||
{
|
||||
m_shortcut_key = WXK_CONTROL_H;
|
||||
m_desc["enable"] = _(L("Hollow this object"));
|
||||
m_desc["preview"] = _(L("Preview"));
|
||||
m_desc["preview"] = _(L("Preview hollowed and drilled model"));
|
||||
m_desc["offset"] = _(L("Offset")) + ": ";
|
||||
m_desc["quality"] = _(L("Quality")) + ": ";
|
||||
m_desc["closing_distance"] = _(L("Closing distance")) + ": ";
|
||||
|
@ -55,38 +55,16 @@ bool GLGizmoHollow::on_init()
|
|||
return true;
|
||||
}
|
||||
|
||||
void GLGizmoHollow::set_sla_support_data(ModelObject* model_object, const Selection& selection)
|
||||
void GLGizmoHollow::set_sla_support_data(ModelObject*, const Selection&)
|
||||
{
|
||||
if (! model_object || selection.is_empty()) {
|
||||
m_c->m_model_object = nullptr;
|
||||
return;
|
||||
}
|
||||
if (m_c->recent_update) {
|
||||
|
||||
bool something_changed = false;
|
||||
|
||||
if (m_c->m_model_object != model_object
|
||||
|| m_c->m_model_object_id != model_object->id()
|
||||
|| m_c->m_active_instance != selection.get_instance_idx()) {
|
||||
m_c->m_model_object = model_object;
|
||||
m_c->m_print_object_idx = -1;
|
||||
m_c->m_active_instance = selection.get_instance_idx();
|
||||
something_changed = true;
|
||||
}
|
||||
|
||||
if (model_object && something_changed && selection.is_from_single_instance())
|
||||
{
|
||||
// Cache the bb - it's needed for dealing with the clipping plane quite often
|
||||
// It could be done inside update_mesh but one has to account for scaling of the instance.
|
||||
m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius();
|
||||
|
||||
if (is_mesh_update_necessary()) {
|
||||
update_mesh();
|
||||
if (m_c->m_model_object)
|
||||
reload_cache();
|
||||
}
|
||||
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
else
|
||||
|
@ -109,8 +87,8 @@ void GLGizmoHollow::on_render() const
|
|||
return;
|
||||
}
|
||||
|
||||
if (! m_c->m_mesh)
|
||||
const_cast<GLGizmoHollow*>(this)->update_mesh();
|
||||
// !!! is it necessary?
|
||||
//const_cast<GLGizmoHollow*>(this)->m_c->update_from_backend(m_parent, m_c->m_model_object);
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
@ -132,7 +110,7 @@ void GLGizmoHollow::on_render() const
|
|||
|
||||
void GLGizmoHollow::render_hollowed_mesh() const
|
||||
{
|
||||
if (m_c->m_volume_with_cavity) {
|
||||
/*if (m_c->m_volume_with_cavity) {
|
||||
m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift);
|
||||
m_parent.get_shader().start_using();
|
||||
|
||||
|
@ -148,14 +126,13 @@ void GLGizmoHollow::render_hollowed_mesh() const
|
|||
m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation());
|
||||
m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id);
|
||||
m_parent.get_shader().stop_using();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoHollow::render_clipping_plane(const Selection& selection) const
|
||||
{
|
||||
if (m_clipping_plane_distance == 0.f || m_c->mesh()->empty())
|
||||
if (m_c->m_clipping_plane_distance == 0.f)
|
||||
return;
|
||||
|
||||
// Get transformation of the instance
|
||||
|
@ -177,22 +154,14 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const
|
|||
m_c->m_object_clipper.reset(new MeshClipper);
|
||||
m_c->m_object_clipper->set_mesh(*m_c->mesh());
|
||||
}
|
||||
m_c->m_object_clipper->set_plane(*m_clipping_plane);
|
||||
m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane);
|
||||
m_c->m_object_clipper->set_transformation(trafo);
|
||||
|
||||
|
||||
// Next, ask the backend if supports are already calculated. If so, we are gonna cut them too.
|
||||
// First we need a pointer to the respective SLAPrintObject. The index into objects vector is
|
||||
// cached so we don't have todo it on each render. We only search for the po if needed:
|
||||
if (m_c->m_print_object_idx < 0 || (int)m_parent.sla_print()->objects().size() != m_c->m_print_objects_count) {
|
||||
m_c->m_print_objects_count = m_parent.sla_print()->objects().size();
|
||||
m_c->m_print_object_idx = -1;
|
||||
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
||||
++m_c->m_print_object_idx;
|
||||
if (po->model_object()->id() == m_c->m_model_object->id())
|
||||
break;
|
||||
}
|
||||
}
|
||||
//if (m_c->m_print_object_idx < 0)
|
||||
// m_c->update_from_backend(m_parent, m_c->m_model_object);
|
||||
|
||||
if (m_c->m_print_object_idx >= 0) {
|
||||
const SLAPrintObject* print_object = m_parent.sla_print()->objects()[m_c->m_print_object_idx];
|
||||
|
||||
|
@ -208,7 +177,7 @@ void GLGizmoHollow::render_clipping_plane(const Selection& selection) const
|
|||
m_c->m_supports_clipper->set_mesh(print_object->support_mesh());
|
||||
m_c->m_old_timestamp = timestamp;
|
||||
}
|
||||
m_c->m_supports_clipper->set_plane(*m_clipping_plane);
|
||||
m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane);
|
||||
m_c->m_supports_clipper->set_transformation(supports_trafo);
|
||||
}
|
||||
else
|
||||
|
@ -345,46 +314,12 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking) cons
|
|||
|
||||
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
||||
{
|
||||
if (m_clipping_plane_distance == 0.f)
|
||||
if (m_c->m_clipping_plane_distance == 0.f)
|
||||
return false;
|
||||
|
||||
Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point;
|
||||
transformed_point(2) += m_z_shift;
|
||||
return m_clipping_plane->is_point_clipped(transformed_point);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool GLGizmoHollow::is_mesh_update_necessary() const
|
||||
{
|
||||
return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty())
|
||||
&& ((m_c->m_model_object->id() != m_c->m_model_object_id) || ! m_c->m_mesh);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoHollow::update_mesh()
|
||||
{
|
||||
if (! m_c->m_model_object)
|
||||
return;
|
||||
|
||||
wxBusyCursor wait;
|
||||
// this way we can use that mesh directly.
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh();
|
||||
|
||||
// If this is different mesh than last time
|
||||
if (m_c->m_model_object_id != m_c->m_model_object->id()) {
|
||||
m_c->m_cavity_mesh.reset(); // dump the cavity
|
||||
m_c->m_volume_with_cavity.reset();
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_c->m_mesh_raycaster.reset();
|
||||
}
|
||||
|
||||
if (! m_c->m_mesh_raycaster)
|
||||
m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh()));
|
||||
|
||||
m_c->m_model_object_id = m_c->m_model_object->id();
|
||||
return m_c->m_clipping_plane->is_point_clipped(transformed_point);
|
||||
}
|
||||
|
||||
|
||||
|
@ -393,9 +328,11 @@ void GLGizmoHollow::update_mesh()
|
|||
// Return false if no intersection was found, true otherwise.
|
||||
bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
|
||||
{
|
||||
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
|
||||
if (! m_c->m_mesh_raycaster)
|
||||
update_mesh();
|
||||
return false;
|
||||
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
|
||||
// !!! is it really necessary?
|
||||
//m_c->update_from_backend(m_parent, m_c->m_model_object);
|
||||
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
@ -406,7 +343,7 @@ bool GLGizmoHollow::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, V
|
|||
// The raycaster query
|
||||
Vec3f hit;
|
||||
Vec3f normal;
|
||||
if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) {
|
||||
if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) {
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
return true;
|
||||
|
@ -492,7 +429,7 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||
points_inside.push_back(points[idx].cast<float>());
|
||||
|
||||
// Only select/deselect points that are actually visible
|
||||
for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get()))
|
||||
for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get()))
|
||||
{
|
||||
if (rectangle_status == GLSelectionRectangle::Deselect)
|
||||
unselect_point(points_idxs[idx]);
|
||||
|
@ -546,13 +483,13 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
|||
}
|
||||
|
||||
if (action == SLAGizmoEventType::MouseWheelUp && control_down) {
|
||||
m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f);
|
||||
m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f);
|
||||
update_clipping_plane(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::MouseWheelDown && control_down) {
|
||||
m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f);
|
||||
m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f);
|
||||
update_clipping_plane(true);
|
||||
return true;
|
||||
}
|
||||
|
@ -605,7 +542,7 @@ void GLGizmoHollow::update_mesh_raycaster(std::unique_ptr<MeshRaycaster> &&rc)
|
|||
{
|
||||
m_c->m_mesh_raycaster = std::move(rc);
|
||||
m_c->m_object_clipper.reset();
|
||||
m_c->m_volume_with_cavity.reset();
|
||||
//m_c->m_volume_with_cavity.reset();
|
||||
}
|
||||
|
||||
void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
|
||||
|
@ -622,8 +559,8 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
|
|||
void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr<TriangleMesh> &&mesh)
|
||||
{
|
||||
// Called from Plater when the UI job finishes
|
||||
m_c->m_cavity_mesh = std::move(mesh);
|
||||
|
||||
/*m_c->m_cavity_mesh = std::move(mesh);
|
||||
|
||||
if(m_c->m_cavity_mesh) {
|
||||
// First subtract the holes:
|
||||
if (! m_c->m_model_object->sla_drain_holes.empty()) {
|
||||
|
@ -665,10 +602,10 @@ void GLGizmoHollow::update_hollowed_mesh(std::unique_ptr<TriangleMesh> &&mesh)
|
|||
m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh()));
|
||||
}
|
||||
|
||||
if (m_clipping_plane_distance == 0.f) {
|
||||
m_clipping_plane_distance = 0.5f;
|
||||
if (m_c->m_clipping_plane_distance == 0.f) {
|
||||
m_c->m_clipping_plane_distance = 0.5f;
|
||||
update_clipping_plane();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>> GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
||||
|
@ -701,10 +638,10 @@ std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>> GLGizmoHollo
|
|||
|
||||
ClippingPlane GLGizmoHollow::get_sla_clipping_plane() const
|
||||
{
|
||||
if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f)
|
||||
if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f)
|
||||
return ClippingPlane::ClipsNothing();
|
||||
else
|
||||
return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]);
|
||||
return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -724,18 +661,24 @@ RENDER_AGAIN:
|
|||
|
||||
// First calculate width of all the texts that are could possibly be shown. We will decide set the dialog width based on that:
|
||||
const float settings_sliders_left =
|
||||
std::max(std::max(m_imgui->calc_text_size(m_desc.at("offset")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("quality")).x),
|
||||
m_imgui->calc_text_size(m_desc.at("closing_distance")).x)
|
||||
+ m_imgui->scaled(1.f);
|
||||
std::max({m_imgui->calc_text_size(m_desc.at("offset")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("quality")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("closing_distance")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("hole_diameter")).x,
|
||||
m_imgui->calc_text_size(m_desc.at("hole_depth")).x})
|
||||
+ m_imgui->scaled(1.f);
|
||||
|
||||
const float clipping_slider_left = std::max(m_imgui->calc_text_size(m_desc.at("clipping_of_view")).x, m_imgui->calc_text_size(m_desc.at("reset_direction")).x) + m_imgui->scaled(1.5f);
|
||||
const float diameter_slider_left = m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f);
|
||||
const float diameter_slider_left = settings_sliders_left; //m_imgui->calc_text_size(m_desc.at("hole_diameter")).x + m_imgui->scaled(1.f);
|
||||
const float minimal_slider_width = m_imgui->scaled(4.f);
|
||||
//const float buttons_width_approx = m_imgui->calc_text_size(m_desc.at("apply_changes")).x + m_imgui->calc_text_size(m_desc.at("discard_changes")).x + m_imgui->scaled(1.5f);
|
||||
|
||||
float window_width = minimal_slider_width + std::max(std::max(settings_sliders_left, clipping_slider_left), diameter_slider_left);
|
||||
window_width = std::max(std::max(window_width, /*buttons_width_approx*/0.f), 0.f);
|
||||
float window_width = minimal_slider_width + std::max({settings_sliders_left, clipping_slider_left, diameter_slider_left});
|
||||
window_width = std::max(window_width, m_imgui->calc_text_size(m_desc.at("preview")).x);
|
||||
|
||||
if (m_imgui->button(m_desc["preview"]))
|
||||
hollow_mesh();
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
{
|
||||
auto opts = get_config_options({"hollowing_enable"});
|
||||
|
@ -745,11 +688,8 @@ RENDER_AGAIN:
|
|||
wxGetApp().obj_list()->update_and_show_object_settings_item();
|
||||
}
|
||||
}
|
||||
m_imgui->disabled_begin(! m_enable_hollowing);
|
||||
|
||||
ImGui::SameLine();
|
||||
if (m_imgui->button(m_desc["preview"]))
|
||||
hollow_mesh();
|
||||
m_imgui->disabled_begin(! m_enable_hollowing);
|
||||
|
||||
std::vector<std::string> opts_keys = {"hollowing_min_thickness", "hollowing_quality", "hollowing_closing_distance"};
|
||||
auto opts = get_config_options(opts_keys);
|
||||
|
@ -834,7 +774,7 @@ RENDER_AGAIN:
|
|||
// m_imgui->text(" "); // vertical gap
|
||||
ImGui::Separator();
|
||||
|
||||
float diameter_upper_cap = 5.f;
|
||||
float diameter_upper_cap = 15.;
|
||||
if (m_new_hole_radius > diameter_upper_cap)
|
||||
m_new_hole_radius = diameter_upper_cap;
|
||||
m_imgui->text(m_desc.at("hole_diameter"));
|
||||
|
@ -904,7 +844,7 @@ RENDER_AGAIN:
|
|||
// Following is rendered in both editing and non-editing mode:
|
||||
// m_imgui->text("");
|
||||
ImGui::Separator();
|
||||
if (m_clipping_plane_distance == 0.f)
|
||||
if (m_c->m_clipping_plane_distance == 0.f)
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
else {
|
||||
if (m_imgui->button(m_desc.at("reset_direction"))) {
|
||||
|
@ -916,7 +856,7 @@ RENDER_AGAIN:
|
|||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
if (ImGui::SliderFloat(" ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
update_clipping_plane(true);
|
||||
|
||||
// make sure supports are shown/hidden as appropriate
|
||||
|
@ -973,7 +913,7 @@ bool GLGizmoHollow::on_is_selectable() const
|
|||
|
||||
std::string GLGizmoHollow::on_get_name() const
|
||||
{
|
||||
return (_(L("Hollowing")) + " [H]").ToUTF8().data();
|
||||
return (_(L("Hollowing and drilling")) + " [H]").ToUTF8().data();
|
||||
}
|
||||
|
||||
|
||||
|
@ -995,17 +935,19 @@ void GLGizmoHollow::on_set_state()
|
|||
|
||||
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
|
||||
//Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
||||
if (is_mesh_update_necessary())
|
||||
update_mesh();
|
||||
//m_c->update_from_backend(m_parent, m_c->m_model_object);
|
||||
m_c->unstash_clipping_plane();
|
||||
update_clipping_plane(m_c->m_clipping_plane_distance != 0.f);
|
||||
|
||||
// we'll now reload support points:
|
||||
if (m_c->m_model_object)
|
||||
reload_cache();
|
||||
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
if (m_c->m_model_object)
|
||||
m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance);
|
||||
if (m_c->m_model_object) {
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(m_show_supports, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
|
||||
// Set default head diameter from config.
|
||||
//const DynamicPrintConfig& cfg = wxGetApp().preset_bundle->sla_prints.get_edited_preset().config;
|
||||
|
@ -1014,8 +956,9 @@ void GLGizmoHollow::on_set_state()
|
|||
if (m_state == Off && m_old_state != Off) { // the gizmo was just turned Off
|
||||
//Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
m_clipping_plane_distance = 0.f;
|
||||
update_clipping_plane();
|
||||
m_c->stash_clipping_plane();
|
||||
m_c->m_clipping_plane_distance = 0.f;
|
||||
update_clipping_plane(true);
|
||||
// Release clippers and the AABB raycaster.
|
||||
m_c->m_object_clipper.reset();
|
||||
m_c->m_supports_clipper.reset();
|
||||
|
@ -1060,8 +1003,8 @@ void GLGizmoHollow::on_stop_dragging()
|
|||
|
||||
void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar)
|
||||
{
|
||||
ar(m_clipping_plane_distance,
|
||||
*m_clipping_plane,
|
||||
ar(m_c->m_clipping_plane_distance,
|
||||
*m_c->m_clipping_plane,
|
||||
m_c->m_model_object_id,
|
||||
m_new_hole_radius,
|
||||
m_new_hole_height,
|
||||
|
@ -1074,8 +1017,8 @@ void GLGizmoHollow::on_load(cereal::BinaryInputArchive& ar)
|
|||
|
||||
void GLGizmoHollow::on_save(cereal::BinaryOutputArchive& ar) const
|
||||
{
|
||||
ar(m_clipping_plane_distance,
|
||||
*m_clipping_plane,
|
||||
ar(m_c->m_clipping_plane_distance,
|
||||
*m_c->m_clipping_plane,
|
||||
m_c->m_model_object_id,
|
||||
m_new_hole_radius,
|
||||
m_new_hole_height,
|
||||
|
@ -1128,12 +1071,14 @@ void GLGizmoHollow::reload_cache()
|
|||
|
||||
void GLGizmoHollow::update_clipping_plane(bool keep_normal) const
|
||||
{
|
||||
Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ?
|
||||
m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward());
|
||||
if (! m_c->m_model_object)
|
||||
return;
|
||||
Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ?
|
||||
m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward());
|
||||
|
||||
const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift);
|
||||
float dist = normal.dot(center);
|
||||
*m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius));
|
||||
*m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius));
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -53,14 +53,12 @@ private:
|
|||
void render_points(const Selection& selection, bool picking = false) const;
|
||||
void render_clipping_plane(const Selection& selection) const;
|
||||
void render_hollowed_mesh() const;
|
||||
bool is_mesh_update_necessary() const;
|
||||
void update_mesh();
|
||||
void hollow_mesh(bool postpone_error_messages = false);
|
||||
bool unsaved_changes() const;
|
||||
|
||||
bool m_show_supports = true;
|
||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||
float m_new_hole_height = 5.f;
|
||||
float m_new_hole_height = 6.f;
|
||||
mutable std::vector<bool> m_selected; // which holes are currently selected
|
||||
|
||||
bool m_enable_hollowing = true;
|
||||
|
@ -72,13 +70,9 @@ private:
|
|||
float m_closing_d_stash = 2.f;
|
||||
Vec3f m_hole_before_drag = Vec3f::Zero();
|
||||
|
||||
|
||||
sla::DrainHoles m_holes_stash;
|
||||
|
||||
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
//std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
|
|
|
@ -27,7 +27,7 @@ GLGizmoSlaSupports::GLGizmoSlaSupports(GLCanvas3D& parent, const std::string& ic
|
|||
, m_quadric(nullptr)
|
||||
, m_its(nullptr)
|
||||
{
|
||||
m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
m_c->m_clipping_plane.reset(new ClippingPlane(Vec3d::Zero(), 0.));
|
||||
m_quadric = ::gluNewQuadric();
|
||||
if (m_quadric != nullptr)
|
||||
// using GLU_FILL does not work when the instance's transformation
|
||||
|
@ -63,43 +63,22 @@ bool GLGizmoSlaSupports::on_init()
|
|||
|
||||
void GLGizmoSlaSupports::set_sla_support_data(ModelObject* model_object, const Selection& selection)
|
||||
{
|
||||
if (! model_object || selection.is_empty()) {
|
||||
m_c->m_model_object = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
bool something_changed = false;
|
||||
|
||||
if (m_c->m_model_object != model_object
|
||||
|| m_c->m_model_object_id != model_object->id()
|
||||
|| m_c->m_active_instance != selection.get_instance_idx()) {
|
||||
m_c->m_model_object = model_object;
|
||||
m_c->m_print_object_idx = -1;
|
||||
m_c->m_active_instance = selection.get_instance_idx();
|
||||
something_changed = true;
|
||||
}
|
||||
|
||||
if (model_object && selection.is_from_single_instance())
|
||||
{
|
||||
// Cache the bb - it's needed for dealing with the clipping plane quite often
|
||||
// It could be done inside update_mesh but one has to account for scaling of the instance.
|
||||
if (something_changed) {
|
||||
m_c->m_active_instance_bb_radius = m_c->m_model_object->instance_bounding_box(m_c->m_active_instance).radius();
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(! m_c->m_cavity_mesh, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
else
|
||||
m_parent.toggle_model_objects_visibility(true, nullptr, -1);
|
||||
if (m_c->recent_update) {
|
||||
if (m_state == On) {
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
m_parent.toggle_model_objects_visibility(/*! m_c->m_cavity_mesh*/ true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
}
|
||||
else
|
||||
m_parent.toggle_model_objects_visibility(true, nullptr, -1);
|
||||
|
||||
if (is_mesh_update_necessary()) {
|
||||
update_mesh();
|
||||
disable_editing_mode();
|
||||
if (m_c->m_model_object)
|
||||
reload_cache();
|
||||
}
|
||||
}
|
||||
|
||||
// If we triggered autogeneration before, check backend and fetch results if they are there
|
||||
// If we triggered autogeneration before, check backend and fetch results if they are there
|
||||
if (m_c->m_model_object) {
|
||||
if (m_c->m_model_object->sla_points_status == sla::PointsStatus::Generating)
|
||||
get_data_from_backend();
|
||||
}
|
||||
|
@ -120,9 +99,6 @@ void GLGizmoSlaSupports::on_render() const
|
|||
return;
|
||||
}
|
||||
|
||||
if (! m_its || ! m_c->m_mesh)
|
||||
const_cast<GLGizmoSlaSupports*>(this)->update_mesh();
|
||||
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
|
@ -143,7 +119,7 @@ void GLGizmoSlaSupports::on_render() const
|
|||
|
||||
void GLGizmoSlaSupports::render_hollowed_mesh() const
|
||||
{
|
||||
if (m_c->m_volume_with_cavity) {
|
||||
/*if (m_c->m_volume_with_cavity) {
|
||||
m_c->m_volume_with_cavity->set_sla_shift_z(m_z_shift);
|
||||
m_parent.get_shader().start_using();
|
||||
|
||||
|
@ -159,14 +135,14 @@ void GLGizmoSlaSupports::render_hollowed_mesh() const
|
|||
m_c->m_volume_with_cavity->set_instance_transformation(m_c->m_model_object->instances[size_t(m_c->m_active_instance)]->get_transformation());
|
||||
m_c->m_volume_with_cavity->render(color_id, print_box_detection_id, print_box_worldmatrix_id);
|
||||
m_parent.get_shader().stop_using();
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
||||
{
|
||||
if (m_clipping_plane_distance == 0.f || m_c->m_mesh->empty())
|
||||
if (m_c->m_clipping_plane_distance == 0.f || m_c->m_mesh->empty())
|
||||
return;
|
||||
|
||||
// Get transformation of the instance
|
||||
|
@ -188,7 +164,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
|||
m_c->m_object_clipper.reset(new MeshClipper);
|
||||
m_c->m_object_clipper->set_mesh(*m_c->mesh());
|
||||
}
|
||||
m_c->m_object_clipper->set_plane(*m_clipping_plane);
|
||||
m_c->m_object_clipper->set_plane(*m_c->m_clipping_plane);
|
||||
m_c->m_object_clipper->set_transformation(trafo);
|
||||
|
||||
|
||||
|
@ -219,7 +195,7 @@ void GLGizmoSlaSupports::render_clipping_plane(const Selection& selection) const
|
|||
m_c->m_supports_clipper->set_mesh(print_object->support_mesh());
|
||||
m_c->m_old_timestamp = timestamp;
|
||||
}
|
||||
m_c->m_supports_clipper->set_plane(*m_clipping_plane);
|
||||
m_c->m_supports_clipper->set_plane(*m_c->m_clipping_plane);
|
||||
m_c->m_supports_clipper->set_transformation(supports_trafo);
|
||||
}
|
||||
else
|
||||
|
@ -359,7 +335,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||
}
|
||||
|
||||
// Now render the drain holes:
|
||||
if (! m_c->m_cavity_mesh) {
|
||||
/*if (! m_c->m_cavity_mesh) {
|
||||
render_color[0] = 0.7f;
|
||||
render_color[1] = 0.7f;
|
||||
render_color[2] = 0.7f;
|
||||
|
@ -394,7 +370,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||
glFrontFace(GL_CCW);
|
||||
glsafe(::glPopMatrix());
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
if (!picking)
|
||||
glsafe(::glDisable(GL_LIGHTING));
|
||||
|
@ -406,51 +382,22 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
|||
|
||||
bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||
{
|
||||
if (m_clipping_plane_distance == 0.f)
|
||||
if (m_c->m_clipping_plane_distance == 0.f)
|
||||
return false;
|
||||
|
||||
Vec3d transformed_point = m_c->m_model_object->instances[m_c->m_active_instance]->get_transformation().get_matrix() * point;
|
||||
transformed_point(2) += m_z_shift;
|
||||
return m_clipping_plane->is_point_clipped(transformed_point);
|
||||
return m_c->m_clipping_plane->is_point_clipped(transformed_point);
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool GLGizmoSlaSupports::is_mesh_update_necessary() const
|
||||
{
|
||||
return ((m_state == On) && (m_c->m_model_object != nullptr) && !m_c->m_model_object->instances.empty())
|
||||
&& ((m_c->m_model_object->id() != m_c->m_model_object_id) || m_its == nullptr);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void GLGizmoSlaSupports::update_mesh()
|
||||
{
|
||||
if (! m_c->m_model_object)
|
||||
return;
|
||||
|
||||
wxBusyCursor wait;
|
||||
// this way we can use that mesh directly.
|
||||
// This mesh does not account for the possible Z up SLA offset.
|
||||
m_c->m_mesh = &m_c->m_model_object->volumes.front()->mesh();
|
||||
m_its = &m_c->m_mesh->its;
|
||||
|
||||
// If this is different mesh than last time or if the AABB tree is uninitialized, recalculate it.
|
||||
if (m_c->m_model_object_id != m_c->m_model_object->id() || ! m_c->m_mesh_raycaster)
|
||||
m_c->m_mesh_raycaster.reset(new MeshRaycaster(*m_c->mesh()));
|
||||
|
||||
m_c->m_model_object_id = m_c->m_model_object->id();
|
||||
disable_editing_mode();
|
||||
}
|
||||
|
||||
|
||||
// Unprojects the mouse position on the mesh and saves hit point and normal of the facet into pos_and_normal
|
||||
// Return false if no intersection was found, true otherwise.
|
||||
bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal)
|
||||
{
|
||||
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
|
||||
if (! m_c->m_mesh_raycaster)
|
||||
update_mesh();
|
||||
return false;
|
||||
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
@ -461,20 +408,20 @@ bool GLGizmoSlaSupports::unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec
|
|||
// The raycaster query
|
||||
Vec3f hit;
|
||||
Vec3f normal;
|
||||
if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_clipping_plane.get())) {
|
||||
if (m_c->m_mesh_raycaster->unproject_on_mesh(mouse_pos, trafo.get_matrix(), camera, hit, normal, m_c->m_clipping_plane.get())) {
|
||||
// Check whether the hit is in a hole
|
||||
bool in_hole = false;
|
||||
// In case the hollowed and drilled mesh is available, we can allow
|
||||
// placing points in holes, because they should never end up
|
||||
// on surface that's been drilled away.
|
||||
if (! m_c->m_cavity_mesh) {
|
||||
/*if (! m_c->m_cavity_mesh) {
|
||||
for (const sla::DrainHole& hole : m_c->m_model_object->sla_drain_holes) {
|
||||
if (hole.is_inside(hit)) {
|
||||
in_hole = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
if (! in_hole) {
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
|
@ -555,7 +502,7 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
points_inside.push_back(points[idx].cast<float>());
|
||||
|
||||
// Only select/deselect points that are actually visible
|
||||
for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_clipping_plane.get()))
|
||||
for (size_t idx : m_c->m_mesh_raycaster->get_unobscured_idxs(trafo, m_parent.get_camera(), points_inside, m_c->m_clipping_plane.get()))
|
||||
{
|
||||
if (rectangle_status == GLSelectionRectangle::Deselect)
|
||||
unselect_point(points_idxs[idx]);
|
||||
|
@ -632,13 +579,13 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
}
|
||||
|
||||
if (action == SLAGizmoEventType::MouseWheelUp && control_down) {
|
||||
m_clipping_plane_distance = std::min(1.f, m_clipping_plane_distance + 0.01f);
|
||||
m_c->m_clipping_plane_distance = std::min(1.f, m_c->m_clipping_plane_distance + 0.01f);
|
||||
update_clipping_plane(true);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (action == SLAGizmoEventType::MouseWheelDown && control_down) {
|
||||
m_clipping_plane_distance = std::max(0.f, m_clipping_plane_distance - 0.01f);
|
||||
m_c->m_clipping_plane_distance = std::max(0.f, m_c->m_clipping_plane_distance - 0.01f);
|
||||
update_clipping_plane(true);
|
||||
return true;
|
||||
}
|
||||
|
@ -719,10 +666,10 @@ std::vector<const ConfigOption*> GLGizmoSlaSupports::get_config_options(const st
|
|||
|
||||
ClippingPlane GLGizmoSlaSupports::get_sla_clipping_plane() const
|
||||
{
|
||||
if (!m_c->m_model_object || m_state == Off || m_clipping_plane_distance == 0.f)
|
||||
if (!m_c->m_model_object || m_state == Off || m_c->m_clipping_plane_distance == 0.f)
|
||||
return ClippingPlane::ClipsNothing();
|
||||
else
|
||||
return ClippingPlane(-m_clipping_plane->get_normal(), m_clipping_plane->get_data()[3]);
|
||||
return ClippingPlane(-m_c->m_clipping_plane->get_normal(), m_c->m_clipping_plane->get_data()[3]);
|
||||
}
|
||||
|
||||
|
||||
|
@ -944,7 +891,7 @@ RENDER_AGAIN:
|
|||
|
||||
// Following is rendered in both editing and non-editing mode:
|
||||
ImGui::Separator();
|
||||
if (m_clipping_plane_distance == 0.f)
|
||||
if (m_c->m_clipping_plane_distance == 0.f)
|
||||
{
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(m_desc.at("clipping_of_view"));
|
||||
|
@ -959,7 +906,7 @@ RENDER_AGAIN:
|
|||
|
||||
ImGui::SameLine(clipping_slider_left);
|
||||
ImGui::PushItemWidth(window_width - clipping_slider_left);
|
||||
if (ImGui::SliderFloat(" ", &m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
if (ImGui::SliderFloat(" ", &m_c->m_clipping_plane_distance, 0.f, 1.f, "%.2f"))
|
||||
update_clipping_plane(true);
|
||||
|
||||
|
||||
|
@ -1043,15 +990,17 @@ void GLGizmoSlaSupports::on_set_state()
|
|||
|
||||
if (m_state == On && m_old_state != On) { // the gizmo was just turned on
|
||||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned on")));
|
||||
if (is_mesh_update_necessary())
|
||||
update_mesh();
|
||||
|
||||
m_c->unstash_clipping_plane();
|
||||
update_clipping_plane(m_c->m_clipping_plane_distance != 0.f);
|
||||
|
||||
|
||||
// we'll now reload support points:
|
||||
if (m_c->m_model_object)
|
||||
reload_cache();
|
||||
|
||||
m_parent.toggle_model_objects_visibility(false);
|
||||
if (m_c->m_model_object && ! m_c->m_cavity_mesh)
|
||||
if (m_c->m_model_object /*&& ! m_c->m_cavity_mesh*/)
|
||||
m_parent.toggle_model_objects_visibility(true, m_c->m_model_object, m_c->m_active_instance);
|
||||
m_parent.toggle_sla_auxiliaries_visibility(! m_editing_mode, m_c->m_model_object, m_c->m_active_instance);
|
||||
|
||||
|
@ -1081,13 +1030,14 @@ void GLGizmoSlaSupports::on_set_state()
|
|||
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _(L("SLA gizmo turned off")));
|
||||
m_parent.toggle_model_objects_visibility(true);
|
||||
m_normal_cache.clear();
|
||||
m_clipping_plane_distance = 0.f;
|
||||
update_clipping_plane();
|
||||
m_c->stash_clipping_plane();
|
||||
m_c->m_clipping_plane_distance = 0.f;
|
||||
update_clipping_plane(true);
|
||||
// Release clippers and the AABB raycaster.
|
||||
m_its = nullptr;
|
||||
m_c->m_object_clipper.reset();
|
||||
m_c->m_supports_clipper.reset();
|
||||
m_c->m_mesh_raycaster.reset();
|
||||
//m_c->m_mesh_raycaster.reset();
|
||||
}
|
||||
}
|
||||
m_old_state = m_state;
|
||||
|
@ -1127,8 +1077,8 @@ void GLGizmoSlaSupports::on_stop_dragging()
|
|||
|
||||
void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar)
|
||||
{
|
||||
ar(m_clipping_plane_distance,
|
||||
*m_clipping_plane,
|
||||
ar(m_c->m_clipping_plane_distance,
|
||||
*m_c->m_clipping_plane,
|
||||
m_c->m_model_object_id,
|
||||
m_new_point_head_diameter,
|
||||
m_normal_cache,
|
||||
|
@ -1141,8 +1091,8 @@ void GLGizmoSlaSupports::on_load(cereal::BinaryInputArchive& ar)
|
|||
|
||||
void GLGizmoSlaSupports::on_save(cereal::BinaryOutputArchive& ar) const
|
||||
{
|
||||
ar(m_clipping_plane_distance,
|
||||
*m_clipping_plane,
|
||||
ar(m_c->m_clipping_plane_distance,
|
||||
*m_c->m_clipping_plane,
|
||||
m_c->m_model_object_id,
|
||||
m_new_point_head_diameter,
|
||||
m_normal_cache,
|
||||
|
@ -1244,6 +1194,9 @@ void GLGizmoSlaSupports::reload_cache()
|
|||
|
||||
bool GLGizmoSlaSupports::has_backend_supports() const
|
||||
{
|
||||
if (! m_c->m_model_object)
|
||||
return false;
|
||||
|
||||
// find SlaPrintObject with this ID
|
||||
for (const SLAPrintObject* po : m_parent.sla_print()->objects()) {
|
||||
if (po->model_object()->id() == m_c->m_model_object->id())
|
||||
|
@ -1338,12 +1291,12 @@ bool GLGizmoSlaSupports::unsaved_changes() const
|
|||
|
||||
void GLGizmoSlaSupports::update_clipping_plane(bool keep_normal) const
|
||||
{
|
||||
Vec3d normal = (keep_normal && m_clipping_plane->get_normal() != Vec3d::Zero() ?
|
||||
m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward());
|
||||
Vec3d normal = (keep_normal && m_c->m_clipping_plane->get_normal() != Vec3d::Zero() ?
|
||||
m_c->m_clipping_plane->get_normal() : -m_parent.get_camera().get_dir_forward());
|
||||
|
||||
const Vec3d& center = m_c->m_model_object->instances[m_c->m_active_instance]->get_offset() + Vec3d(0., 0., m_z_shift);
|
||||
float dist = normal.dot(center);
|
||||
*m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius));
|
||||
*m_c->m_clipping_plane = ClippingPlane(normal, (dist - (-m_c->m_active_instance_bb_radius) - m_c->m_clipping_plane_distance * 2*m_c->m_active_instance_bb_radius));
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
|
|
|
@ -91,8 +91,6 @@ private:
|
|||
void render_points(const Selection& selection, bool picking = false) const;
|
||||
void render_clipping_plane(const Selection& selection) const;
|
||||
void render_hollowed_mesh() const;
|
||||
bool is_mesh_update_necessary() const;
|
||||
void update_mesh();
|
||||
bool unsaved_changes() const;
|
||||
|
||||
bool m_lock_unique_islands = false;
|
||||
|
@ -105,8 +103,7 @@ private:
|
|||
mutable std::vector<CacheEntry> m_editing_cache; // a support point and whether it is currently selected
|
||||
std::vector<sla::SupportPoint> m_normal_cache; // to restore after discarding changes or undo/redo
|
||||
|
||||
float m_clipping_plane_distance = 0.f;
|
||||
std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
//std::unique_ptr<ClippingPlane> m_clipping_plane;
|
||||
|
||||
// This map holds all translated description texts, so they can be easily referenced during layout calculations
|
||||
// etc. When language changes, GUI is recreated and this class constructed again, so the change takes effect.
|
||||
|
|
|
@ -348,6 +348,9 @@ void GLGizmosManager::set_sla_support_data(ModelObject* model_object)
|
|||
if (!m_enabled || m_gizmos.empty())
|
||||
return;
|
||||
|
||||
// Update common data for hollowing and sla support gizmos.
|
||||
m_common_gizmos_data->update_from_backend(m_parent, model_object);
|
||||
|
||||
dynamic_cast<GLGizmoSlaSupports*>(m_gizmos[SlaSupports].get())->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
dynamic_cast<GLGizmoHollow*>(m_gizmos[Hollow].get())->set_sla_support_data(model_object, m_parent.get_selection());
|
||||
}
|
||||
|
|
|
@ -5133,7 +5133,7 @@ void Plater::reslice_SLA_supports(const ModelObject &object, bool postpone_error
|
|||
|
||||
void Plater::reslice_SLA_hollowing(const ModelObject &object, bool postpone_error_messages)
|
||||
{
|
||||
reslice_SLA_until_step(slaposHollowing, object, postpone_error_messages);
|
||||
reslice_SLA_until_step(slaposDrillHoles, object, postpone_error_messages);
|
||||
}
|
||||
|
||||
void Plater::reslice_SLA_until_step(SLAPrintObjectStep step, const ModelObject &object, bool postpone_error_messages)
|
||||
|
|
Loading…
Reference in a new issue