Cherry-picking 118f4859c472ccbc30b43101c6674dadc81d7b12
And resolve conflicts
This commit is contained in:
parent
ce5d242f76
commit
f100a59688
17
resources/shaders/110/gouraud_light_clip.fs
Normal file
17
resources/shaders/110/gouraud_light_clip.fs
Normal file
@ -0,0 +1,17 @@
|
||||
#version 110
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
uniform float emission_factor;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float clipping_planes_dot;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (clipping_planes_dot < 0.0)
|
||||
discard;
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
|
||||
}
|
54
resources/shaders/110/gouraud_light_clip.vs
Normal file
54
resources/shaders/110/gouraud_light_clip.vs
Normal file
@ -0,0 +1,54 @@
|
||||
#version 110
|
||||
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 20.0
|
||||
|
||||
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
uniform mat4 view_model_matrix;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat3 view_normal_matrix;
|
||||
uniform mat4 volume_world_matrix;
|
||||
|
||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||
uniform vec4 clipping_plane;
|
||||
|
||||
attribute vec3 v_position;
|
||||
attribute vec3 v_normal;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float clipping_planes_dot;
|
||||
|
||||
void main()
|
||||
{
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 eye_normal = normalize(view_normal_matrix * v_normal);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
vec4 eye_position = view_model_matrix * vec4(v_position, 1.0);
|
||||
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
gl_Position = projection_matrix * eye_position;
|
||||
|
||||
// Fill in the scalar for fragment shader clipping. Fragments with this value lower than zero are discarded.
|
||||
clipping_planes_dot = dot(volume_world_matrix * vec4(v_position, 1.0), clipping_plane);
|
||||
}
|
19
resources/shaders/140/gouraud_light_clip.fs
Normal file
19
resources/shaders/140/gouraud_light_clip.fs
Normal file
@ -0,0 +1,19 @@
|
||||
#version 140
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
uniform float emission_factor;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
in vec2 intensity;
|
||||
|
||||
in float clipping_planes_dot;
|
||||
|
||||
out vec4 out_color;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (clipping_planes_dot < 0.0)
|
||||
discard;
|
||||
|
||||
out_color = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
|
||||
}
|
54
resources/shaders/140/gouraud_light_clip.vs
Normal file
54
resources/shaders/140/gouraud_light_clip.vs
Normal file
@ -0,0 +1,54 @@
|
||||
#version 140
|
||||
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 20.0
|
||||
|
||||
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
uniform mat4 view_model_matrix;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat3 view_normal_matrix;
|
||||
uniform mat4 volume_world_matrix;
|
||||
|
||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||
uniform vec4 clipping_plane;
|
||||
|
||||
in vec3 v_position;
|
||||
in vec3 v_normal;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
out vec2 intensity;
|
||||
|
||||
out float clipping_planes_dot;
|
||||
|
||||
void main()
|
||||
{
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 eye_normal = normalize(view_normal_matrix * v_normal);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
vec4 eye_position = view_model_matrix * vec4(v_position, 1.0);
|
||||
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
gl_Position = projection_matrix * eye_position;
|
||||
|
||||
// Fill in the scalar for fragment shader clipping. Fragments with this value lower than zero are discarded.
|
||||
clipping_planes_dot = dot(volume_world_matrix * vec4(v_position, 1.0), clipping_plane);
|
||||
}
|
19
resources/shaders/ES/gouraud_light_clip.fs
Normal file
19
resources/shaders/ES/gouraud_light_clip.fs
Normal file
@ -0,0 +1,19 @@
|
||||
#version 100
|
||||
|
||||
precision highp float;
|
||||
|
||||
uniform vec4 uniform_color;
|
||||
uniform float emission_factor;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float clipping_planes_dot;
|
||||
|
||||
void main()
|
||||
{
|
||||
if (clipping_planes_dot < 0.0)
|
||||
discard;
|
||||
|
||||
gl_FragColor = vec4(vec3(intensity.y) + uniform_color.rgb * (intensity.x + emission_factor), uniform_color.a);
|
||||
}
|
54
resources/shaders/ES/gouraud_light_clip.vs
Normal file
54
resources/shaders/ES/gouraud_light_clip.vs
Normal file
@ -0,0 +1,54 @@
|
||||
#version 100
|
||||
|
||||
#define INTENSITY_CORRECTION 0.6
|
||||
|
||||
// normalized values for (-0.6/1.31, 0.6/1.31, 1./1.31)
|
||||
const vec3 LIGHT_TOP_DIR = vec3(-0.4574957, 0.4574957, 0.7624929);
|
||||
#define LIGHT_TOP_DIFFUSE (0.8 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SPECULAR (0.125 * INTENSITY_CORRECTION)
|
||||
#define LIGHT_TOP_SHININESS 20.0
|
||||
|
||||
// normalized values for (1./1.43, 0.2/1.43, 1./1.43)
|
||||
const vec3 LIGHT_FRONT_DIR = vec3(0.6985074, 0.1397015, 0.6985074);
|
||||
#define LIGHT_FRONT_DIFFUSE (0.3 * INTENSITY_CORRECTION)
|
||||
|
||||
#define INTENSITY_AMBIENT 0.3
|
||||
|
||||
uniform mat4 view_model_matrix;
|
||||
uniform mat4 projection_matrix;
|
||||
uniform mat3 view_normal_matrix;
|
||||
uniform mat4 volume_world_matrix;
|
||||
|
||||
// Clipping plane - general orientation. Used by the SLA gizmo.
|
||||
uniform vec4 clipping_plane;
|
||||
|
||||
attribute vec3 v_position;
|
||||
attribute vec3 v_normal;
|
||||
|
||||
// x = tainted, y = specular;
|
||||
varying vec2 intensity;
|
||||
|
||||
varying float clipping_planes_dot;
|
||||
|
||||
void main()
|
||||
{
|
||||
// First transform the normal into camera space and normalize the result.
|
||||
vec3 eye_normal = normalize(view_normal_matrix * v_normal);
|
||||
|
||||
// Compute the cos of the angle between the normal and lights direction. The light is directional so the direction is constant for every vertex.
|
||||
// Since these two are normalized the cosine is the dot product. We also need to clamp the result to the [0,1] range.
|
||||
float NdotL = max(dot(eye_normal, LIGHT_TOP_DIR), 0.0);
|
||||
|
||||
intensity.x = INTENSITY_AMBIENT + NdotL * LIGHT_TOP_DIFFUSE;
|
||||
vec4 eye_position = view_model_matrix * vec4(v_position, 1.0);
|
||||
intensity.y = LIGHT_TOP_SPECULAR * pow(max(dot(-normalize(eye_position.xyz), reflect(-LIGHT_TOP_DIR, eye_normal)), 0.0), LIGHT_TOP_SHININESS);
|
||||
|
||||
// Perform the same lighting calculation for the 2nd light source (no specular applied).
|
||||
NdotL = max(dot(eye_normal, LIGHT_FRONT_DIR), 0.0);
|
||||
intensity.x += NdotL * LIGHT_FRONT_DIFFUSE;
|
||||
|
||||
gl_Position = projection_matrix * eye_position;
|
||||
|
||||
// Fill in the scalar for fragment shader clipping. Fragments with this value lower than zero are discarded.
|
||||
clipping_planes_dot = dot(volume_world_matrix * vec4(v_position, 1.0), clipping_plane);
|
||||
}
|
@ -476,6 +476,11 @@ public:
|
||||
const PrintObjects& objects() const { return m_objects; }
|
||||
// PrintObject by its ObjectID, to be used to uniquely bind slicing warnings to their source PrintObjects
|
||||
// in the notification center.
|
||||
const SLAPrintObject* get_print_object_by_model_object_id(ObjectID object_id) const {
|
||||
auto it = std::find_if(m_objects.begin(), m_objects.end(),
|
||||
[object_id](const SLAPrintObject* obj) { return obj->model_object()->id() == object_id; });
|
||||
return (it == m_objects.end()) ? nullptr : *it;
|
||||
}
|
||||
const SLAPrintObject* get_object(ObjectID object_id) const {
|
||||
auto it = std::find_if(m_objects.begin(), m_objects.end(),
|
||||
[object_id](const SLAPrintObject *obj) { return obj->id() == object_id; });
|
||||
|
@ -852,74 +852,6 @@ int GLVolumeCollection::load_object_volume(
|
||||
return int(this->volumes.size() - 1);
|
||||
}
|
||||
|
||||
//// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
//// This function produces volumes for multiple instances in a single shot,
|
||||
//// as some object specific mesh conversions may be expensive.
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//void GLVolumeCollection::load_object_auxiliary(
|
||||
// const SLAPrintObject* print_object,
|
||||
// int obj_idx,
|
||||
// // pairs of <instance_idx, print_instance_idx>
|
||||
// const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
// SLAPrintObjectStep milestone,
|
||||
// // Timestamp of the last change of the milestone
|
||||
// size_t timestamp)
|
||||
//#else
|
||||
//void GLVolumeCollection::load_object_auxiliary(
|
||||
// const SLAPrintObject *print_object,
|
||||
// int obj_idx,
|
||||
// // pairs of <instance_idx, print_instance_idx>
|
||||
// const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
// SLAPrintObjectStep milestone,
|
||||
// // Timestamp of the last change of the milestone
|
||||
// size_t timestamp,
|
||||
// bool opengl_initialized)
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//{
|
||||
// assert(print_object->is_step_done(milestone));
|
||||
// Transform3d mesh_trafo_inv = print_object->trafo().inverse();
|
||||
// // Get the support mesh.
|
||||
// TriangleMesh mesh = print_object->get_mesh(milestone);
|
||||
// mesh.transform(mesh_trafo_inv);
|
||||
// // Convex hull is required for out of print bed detection.
|
||||
// TriangleMesh convex_hull = mesh.convex_hull_3d();
|
||||
// for (const std::pair<size_t, size_t>& instance_idx : instances) {
|
||||
// const ModelInstance& model_instance = *print_object->model_object()->instances[instance_idx.first];
|
||||
// this->volumes.emplace_back(new GLVolume((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
|
||||
// GLVolume& v = *this->volumes.back();
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#if ENABLE_SMOOTH_NORMALS
|
||||
// v.model.init_from(mesh, true);
|
||||
//#else
|
||||
// v.model.init_from(mesh);
|
||||
// v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
|
||||
//#if ENABLE_RAYCAST_PICKING
|
||||
// v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
|
||||
//#endif // ENABLE_RAYCAST_PICKING
|
||||
//#endif // ENABLE_SMOOTH_NORMALS
|
||||
//#else
|
||||
//#if ENABLE_SMOOTH_NORMALS
|
||||
// v.indexed_vertex_array.load_mesh(mesh, true);
|
||||
//#else
|
||||
// v.indexed_vertex_array.load_mesh(mesh);
|
||||
//#endif // ENABLE_SMOOTH_NORMALS
|
||||
// v.indexed_vertex_array.finalize_geometry(opengl_initialized);
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
|
||||
// v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
|
||||
// // Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.
|
||||
// if (&instance_idx == &instances.back())
|
||||
// v.set_convex_hull(std::move(convex_hull));
|
||||
// else
|
||||
// v.set_convex_hull(convex_hull);
|
||||
// v.is_modifier = false;
|
||||
// v.shader_outside_printer_detection_enabled = (milestone == slaposSupportTree);
|
||||
// v.set_instance_transformation(model_instance.get_transformation());
|
||||
// // Leave the volume transformation at identity.
|
||||
// // v.set_volume_transformation(model_volume->get_transformation());
|
||||
// }
|
||||
//}
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
#if ENABLE_OPENGL_ES
|
||||
int GLVolumeCollection::load_wipe_tower_preview(
|
||||
|
@ -658,16 +658,6 @@ public:
|
||||
int volume_idx,
|
||||
int instance_idx);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
// void load_object_auxiliary(
|
||||
// const SLAPrintObject* print_object,
|
||||
// int obj_idx,
|
||||
// // pairs of <instance_idx, print_instance_idx>
|
||||
// const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
// SLAPrintObjectStep milestone,
|
||||
// // Timestamp of the last change of the milestone
|
||||
// size_t timestamp);
|
||||
|
||||
#if ENABLE_OPENGL_ES
|
||||
int load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, TriangleMesh* out_mesh = nullptr);
|
||||
@ -689,17 +679,6 @@ public:
|
||||
int instance_idx,
|
||||
bool opengl_initialized);
|
||||
|
||||
// Load SLA auxiliary GLVolumes (for support trees or pad).
|
||||
void load_object_auxiliary(
|
||||
const SLAPrintObject *print_object,
|
||||
int obj_idx,
|
||||
// pairs of <instance_idx, print_instance_idx>
|
||||
const std::vector<std::pair<size_t, size_t>>& instances,
|
||||
SLAPrintObjectStep milestone,
|
||||
// Timestamp of the last change of the milestone
|
||||
size_t timestamp,
|
||||
bool opengl_initialized);
|
||||
|
||||
int load_wipe_tower_preview(
|
||||
float pos_x, float pos_y, float width, float depth, float height, float rotation_angle, bool size_unknown, float brim_width, bool opengl_initialized);
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
@ -2011,15 +2011,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
size_t volume_idx;
|
||||
};
|
||||
|
||||
// // SLA steps to pull the preview meshes for.
|
||||
// typedef std::array<SLAPrintObjectStep, 3> SLASteps;
|
||||
// SLASteps sla_steps = { slaposDrillHoles, slaposSupportTree, slaposPad };
|
||||
// struct SLASupportState {
|
||||
// std::array<PrintStateBase::StateWithTimeStamp, std::tuple_size<SLASteps>::value> step;
|
||||
// };
|
||||
// // State of the sla_steps for all SLAPrintObjects.
|
||||
// std::vector<SLASupportState> sla_support_state;
|
||||
|
||||
std::vector<size_t> instance_ids_selected;
|
||||
std::vector<size_t> map_glvolume_old_to_new(m_volumes.volumes.size(), size_t(-1));
|
||||
std::vector<GLVolumeState> deleted_volumes;
|
||||
@ -2044,33 +2035,7 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
}
|
||||
}
|
||||
}
|
||||
// if (printer_technology == ptSLA) {
|
||||
// const SLAPrint* sla_print = this->sla_print();
|
||||
//#ifndef NDEBUG
|
||||
// // Verify that the SLAPrint object is synchronized with m_model.
|
||||
// check_model_ids_equal(*m_model, sla_print->model());
|
||||
//#endif /* NDEBUG */
|
||||
// sla_support_state.reserve(sla_print->objects().size());
|
||||
// for (const SLAPrintObject* print_object : sla_print->objects()) {
|
||||
// SLASupportState state;
|
||||
// for (size_t istep = 0; istep < sla_steps.size(); ++istep) {
|
||||
// state.step[istep] = print_object->step_state_with_timestamp(sla_steps[istep]);
|
||||
// if (state.step[istep].state == PrintStateBase::DONE) {
|
||||
// if (!print_object->has_mesh(sla_steps[istep]))
|
||||
// // Consider the DONE step without a valid mesh as invalid for the purpose
|
||||
// // of mesh visualization.
|
||||
// state.step[istep].state = PrintStateBase::INVALID;
|
||||
// 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.
|
||||
// if (model_instance->is_printable())
|
||||
// aux_volume_state.emplace_back(state.step[istep].timestamp, model_instance->id());
|
||||
// }
|
||||
// }
|
||||
// sla_support_state.emplace_back(state);
|
||||
// }
|
||||
// }
|
||||
|
||||
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. Find the GLVolume of a hollowed mesh.
|
||||
@ -2190,139 +2155,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
|
||||
}
|
||||
|
||||
if (printer_technology == ptSLA) {
|
||||
// size_t idx = 0;
|
||||
// const SLAPrint *sla_print = this->sla_print();
|
||||
// std::vector<double> shift_zs(m_model->objects.size(), 0);
|
||||
// double relative_correction_z = sla_print->relative_correction().z();
|
||||
// if (relative_correction_z <= EPSILON)
|
||||
// relative_correction_z = 1.;
|
||||
// for (const SLAPrintObject *print_object : sla_print->objects()) {
|
||||
// SLASupportState &state = sla_support_state[idx ++];
|
||||
// const ModelObject *model_object = print_object->model_object();
|
||||
// // Find an index of the ModelObject
|
||||
// int object_idx;
|
||||
// // 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);
|
||||
// assert(it != sla_print->model().objects.end());
|
||||
// object_idx = it - sla_print->model().objects.begin();
|
||||
// // Cache the Z offset to be applied to all volumes with this object_idx.
|
||||
// shift_zs[object_idx] = print_object->get_current_elevation() / relative_correction_z;
|
||||
// // Collect indices of this print_object's instances, for which the SLA support meshes are to be added to the scene.
|
||||
// // pairs of <instance_idx, print_instance_idx>
|
||||
// std::vector<std::pair<size_t, size_t>> instances[std::tuple_size<SLASteps>::value];
|
||||
// for (size_t print_instance_idx = 0; print_instance_idx < print_object->instances().size(); ++ print_instance_idx) {
|
||||
// const SLAPrintObject::Instance &instance = print_object->instances()[print_instance_idx];
|
||||
// // Find index of ModelInstance corresponding to this SLAPrintObject::Instance.
|
||||
// auto it = std::find_if(model_object->instances.begin(), model_object->instances.end(),
|
||||
// [&instance](const ModelInstance *mi) { return mi->id() == instance.instance_id; });
|
||||
// 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 (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.
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// volume.model.reset();
|
||||
//#else
|
||||
// volume.indexed_vertex_array.release_geometry();
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// if (state.step[istep].state == PrintStateBase::DONE) {
|
||||
// TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
|
||||
// assert(! mesh.empty());
|
||||
|
||||
// // sla_trafo does not contain volume trafo. To get a mesh to create
|
||||
// // a new volume from, we have to apply vol trafo inverse separately.
|
||||
// const ModelObject& mo = *m_model->objects[volume.object_idx()];
|
||||
// Transform3d trafo = sla_print->sla_trafo(mo)
|
||||
// * mo.volumes.front()->get_transformation().get_matrix();
|
||||
// mesh.transform(trafo.inverse());
|
||||
//#if ENABLE_SMOOTH_NORMALS
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// volume.model.init_from(mesh, true);
|
||||
//#else
|
||||
// volume.indexed_vertex_array.load_mesh(mesh, true);
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#else
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// volume.model.init_from(mesh);
|
||||
//#if ENABLE_RAYCAST_PICKING
|
||||
// volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
|
||||
//#endif // ENABLE_RAYCAST_PICKING
|
||||
//#else
|
||||
// volume.indexed_vertex_array.load_mesh(mesh);
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#endif // ENABLE_SMOOTH_NORMALS
|
||||
// }
|
||||
// else {
|
||||
// // Reload the original volume.
|
||||
//#if ENABLE_SMOOTH_NORMALS
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
|
||||
//#else
|
||||
// volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#else
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#if ENABLE_RAYCAST_PICKING
|
||||
// const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
|
||||
// volume.model.init_from(new_mesh);
|
||||
// volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
|
||||
//#else
|
||||
// volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||
//#endif // ENABLE_RAYCAST_PICKING
|
||||
//#else
|
||||
// volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
//#endif // ENABLE_SMOOTH_NORMALS
|
||||
// }
|
||||
//#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// volume.finalize_geometry(true);
|
||||
//#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// }
|
||||
// //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());
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// for (size_t istep = 0; istep < sla_steps.size(); ++istep)
|
||||
// if (!instances[istep].empty())
|
||||
//#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp);
|
||||
//#else
|
||||
// m_volumes.load_object_auxiliary(print_object, object_idx, instances[istep], sla_steps[istep], state.step[istep].timestamp, m_initialized);
|
||||
//#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// }
|
||||
|
||||
// Shift-up all volumes of the object so that it has the right elevation with respect to the print bed
|
||||
for (GLVolume* volume : m_volumes.volumes)
|
||||
if (volume->object_idx() < (int)m_model->objects.size() && m_model->objects[volume->object_idx()]->instances[volume->instance_idx()]->is_printable()) {
|
||||
@ -7638,25 +7470,24 @@ void GLCanvas3D::_load_sla_shells()
|
||||
};
|
||||
|
||||
// adds objects' volumes
|
||||
for (const SLAPrintObject* obj : print->objects())
|
||||
/*if (obj->is_step_done(slaposSliceSupports))*/ {
|
||||
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);
|
||||
// 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();
|
||||
if (auto &tree_mesh = obj->support_mesh(); !tree_mesh.empty())
|
||||
add_volume(*obj, -int(slaposSupportTree), instance, tree_mesh, GLVolume::SLA_SUPPORT_COLOR, true);
|
||||
if (auto &pad_mesh = obj->pad_mesh(); !pad_mesh.empty())
|
||||
add_volume(*obj, -int(slaposPad), instance, pad_mesh, GLVolume::SLA_PAD_COLOR, false);
|
||||
}
|
||||
double shift_z = obj->get_current_elevation();
|
||||
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
|
||||
// apply shift z
|
||||
m_volumes.volumes[i]->set_sla_shift_z(shift_z);
|
||||
}
|
||||
for (const SLAPrintObject* obj : print->objects()) {
|
||||
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);
|
||||
// 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();
|
||||
if (auto &tree_mesh = obj->support_mesh(); !tree_mesh.empty())
|
||||
add_volume(*obj, -int(slaposSupportTree), instance, tree_mesh, GLVolume::SLA_SUPPORT_COLOR, true);
|
||||
if (auto &pad_mesh = obj->pad_mesh(); !pad_mesh.empty())
|
||||
add_volume(*obj, -int(slaposPad), instance, pad_mesh, GLVolume::SLA_PAD_COLOR, false);
|
||||
}
|
||||
double shift_z = obj->get_current_elevation();
|
||||
for (unsigned int i = initial_volumes_count; i < m_volumes.volumes.size(); ++ i) {
|
||||
// apply shift z
|
||||
m_volumes.volumes[i]->set_sla_shift_z(shift_z);
|
||||
}
|
||||
}
|
||||
|
||||
update_volumes_colors_by_extruder();
|
||||
}
|
||||
|
@ -688,8 +688,6 @@ public:
|
||||
void set_raycaster_gizmos_on_top(bool value) {
|
||||
m_scene_raycaster.set_gizmos_on_top(value);
|
||||
}
|
||||
|
||||
const SceneRaycaster & raycaster() const { return m_scene_raycaster; }
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void set_as_dirty();
|
||||
|
@ -72,6 +72,8 @@ std::pair<bool, std::string> GLShadersManager::init()
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
// used to render bed axes and model, selection hints, gcode sequential view marker model, preview shells, options in gcode preview
|
||||
valid &= append_shader("gouraud_light", { prefix + "gouraud_light.vs", prefix + "gouraud_light.fs" });
|
||||
// extend "gouraud_light" by adding clipping, used in sla gizmos
|
||||
valid &= append_shader("gouraud_light_clip", { prefix + "gouraud_light_clip.vs", prefix + "gouraud_light_clip.fs" });
|
||||
// used to render printbed
|
||||
valid &= append_shader("printbed", { prefix + "printbed.vs", prefix + "printbed.fs" });
|
||||
#else
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "slic3r/GUI/GUI_ObjectList.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/SLAPrint.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
@ -53,14 +54,21 @@ void GLGizmoHollow::data_changed()
|
||||
reload_cache();
|
||||
m_old_mo_id = mo->id();
|
||||
}
|
||||
// if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
|
||||
// m_holes_in_drilled_mesh = mo->sla_drain_holes;
|
||||
|
||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||
if (po != nullptr && po->get_mesh_to_print().empty())
|
||||
process_mesh(slaposAssembly);
|
||||
|
||||
update_volumes();
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_raycasters.empty())
|
||||
on_register_raycasters_for_picking();
|
||||
if (m_hole_raycasters.empty())
|
||||
register_hole_raycasters_for_picking();
|
||||
else
|
||||
update_raycasters_for_picking_transform();
|
||||
update_hole_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_c->instances_hider()->set_hide_full_scene(true);
|
||||
}
|
||||
}
|
||||
|
||||
@ -87,16 +95,15 @@ void GLGizmoHollow::on_render()
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
if (selection.is_from_single_instance())
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
render_points(selection);
|
||||
render_volumes();
|
||||
render_points(selection);
|
||||
#else
|
||||
render_points(selection, false);
|
||||
render_points(selection, false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_selection_rectangle.render(m_parent);
|
||||
m_c->object_clipper()->render_cut();
|
||||
m_c->supports_clipper()->render_cut();
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
@ -104,27 +111,14 @@ void GLGizmoHollow::on_render()
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoHollow::on_register_raycasters_for_picking()
|
||||
{
|
||||
assert(m_raycasters.empty());
|
||||
|
||||
init_cylinder_model();
|
||||
|
||||
set_sla_auxiliary_volumes_picking_state(false);
|
||||
|
||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||
if (info != nullptr && !info->model_object()->sla_drain_holes.empty()) {
|
||||
const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes;
|
||||
for (int i = 0; i < (int)drain_holes.size(); ++i) {
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cylinder.mesh_raycaster));
|
||||
}
|
||||
update_raycasters_for_picking_transform();
|
||||
}
|
||||
register_hole_raycasters_for_picking();
|
||||
register_volume_raycasters_for_picking();
|
||||
}
|
||||
|
||||
void GLGizmoHollow::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
|
||||
m_raycasters.clear();
|
||||
set_sla_auxiliary_volumes_picking_state(true);
|
||||
unregister_hole_raycasters_for_picking();
|
||||
unregister_volume_raycasters_for_picking();
|
||||
}
|
||||
#else
|
||||
void GLGizmoHollow::on_render_for_picking()
|
||||
@ -190,7 +184,7 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const bool clipped = is_mesh_point_clipped(drain_hole.pos.cast<double>());
|
||||
m_raycasters[i]->set_active(!clipped);
|
||||
m_hole_raycasters[i]->set_active(!clipped);
|
||||
if (clipped)
|
||||
continue;
|
||||
#else
|
||||
@ -270,6 +264,25 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
void GLGizmoHollow::render_volumes()
|
||||
{
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_clip");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.0f);
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
|
||||
ClippingPlane clipping_plane = (m_c->object_clipper()->get_position() == 0.0) ? ClippingPlane::ClipsNothing() : *m_c->object_clipper()->get_clipping_plane();
|
||||
clipping_plane.set_normal(-clipping_plane.get_normal());
|
||||
m_volumes.set_clipping_plane(clipping_plane.get_data());
|
||||
|
||||
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
||||
shader->stop_using();
|
||||
|
||||
}
|
||||
|
||||
bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
||||
{
|
||||
if (m_c->object_clipper()->get_position() == 0.)
|
||||
@ -291,48 +304,26 @@ bool GLGizmoHollow::is_mesh_point_clipped(const Vec3d& point) const
|
||||
// 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 (m_c->raycaster()->raycasters().size() != 1)
|
||||
return false;
|
||||
if (! m_c->raycaster()->raycaster())
|
||||
return false;
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_first_volume();
|
||||
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
||||
|
||||
double clp_dist = m_c->object_clipper()->get_position();
|
||||
const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane();
|
||||
|
||||
// The raycaster query
|
||||
Vec3f hit;
|
||||
Vec3f normal;
|
||||
if (m_c->raycaster()->raycaster()->unproject_on_mesh(
|
||||
mouse_pos,
|
||||
trafo.get_matrix(),
|
||||
camera,
|
||||
m_volumes.volumes.front()->world_matrix(),
|
||||
wxGetApp().plater()->get_camera(),
|
||||
hit,
|
||||
normal,
|
||||
clp_dist != 0. ? clp : nullptr))
|
||||
{
|
||||
// if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh()) {
|
||||
// // in this case the raycaster sees the hollowed and drilled mesh.
|
||||
// // if the point lies on the surface created by the hole, we want
|
||||
// // to ignore it.
|
||||
// for (const sla::DrainHole& hole : m_holes_in_drilled_mesh) {
|
||||
// sla::DrainHole outer(hole);
|
||||
// outer.radius *= 1.001f;
|
||||
// outer.height *= 1.001f;
|
||||
// if (outer.is_inside(hit))
|
||||
// return false;
|
||||
// }
|
||||
// }
|
||||
|
||||
m_c->object_clipper()->get_position() != 0.0 ? m_c->object_clipper()->get_clipping_plane() : nullptr)) {
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Following function is called from GLCanvas3D to inform the gizmo about a mouse/keyboard event.
|
||||
@ -348,9 +339,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
||||
// left down with shift - show the selection rectangle:
|
||||
if (action == SLAGizmoEventType::LeftDown && (shift_down || alt_down || control_down)) {
|
||||
if (m_hover_id == -1) {
|
||||
if (shift_down || alt_down) {
|
||||
if (shift_down || alt_down)
|
||||
m_selection_rectangle.start_dragging(mouse_position, shift_down ? GLSelectionRectangle::EState::Select : GLSelectionRectangle::EState::Deselect);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_selected[m_hover_id])
|
||||
@ -383,8 +373,8 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
|
||||
m_parent.set_as_dirty();
|
||||
m_wait_for_up_event = true;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
unregister_hole_raycasters_for_picking();
|
||||
register_hole_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
else
|
||||
@ -510,8 +500,8 @@ void GLGizmoHollow::delete_selected_points()
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
unregister_hole_raycasters_for_picking();
|
||||
register_hole_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
select_point(NoPoints);
|
||||
}
|
||||
@ -580,39 +570,61 @@ bool GLGizmoHollow::on_mouse(const wxMouseEvent &mouse_event)
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
|
||||
void GLGizmoHollow::process_mesh(SLAPrintObjectStep step, bool postpone_error_messages)
|
||||
{
|
||||
wxGetApp().CallAfter([this, postpone_error_messages]() {
|
||||
wxGetApp().plater()->reslice_SLA_hollowing(
|
||||
*m_c->selection_info()->model_object(), postpone_error_messages);
|
||||
});
|
||||
wxGetApp().CallAfter([this, step, postpone_error_messages]() {
|
||||
wxGetApp().plater()->reslice_SLA_until_step(step, *m_c->selection_info()->model_object(), postpone_error_messages);
|
||||
});
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoHollow::set_sla_auxiliary_volumes_picking_state(bool state)
|
||||
void GLGizmoHollow::register_hole_raycasters_for_picking()
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||
if (raycasters != nullptr) {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList ids = selection.get_volume_idxs();
|
||||
for (unsigned int id : ids) {
|
||||
const GLVolume* v = selection.get_volume(id);
|
||||
if (v->is_sla_pad() || v->is_sla_support()) {
|
||||
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
||||
if (it != raycasters->end())
|
||||
(*it)->set_active(state);
|
||||
}
|
||||
assert(m_hole_raycasters.empty());
|
||||
|
||||
init_cylinder_model();
|
||||
|
||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||
if (info != nullptr && !info->model_object()->sla_drain_holes.empty()) {
|
||||
const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes;
|
||||
for (int i = 0; i < (int)drain_holes.size(); ++i) {
|
||||
m_hole_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cylinder.mesh_raycaster, Transform3d::Identity()));
|
||||
}
|
||||
update_hole_raycasters_for_picking_transform();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoHollow::update_raycasters_for_picking_transform()
|
||||
void GLGizmoHollow::unregister_hole_raycasters_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_hole_raycasters.size(); ++i) {
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, i);
|
||||
}
|
||||
m_hole_raycasters.clear();
|
||||
}
|
||||
|
||||
void GLGizmoHollow::register_volume_raycasters_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
||||
const GLVolume* v = m_volumes.volumes[i];
|
||||
m_volume_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i, *v->mesh_raycaster, v->world_matrix()));
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoHollow::unregister_volume_raycasters_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_volume_raycasters.size(); ++i) {
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i);
|
||||
}
|
||||
m_volume_raycasters.clear();
|
||||
}
|
||||
|
||||
void GLGizmoHollow::update_hole_raycasters_for_picking_transform()
|
||||
{
|
||||
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
|
||||
if (info != nullptr) {
|
||||
const sla::DrainHoles& drain_holes = info->model_object()->sla_drain_holes;
|
||||
if (!drain_holes.empty()) {
|
||||
assert(!m_raycasters.empty());
|
||||
assert(!m_hole_raycasters.empty());
|
||||
|
||||
const GLVolume* vol = m_parent.get_selection().get_first_volume();
|
||||
const Transform3d instance_scaling_matrix_inverse = vol->get_instance_transformation().get_scaling_factor_matrix().inverse();
|
||||
@ -625,13 +637,62 @@ void GLGizmoHollow::update_raycasters_for_picking_transform()
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
const Transform3d matrix = vol->world_matrix() * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
m_raycasters[i]->set_transform(matrix);
|
||||
m_hole_raycasters[i]->set_transform(matrix);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmoHollow::update_volumes()
|
||||
{
|
||||
m_volumes.clear();
|
||||
unregister_volume_raycasters_for_picking();
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
if (mo == nullptr)
|
||||
return;
|
||||
|
||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||
if (po == nullptr)
|
||||
return;
|
||||
|
||||
TriangleMesh backend_mesh = po->get_mesh_to_print();
|
||||
if (!backend_mesh.empty()) {
|
||||
// The backend has generated a valid mesh. Use it
|
||||
backend_mesh.transform(po->trafo().inverse());
|
||||
m_volumes.volumes.emplace_back(new GLVolume());
|
||||
GLVolume* new_volume = m_volumes.volumes.back();
|
||||
new_volume->model.init_from(backend_mesh);
|
||||
new_volume->set_instance_transformation(po->model_object()->instances[m_parent.get_selection().get_instance_idx()]->get_transformation());
|
||||
new_volume->set_sla_shift_z(po->get_current_elevation());
|
||||
new_volume->selected = true; // to set the proper color
|
||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(backend_mesh);
|
||||
}
|
||||
|
||||
if (m_volumes.volumes.empty()) {
|
||||
// No valid mesh found in the backend. Use the selection to duplicate the volumes
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
for (unsigned int idx : idxs) {
|
||||
const GLVolume* v = selection.get_volume(idx);
|
||||
if (!v->is_modifier) {
|
||||
m_volumes.volumes.emplace_back(new GLVolume());
|
||||
GLVolume* new_volume = m_volumes.volumes.back();
|
||||
const TriangleMesh& mesh = mo->volumes[v->volume_idx()]->mesh();
|
||||
new_volume->model.init_from(mesh);
|
||||
new_volume->set_instance_transformation(v->get_instance_transformation());
|
||||
new_volume->set_volume_transformation(v->get_volume_transformation());
|
||||
new_volume->set_sla_shift_z(v->get_sla_shift_z());
|
||||
new_volume->selected = true; // to set the proper color
|
||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register_volume_raycasters_for_picking();
|
||||
}
|
||||
|
||||
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>>
|
||||
GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const
|
||||
{
|
||||
@ -724,8 +785,8 @@ RENDER_AGAIN:
|
||||
window_width = std::max(window_width, button_preview_width);
|
||||
|
||||
if (m_imgui->button(m_desc["preview"]))
|
||||
hollow_mesh();
|
||||
|
||||
process_mesh(slaposDrillHoles);
|
||||
|
||||
bool config_changed = false;
|
||||
|
||||
ImGui::Separator();
|
||||
@ -896,13 +957,6 @@ RENDER_AGAIN:
|
||||
if (m_imgui->slider_float("##clp_dist", &clp_dist, 0.f, 1.f, "%.2f"))
|
||||
m_c->object_clipper()->set_position_by_ratio(clp_dist, true);
|
||||
|
||||
// make sure supports are shown/hidden as appropriate
|
||||
bool show_sups = m_c->instances_hider()->are_supports_shown();
|
||||
if (m_imgui->checkbox(m_desc["show_supports"], show_sups)) {
|
||||
m_c->instances_hider()->show_supports(show_sups);
|
||||
force_refresh = true;
|
||||
}
|
||||
|
||||
m_imgui->end();
|
||||
|
||||
|
||||
@ -935,7 +989,7 @@ bool GLGizmoHollow::on_is_activable() const
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|
||||
|| !selection.is_from_single_instance())
|
||||
|| !selection.is_single_full_instance())
|
||||
return false;
|
||||
|
||||
// Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside.
|
||||
@ -964,9 +1018,7 @@ CommonGizmosDataID GLGizmoHollow::on_get_requirements() const
|
||||
int(CommonGizmosDataID::SelectionInfo)
|
||||
| int(CommonGizmosDataID::InstancesHider)
|
||||
| int(CommonGizmosDataID::Raycaster)
|
||||
| int(CommonGizmosDataID::HollowedMesh)
|
||||
| int(CommonGizmosDataID::ObjectClipper)
|
||||
| int(CommonGizmosDataID::SupportsClipper));
|
||||
| int(CommonGizmosDataID::ObjectClipper));
|
||||
}
|
||||
|
||||
|
||||
@ -975,8 +1027,12 @@ void GLGizmoHollow::on_set_state()
|
||||
if (m_state == m_old_state)
|
||||
return;
|
||||
|
||||
if (m_state == Off && m_old_state != Off) // the gizmo was just turned Off
|
||||
if (m_state == Off && m_old_state != Off) {
|
||||
// the gizmo was just turned Off
|
||||
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_FORCE_UPDATE));
|
||||
m_c->instances_hider()->set_hide_full_scene(false);
|
||||
}
|
||||
|
||||
m_old_state = m_state;
|
||||
}
|
||||
|
||||
@ -1091,6 +1147,9 @@ void GLGizmoHollow::reload_cache()
|
||||
|
||||
void GLGizmoHollow::on_set_hover_id()
|
||||
{
|
||||
if (m_c->selection_info()->model_object() == nullptr)
|
||||
return;
|
||||
|
||||
if (int(m_c->selection_info()->model_object()->sla_drain_holes.size()) <= m_hover_id)
|
||||
m_hover_id = -1;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
#include <libslic3r/SLA/Hollowing.hpp>
|
||||
#include <libslic3r/ObjectID.hpp>
|
||||
@ -25,7 +26,6 @@ class GLGizmoHollow : public GLGizmoBase
|
||||
private:
|
||||
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
||||
|
||||
|
||||
public:
|
||||
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
void data_changed() override;
|
||||
@ -59,21 +59,29 @@ private:
|
||||
#else
|
||||
void render_points(const Selection& selection, bool picking = false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void hollow_mesh(bool postpone_error_messages = false);
|
||||
void render_volumes();
|
||||
void process_mesh(SLAPrintObjectStep step, bool postpone_error_messages = false);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void set_sla_auxiliary_volumes_picking_state(bool state);
|
||||
void update_raycasters_for_picking_transform();
|
||||
void register_hole_raycasters_for_picking();
|
||||
void unregister_hole_raycasters_for_picking();
|
||||
void register_volume_raycasters_for_picking();
|
||||
void unregister_volume_raycasters_for_picking();
|
||||
void update_hole_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void update_volumes();
|
||||
|
||||
ObjectID m_old_mo_id = -1;
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel m_cylinder;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_raycasters;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_hole_raycasters;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volume_raycasters;
|
||||
#else
|
||||
GLModel m_cylinder;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
GLVolumeCollection m_volumes;
|
||||
|
||||
float m_new_hole_radius = 2.f; // Size of a new hole.
|
||||
float m_new_hole_height = 6.f;
|
||||
mutable std::vector<bool> m_selected; // which holes are currently selected
|
||||
|
@ -60,6 +60,16 @@ bool GLGizmoSlaSupports::on_init()
|
||||
return true;
|
||||
}
|
||||
|
||||
static int last_completed_step(const SLAPrint& sla)
|
||||
{
|
||||
int step = -1;
|
||||
for (int i = 0; i < (int)SLAPrintObjectStep::slaposCount; ++i) {
|
||||
if (sla.is_step_done((SLAPrintObjectStep)i))
|
||||
++step;
|
||||
}
|
||||
return step;
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::data_changed()
|
||||
{
|
||||
if (! m_c->selection_info())
|
||||
@ -71,19 +81,25 @@ void GLGizmoSlaSupports::data_changed()
|
||||
disable_editing_mode();
|
||||
reload_cache();
|
||||
m_old_mo_id = mo->id();
|
||||
m_c->instances_hider()->show_supports(true);
|
||||
}
|
||||
|
||||
// If we triggered autogeneration before, check backend and fetch results if they are there
|
||||
if (mo) {
|
||||
m_c->instances_hider()->set_hide_full_scene(true);
|
||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||
if (po != nullptr && last_completed_step(*po->print()) < (int)slaposDrillHoles)
|
||||
process_mesh(slaposDrillHoles, false);
|
||||
|
||||
update_volumes();
|
||||
|
||||
if (mo->sla_points_status == sla::PointsStatus::Generating)
|
||||
get_data_from_backend();
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (m_raycasters.empty())
|
||||
on_register_raycasters_for_picking();
|
||||
if (m_point_raycasters.empty())
|
||||
register_point_raycasters_for_picking();
|
||||
else
|
||||
update_raycasters_for_picking_transform();
|
||||
update_point_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
|
||||
@ -111,8 +127,6 @@ void GLGizmoSlaSupports::on_render()
|
||||
if (!m_sphere.is_initialized())
|
||||
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0));
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
if (!m_cylinder.is_initialized())
|
||||
m_cylinder.init_from(its_make_cylinder(1.0, 1.0, double(PI) / 12.0));
|
||||
|
||||
ModelObject* mo = m_c->selection_info()->model_object();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
@ -128,16 +142,15 @@ void GLGizmoSlaSupports::on_render()
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
|
||||
if (selection.is_from_single_instance())
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
render_points(selection);
|
||||
render_volumes();
|
||||
render_points(selection);
|
||||
#else
|
||||
render_points(selection, false);
|
||||
render_points(selection, false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_selection_rectangle.render(m_parent);
|
||||
m_c->object_clipper()->render_cut();
|
||||
m_c->supports_clipper()->render_cut();
|
||||
|
||||
glsafe(::glDisable(GL_BLEND));
|
||||
}
|
||||
@ -145,23 +158,14 @@ void GLGizmoSlaSupports::on_render()
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoSlaSupports::on_register_raycasters_for_picking()
|
||||
{
|
||||
assert(m_raycasters.empty());
|
||||
set_sla_auxiliary_volumes_picking_state(false);
|
||||
|
||||
if (m_editing_mode && !m_editing_cache.empty()) {
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_sphere.mesh_raycaster),
|
||||
m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cone.mesh_raycaster));
|
||||
}
|
||||
update_raycasters_for_picking_transform();
|
||||
}
|
||||
register_point_raycasters_for_picking();
|
||||
register_volume_raycasters_for_picking();
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::on_unregister_raycasters_for_picking()
|
||||
{
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
|
||||
m_raycasters.clear();
|
||||
set_sla_auxiliary_volumes_picking_state(true);
|
||||
unregister_point_raycasters_for_picking();
|
||||
unregister_volume_raycasters_for_picking();
|
||||
}
|
||||
#else
|
||||
void GLGizmoSlaSupports::on_render_for_picking()
|
||||
@ -181,10 +185,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
const size_t cache_size = m_editing_mode ? m_editing_cache.size() : m_normal_cache.size();
|
||||
|
||||
const bool has_points = (cache_size != 0);
|
||||
const bool has_holes = (/*! m_c->hollowed_mesh()->get_hollowed_mesh()
|
||||
&&*/ ! m_c->selection_info()->model_object()->sla_drain_holes.empty());
|
||||
|
||||
if (! has_points && ! has_holes)
|
||||
if (!has_points)
|
||||
return;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
@ -234,9 +235,9 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
const bool clipped = is_mesh_point_clipped(support_point.pos.cast<double>());
|
||||
if (!m_raycasters.empty()) {
|
||||
m_raycasters[i].first->set_active(!clipped);
|
||||
m_raycasters[i].second->set_active(!clipped);
|
||||
if (i < m_point_raycasters.size()) {
|
||||
m_point_raycasters[i].first->set_active(!clipped);
|
||||
m_point_raycasters[i].second->set_active(!clipped);
|
||||
}
|
||||
if (clipped)
|
||||
continue;
|
||||
@ -306,8 +307,7 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
if (m_editing_mode) {
|
||||
// in case the normal is not yet cached, find and cache it
|
||||
if (m_editing_cache[i].normal == Vec3f::Zero())
|
||||
m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
//m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
@ -373,67 +373,28 @@ void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
// Now render the drain holes:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
if (has_holes) {
|
||||
#else
|
||||
if (has_holes && ! picking) {
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
render_color = { 0.7f, 0.7f, 0.7f, 0.7f };
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cylinder.set_color(render_color);
|
||||
#else
|
||||
m_cylinder.set_color(-1, render_color);
|
||||
if (shader != nullptr)
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
shader->set_uniform("emission_factor", 0.5f);
|
||||
for (const sla::DrainHole& drain_hole : m_c->selection_info()->model_object()->sla_drain_holes) {
|
||||
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
|
||||
continue;
|
||||
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
#else
|
||||
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glTranslatef(drain_hole.pos.x(), drain_hole.pos.y(), drain_hole.pos.z()));
|
||||
glsafe(::glMultMatrixd(instance_scaling_matrix_inverse.data()));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glsafe(::glFrontFace(GL_CW));
|
||||
|
||||
// Matrices set, we can render the point mark now.
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
const Transform3d model_matrix = vol->world_matrix() * hole_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform(-drain_hole.height * Vec3d::UnitZ()) * Geometry::scale_transform(Vec3d(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
shader->set_uniform("view_model_matrix", view_matrix * model_matrix);
|
||||
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
|
||||
shader->set_uniform("view_normal_matrix", view_normal_matrix);
|
||||
#else
|
||||
glsafe(::glRotated(aa.angle() * (180. / M_PI), aa.axis().x(), aa.axis().y(), aa.axis().z()));
|
||||
glsafe(::glTranslated(0., 0., -drain_hole.height));
|
||||
glsafe(::glScaled(drain_hole.radius, drain_hole.radius, drain_hole.height + sla::HoleStickOutLength));
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
m_cylinder.render();
|
||||
|
||||
if (vol->is_left_handed())
|
||||
glsafe(::glFrontFace(GL_CCW));
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
}
|
||||
|
||||
#if !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
glsafe(::glPopMatrix());
|
||||
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::render_volumes()
|
||||
{
|
||||
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light_clip");
|
||||
if (shader == nullptr)
|
||||
return;
|
||||
|
||||
shader->start_using();
|
||||
shader->set_uniform("emission_factor", 0.0f);
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
|
||||
ClippingPlane clipping_plane = (m_c->object_clipper()->get_position() == 0.0) ? ClippingPlane::ClipsNothing() : *m_c->object_clipper()->get_clipping_plane();
|
||||
clipping_plane.set_normal(-clipping_plane.get_normal());
|
||||
m_volumes.set_clipping_plane(clipping_plane.get_data());
|
||||
|
||||
m_volumes.render(GLVolumeCollection::ERenderType::Opaque, false, camera.get_view_matrix(), camera.get_projection_matrix());
|
||||
shader->stop_using();
|
||||
}
|
||||
|
||||
bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||
{
|
||||
@ -456,48 +417,22 @@ bool GLGizmoSlaSupports::is_mesh_point_clipped(const Vec3d& point) const
|
||||
// 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 (m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->empty())
|
||||
if (!m_c->raycaster()->raycaster())
|
||||
return false;
|
||||
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_first_volume();
|
||||
Geometry::Transformation trafo = volume->get_instance_transformation() * volume->get_volume_transformation();
|
||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., m_c->selection_info()->get_sla_shift()));
|
||||
|
||||
double clp_dist = m_c->object_clipper()->get_position();
|
||||
const ClippingPlane* clp = m_c->object_clipper()->get_clipping_plane();
|
||||
|
||||
// The raycaster query
|
||||
Vec3f hit;
|
||||
Vec3f normal;
|
||||
if (m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->unproject_on_mesh(
|
||||
if (m_c->raycaster()->raycaster()->unproject_on_mesh(
|
||||
mouse_pos,
|
||||
trafo.get_matrix(),
|
||||
camera,
|
||||
m_volumes.volumes.front()->world_matrix(),
|
||||
wxGetApp().plater()->get_camera(),
|
||||
hit,
|
||||
normal,
|
||||
clp_dist != 0. ? clp : nullptr))
|
||||
{
|
||||
// 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->hollowed_mesh()->get_hollowed_mesh()) {
|
||||
// sla::DrainHoles drain_holes = m_c->selection_info()->model_object()->sla_drain_holes;
|
||||
// for (const sla::DrainHole& hole : 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);
|
||||
return true;
|
||||
// }
|
||||
m_c->object_clipper()->get_position() != 0.0 ? m_c->object_clipper()->get_clipping_plane() : nullptr)) {
|
||||
// Return both the point and the facet normal.
|
||||
pos_and_normal = std::make_pair(hit, normal);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@ -548,8 +483,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
m_parent.set_as_dirty();
|
||||
m_wait_for_up_event = true;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
unregister_point_raycasters_for_picking();
|
||||
register_point_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
else
|
||||
@ -592,9 +527,8 @@ bool GLGizmoSlaSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||
for (size_t idx : points_idxs)
|
||||
points_inside.emplace_back((trafo.get_matrix().cast<float>() * (m_editing_cache[idx].support_point.pos + m_editing_cache[idx].normal)).cast<float>());
|
||||
|
||||
assert(!m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume).emtpy());
|
||||
for (size_t idx : m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_unobscured_idxs(
|
||||
trafo, wxGetApp().plater()->get_camera(), points_inside,
|
||||
for (size_t idx : m_c->raycaster()->raycaster()->get_unobscured_idxs(
|
||||
trafo, wxGetApp().plater()->get_camera(), points_inside,
|
||||
m_c->object_clipper()->get_clipping_plane()))
|
||||
{
|
||||
if (idx >= orig_pts_num) // this is a cone-base, get index of point it belongs to
|
||||
@ -712,8 +646,8 @@ void GLGizmoSlaSupports::delete_selected_points(bool force)
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
on_register_raycasters_for_picking();
|
||||
unregister_point_raycasters_for_picking();
|
||||
register_point_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
select_point(NoPoints);
|
||||
@ -1027,7 +961,7 @@ bool GLGizmoSlaSupports::on_is_activable() const
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
|
||||
if (wxGetApp().preset_bundle->printers.get_edited_preset().printer_technology() != ptSLA
|
||||
|| !selection.is_from_single_instance())
|
||||
|| !selection.is_single_full_instance())
|
||||
return false;
|
||||
|
||||
// Check that none of the selected volumes is outside. Only SLA auxiliaries (supports) are allowed outside.
|
||||
@ -1055,9 +989,7 @@ CommonGizmosDataID GLGizmoSlaSupports::on_get_requirements() const
|
||||
int(CommonGizmosDataID::SelectionInfo)
|
||||
| int(CommonGizmosDataID::InstancesHider)
|
||||
| int(CommonGizmosDataID::Raycaster)
|
||||
| int(CommonGizmosDataID::HollowedMesh)
|
||||
| int(CommonGizmosDataID::ObjectClipper)
|
||||
| int(CommonGizmosDataID::SupportsClipper));
|
||||
| int(CommonGizmosDataID::ObjectClipper));
|
||||
}
|
||||
|
||||
|
||||
@ -1101,6 +1033,9 @@ void GLGizmoSlaSupports::on_set_state()
|
||||
disable_editing_mode(); // so it is not active next time the gizmo opens
|
||||
m_old_mo_id = -1;
|
||||
}
|
||||
|
||||
if (m_state == Off)
|
||||
m_c->instances_hider()->set_hide_full_scene(false);
|
||||
}
|
||||
m_old_state = m_state;
|
||||
}
|
||||
@ -1395,10 +1330,8 @@ void GLGizmoSlaSupports::switch_to_editing_mode()
|
||||
m_editing_cache.emplace_back(sp);
|
||||
select_point(NoPoints);
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_register_raycasters_for_picking();
|
||||
register_point_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
m_c->instances_hider()->show_supports(false);
|
||||
m_parent.set_as_dirty();
|
||||
}
|
||||
|
||||
@ -1408,10 +1341,9 @@ void GLGizmoSlaSupports::disable_editing_mode()
|
||||
if (m_editing_mode) {
|
||||
m_editing_mode = false;
|
||||
wxGetApp().plater()->leave_gizmos_stack();
|
||||
m_c->instances_hider()->show_supports(true);
|
||||
m_parent.set_as_dirty();
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
on_unregister_raycasters_for_picking();
|
||||
unregister_point_raycasters_for_picking();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
}
|
||||
wxGetApp().plater()->get_notification_manager()->close_notification_of_type(NotificationType::QuitSLAManualMode);
|
||||
@ -1432,53 +1364,130 @@ bool GLGizmoSlaSupports::unsaved_changes() const
|
||||
}
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void GLGizmoSlaSupports::set_sla_auxiliary_volumes_picking_state(bool state)
|
||||
void GLGizmoSlaSupports::register_point_raycasters_for_picking()
|
||||
{
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>>* raycasters = m_parent.get_raycasters_for_picking(SceneRaycaster::EType::Volume);
|
||||
if (raycasters != nullptr) {
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList ids = selection.get_volume_idxs();
|
||||
for (unsigned int id : ids) {
|
||||
const GLVolume* v = selection.get_volume(id);
|
||||
if (v->is_sla_pad() || v->is_sla_support()) {
|
||||
auto it = std::find_if(raycasters->begin(), raycasters->end(), [v](std::shared_ptr<SceneRaycasterItem> item) { return item->get_raycaster() == v->mesh_raycaster.get(); });
|
||||
if (it != raycasters->end())
|
||||
(*it)->set_active(state);
|
||||
}
|
||||
assert(m_point_raycasters.empty());
|
||||
|
||||
if (m_editing_mode && !m_editing_cache.empty()) {
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
m_point_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_sphere.mesh_raycaster, Transform3d::Identity()),
|
||||
m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i, *m_cone.mesh_raycaster, Transform3d::Identity()));
|
||||
}
|
||||
update_point_raycasters_for_picking_transform();
|
||||
}
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::update_raycasters_for_picking_transform()
|
||||
void GLGizmoSlaSupports::unregister_point_raycasters_for_picking()
|
||||
{
|
||||
if (!m_editing_cache.empty()) {
|
||||
assert(!m_raycasters.empty());
|
||||
for (size_t i = 0; i < m_point_raycasters.size(); ++i) {
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, i);
|
||||
}
|
||||
m_point_raycasters.clear();
|
||||
}
|
||||
|
||||
const GLVolume* vol = m_parent.get_selection().get_first_volume();
|
||||
const Geometry::Transformation transformation(vol->world_matrix());
|
||||
const Transform3d instance_scaling_matrix_inverse = transformation.get_scaling_factor_matrix().inverse();
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
const Transform3d support_matrix = Geometry::translation_transform(m_editing_cache[i].support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
void GLGizmoSlaSupports::register_volume_raycasters_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
|
||||
const GLVolume* v = m_volumes.volumes[i];
|
||||
m_volume_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i, *v->mesh_raycaster, v->world_matrix()));
|
||||
}
|
||||
}
|
||||
|
||||
if (m_editing_cache[i].normal == Vec3f::Zero())
|
||||
m_parent.raycaster().get_raycasters(SceneRaycaster::EType::Volume)->front()->get_raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
void GLGizmoSlaSupports::unregister_volume_raycasters_for_picking()
|
||||
{
|
||||
for (size_t i = 0; i < m_volume_raycasters.size(); ++i) {
|
||||
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, (int)SceneRaycaster::EIdBase::Gizmo + (int)i);
|
||||
}
|
||||
m_volume_raycasters.clear();
|
||||
}
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
const Transform3d cone_matrix = vol->world_matrix() * support_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::translation_transform((CONE_HEIGHT + m_editing_cache[i].support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ()) *
|
||||
Geometry::rotation_transform({ double(PI), 0.0, 0.0 }) * Geometry::scale_transform({ CONE_RADIUS, CONE_RADIUS, CONE_HEIGHT });
|
||||
m_raycasters[i].second->set_transform(cone_matrix);
|
||||
void GLGizmoSlaSupports::update_point_raycasters_for_picking_transform()
|
||||
{
|
||||
if (m_editing_cache.empty())
|
||||
return;
|
||||
|
||||
const double radius = (double)m_editing_cache[i].support_point.head_front_radius * RenderPointScale;
|
||||
const Transform3d sphere_matrix = vol->world_matrix() * support_matrix * Geometry::scale_transform(radius);
|
||||
m_raycasters[i].first->set_transform(sphere_matrix);
|
||||
}
|
||||
assert(!m_point_raycasters.empty());
|
||||
|
||||
const GLVolume* vol = m_parent.get_selection().get_first_volume();
|
||||
const Geometry::Transformation transformation(vol->world_matrix());
|
||||
const Transform3d instance_scaling_matrix_inverse = transformation.get_scaling_factor_matrix().inverse();
|
||||
for (size_t i = 0; i < m_editing_cache.size(); ++i) {
|
||||
const Transform3d support_matrix = Geometry::translation_transform(m_editing_cache[i].support_point.pos.cast<double>()) * instance_scaling_matrix_inverse;
|
||||
|
||||
if (m_editing_cache[i].normal == Vec3f::Zero())
|
||||
m_c->raycaster()->raycaster()->get_closest_point(m_editing_cache[i].support_point.pos, &m_editing_cache[i].normal);
|
||||
|
||||
Eigen::Quaterniond q;
|
||||
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * m_editing_cache[i].normal.cast<double>());
|
||||
const Eigen::AngleAxisd aa(q);
|
||||
const Transform3d cone_matrix = vol->world_matrix() * support_matrix * Transform3d(aa.toRotationMatrix()) *
|
||||
Geometry::assemble_transform((CONE_HEIGHT + m_editing_cache[i].support_point.head_front_radius * RenderPointScale) * Vec3d::UnitZ(),
|
||||
Vec3d(PI, 0.0, 0.0), Vec3d(CONE_RADIUS, CONE_RADIUS, CONE_HEIGHT));
|
||||
m_point_raycasters[i].second->set_transform(cone_matrix);
|
||||
|
||||
const double radius = (double)m_editing_cache[i].support_point.head_front_radius * RenderPointScale;
|
||||
const Transform3d sphere_matrix = vol->world_matrix() * support_matrix * Geometry::scale_transform(radius);
|
||||
m_point_raycasters[i].first->set_transform(sphere_matrix);
|
||||
}
|
||||
}
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
|
||||
void GLGizmoSlaSupports::update_volumes()
|
||||
{
|
||||
m_volumes.clear();
|
||||
unregister_volume_raycasters_for_picking();
|
||||
|
||||
const ModelObject* mo = m_c->selection_info()->model_object();
|
||||
if (mo == nullptr)
|
||||
return;
|
||||
|
||||
const SLAPrintObject* po = m_c->selection_info()->print_object();
|
||||
if (po == nullptr)
|
||||
return;
|
||||
|
||||
TriangleMesh backend_mesh = po->get_mesh_to_print();
|
||||
if (!backend_mesh.empty()) {
|
||||
// The backend has generated a valid mesh. Use it
|
||||
backend_mesh.transform(po->trafo().inverse());
|
||||
m_volumes.volumes.emplace_back(new GLVolume());
|
||||
GLVolume* new_volume = m_volumes.volumes.back();
|
||||
new_volume->model.init_from(backend_mesh);
|
||||
new_volume->set_instance_transformation(po->model_object()->instances[m_parent.get_selection().get_instance_idx()]->get_transformation());
|
||||
new_volume->set_sla_shift_z(po->get_current_elevation());
|
||||
new_volume->selected = true; // to set the proper color
|
||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(backend_mesh);
|
||||
}
|
||||
|
||||
if (m_volumes.volumes.empty()) {
|
||||
// No valid mesh found in the backend. Use the selection to duplicate the volumes
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Selection::IndicesList& idxs = selection.get_volume_idxs();
|
||||
for (unsigned int idx : idxs) {
|
||||
const GLVolume* v = selection.get_volume(idx);
|
||||
if (!v->is_modifier) {
|
||||
m_volumes.volumes.emplace_back(new GLVolume());
|
||||
GLVolume* new_volume = m_volumes.volumes.back();
|
||||
const TriangleMesh& mesh = mo->volumes[v->volume_idx()]->mesh();
|
||||
new_volume->model.init_from(mesh);
|
||||
new_volume->set_instance_transformation(v->get_instance_transformation());
|
||||
new_volume->set_volume_transformation(v->get_volume_transformation());
|
||||
new_volume->set_sla_shift_z(v->get_sla_shift_z());
|
||||
new_volume->selected = true; // to set the proper color
|
||||
new_volume->mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
register_volume_raycasters_for_picking();
|
||||
}
|
||||
|
||||
void GLGizmoSlaSupports::process_mesh(SLAPrintObjectStep step, bool postpone_error_messages)
|
||||
{
|
||||
wxGetApp().CallAfter([this, step, postpone_error_messages]() {
|
||||
wxGetApp().plater()->reslice_SLA_until_step(step, *m_c->selection_info()->model_object(), postpone_error_messages);
|
||||
});
|
||||
}
|
||||
|
||||
SlaGizmoHelpDialog::SlaGizmoHelpDialog()
|
||||
: wxDialog(nullptr, wxID_ANY, _L("SLA gizmo keyboard shortcuts"), wxDefaultPosition, wxDefaultSize, wxDEFAULT_DIALOG_STYLE|wxRESIZE_BORDER)
|
||||
{
|
||||
|
@ -3,6 +3,7 @@
|
||||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "slic3r/GUI/GLSelectionRectangle.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
#include "libslic3r/SLA/SupportPoint.hpp"
|
||||
#include "libslic3r/ObjectID.hpp"
|
||||
@ -22,7 +23,6 @@ enum class SLAGizmoEventType : unsigned char;
|
||||
class GLGizmoSlaSupports : public GLGizmoBase
|
||||
{
|
||||
private:
|
||||
|
||||
bool unproject_on_mesh(const Vec2d& mouse_pos, std::pair<Vec3f, Vec3f>& pos_and_normal);
|
||||
|
||||
static constexpr float RenderPointScale = 1.f;
|
||||
@ -93,11 +93,17 @@ private:
|
||||
#else
|
||||
void render_points(const Selection& selection, bool picking = false);
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void render_volumes();
|
||||
bool unsaved_changes() const;
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
void set_sla_auxiliary_volumes_picking_state(bool state);
|
||||
void update_raycasters_for_picking_transform();
|
||||
void register_point_raycasters_for_picking();
|
||||
void unregister_point_raycasters_for_picking();
|
||||
void register_volume_raycasters_for_picking();
|
||||
void unregister_volume_raycasters_for_picking();
|
||||
void update_point_raycasters_for_picking_transform();
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
void update_volumes();
|
||||
void process_mesh(SLAPrintObjectStep step, bool postpone_error_messages = false);
|
||||
|
||||
bool m_lock_unique_islands = false;
|
||||
bool m_editing_mode = false; // Is editing mode active?
|
||||
@ -113,12 +119,14 @@ private:
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
PickingModel m_sphere;
|
||||
PickingModel m_cone;
|
||||
std::vector<std::pair<std::shared_ptr<SceneRaycasterItem>, std::shared_ptr<SceneRaycasterItem>>> m_raycasters;
|
||||
std::vector<std::pair<std::shared_ptr<SceneRaycasterItem>, std::shared_ptr<SceneRaycasterItem>>> m_point_raycasters;
|
||||
std::vector<std::shared_ptr<SceneRaycasterItem>> m_volume_raycasters;
|
||||
#else
|
||||
GLModel m_cone;
|
||||
GLModel m_sphere;
|
||||
#endif // ENABLE_RAYCAST_PICKING
|
||||
GLModel m_cylinder;
|
||||
|
||||
GLVolumeCollection m_volumes;
|
||||
|
||||
// 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.
|
||||
|
@ -59,13 +59,6 @@ InstancesHider* CommonGizmosDataPool::instances_hider() const
|
||||
return inst_hider->is_valid() ? inst_hider : nullptr;
|
||||
}
|
||||
|
||||
//HollowedMesh* CommonGizmosDataPool::hollowed_mesh() const
|
||||
//{
|
||||
// HollowedMesh* hol_mesh = dynamic_cast<HollowedMesh*>(m_data.at(CommonGizmosDataID::HollowedMesh).get());
|
||||
// assert(hol_mesh);
|
||||
// return hol_mesh->is_valid() ? hol_mesh : nullptr;
|
||||
//}
|
||||
|
||||
Raycaster* CommonGizmosDataPool::raycaster() const
|
||||
{
|
||||
Raycaster* rc = dynamic_cast<Raycaster*>(m_data.at(CommonGizmosDataID::Raycaster).get());
|
||||
@ -123,9 +116,8 @@ void SelectionInfo::on_update()
|
||||
|
||||
if (selection.is_single_full_instance()) {
|
||||
m_model_object = selection.get_model()->objects[selection.get_object_idx()];
|
||||
|
||||
if (m_model_object)
|
||||
m_print_object = get_pool()->get_canvas()->sla_print()->get_object(m_model_object->id());
|
||||
m_print_object = get_pool()->get_canvas()->sla_print()->get_print_object_by_model_object_id(m_model_object->id());
|
||||
|
||||
m_z_shift = selection.get_first_volume()->get_sla_shift_z();
|
||||
}
|
||||
@ -154,8 +146,10 @@ void InstancesHider::on_update()
|
||||
|
||||
if (mo && active_inst != -1) {
|
||||
canvas->toggle_model_objects_visibility(false);
|
||||
canvas->toggle_model_objects_visibility(true, mo, active_inst);
|
||||
canvas->toggle_sla_auxiliaries_visibility(m_show_supports, mo, active_inst);
|
||||
if (!m_hide_full_scene) {
|
||||
canvas->toggle_model_objects_visibility(true, mo, active_inst);
|
||||
canvas->toggle_sla_auxiliaries_visibility(false, mo, active_inst);
|
||||
}
|
||||
canvas->set_use_clipping_planes(true);
|
||||
// Some objects may be sinking, do not show whatever is below the bed.
|
||||
canvas->set_clipping_plane(0, ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
|
||||
@ -188,9 +182,10 @@ void InstancesHider::on_release()
|
||||
m_clippers.clear();
|
||||
}
|
||||
|
||||
void InstancesHider::show_supports(bool show) {
|
||||
if (m_show_supports != show) {
|
||||
m_show_supports = show;
|
||||
void InstancesHider::set_hide_full_scene(bool hide)
|
||||
{
|
||||
if (m_hide_full_scene != hide) {
|
||||
m_hide_full_scene = hide;
|
||||
on_update();
|
||||
}
|
||||
}
|
||||
@ -255,81 +250,6 @@ void InstancesHider::render_cut() const
|
||||
|
||||
|
||||
|
||||
//void HollowedMesh::on_update()
|
||||
//{
|
||||
// const ModelObject* mo = get_pool()->selection_info()->model_object();
|
||||
// bool is_sla = wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA;
|
||||
// if (! mo || ! is_sla)
|
||||
// return;
|
||||
|
||||
// const GLCanvas3D* canvas = get_pool()->get_canvas();
|
||||
// const PrintObjects& print_objects = canvas->sla_print()->objects();
|
||||
// const SLAPrintObject* print_object = (m_print_object_idx >= 0 && m_print_object_idx < int(print_objects.size()))
|
||||
// ? print_objects[m_print_object_idx]
|
||||
// : nullptr;
|
||||
|
||||
// // Find the respective SLAPrintObject.
|
||||
// if (m_print_object_idx < 0 || m_print_objects_count != int(print_objects.size())) {
|
||||
// m_print_objects_count = print_objects.size();
|
||||
// m_print_object_idx = -1;
|
||||
// for (const SLAPrintObject* po : print_objects) {
|
||||
// ++m_print_object_idx;
|
||||
// if (po->model_object()->id() == mo->id()) {
|
||||
// print_object = po;
|
||||
// break;
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
// // If there is a valid SLAPrintObject, check state of Hollowing step.
|
||||
// if (print_object) {
|
||||
// if (print_object->is_step_done(slaposDrillHoles) && !print_object->get_mesh_to_print().empty()) {
|
||||
// size_t timestamp = print_object->step_state_with_timestamp(slaposDrillHoles).timestamp;
|
||||
// if (timestamp > m_old_hollowing_timestamp) {
|
||||
// const TriangleMesh& backend_mesh = print_object->get_mesh_to_print();
|
||||
// if (! backend_mesh.empty()) {
|
||||
// m_hollowed_mesh_transformed.reset(new TriangleMesh(backend_mesh));
|
||||
// Transform3d trafo_inv = (canvas->sla_print()->sla_trafo(*mo) * print_object->model_object()->volumes.front()->get_transformation().get_matrix()).inverse();
|
||||
// m_hollowed_mesh_transformed->transform(trafo_inv);
|
||||
// m_drainholes = print_object->model_object()->sla_drain_holes;
|
||||
// m_old_hollowing_timestamp = timestamp;
|
||||
|
||||
//// indexed_triangle_set interior = print_object->hollowed_interior_mesh();
|
||||
//// its_flip_triangles(interior);
|
||||
//// m_hollowed_interior_transformed = std::make_unique<TriangleMesh>(std::move(interior));
|
||||
//// m_hollowed_interior_transformed->transform(trafo_inv);
|
||||
// }
|
||||
// else {
|
||||
// m_hollowed_mesh_transformed.reset(nullptr);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// m_hollowed_mesh_transformed.reset(nullptr);
|
||||
// }
|
||||
//}
|
||||
|
||||
|
||||
//void HollowedMesh::on_release()
|
||||
//{
|
||||
// m_hollowed_mesh_transformed.reset();
|
||||
// m_old_hollowing_timestamp = 0;
|
||||
// m_print_object_idx = -1;
|
||||
//}
|
||||
|
||||
|
||||
//const TriangleMesh* HollowedMesh::get_hollowed_mesh() const
|
||||
//{
|
||||
// return m_hollowed_mesh_transformed.get();
|
||||
//}
|
||||
|
||||
//const TriangleMesh* HollowedMesh::get_hollowed_interior() const
|
||||
//{
|
||||
// return m_hollowed_interior_transformed.get();
|
||||
//}
|
||||
|
||||
|
||||
|
||||
|
||||
void Raycaster::on_update()
|
||||
{
|
||||
@ -347,21 +267,28 @@ void Raycaster::on_update()
|
||||
mvs = mo->volumes;
|
||||
|
||||
std::vector<const TriangleMesh*> meshes;
|
||||
const std::vector<ModelVolume*>& mvs = mo->volumes;
|
||||
// if (mvs.size() == 1) {
|
||||
// assert(mvs.front()->is_model_part());
|
||||
// const HollowedMesh* hollowed_mesh_tracker = get_pool()->hollowed_mesh();
|
||||
// if (hollowed_mesh_tracker && hollowed_mesh_tracker->get_hollowed_mesh())
|
||||
// meshes.push_back(hollowed_mesh_tracker->get_hollowed_mesh());
|
||||
// }
|
||||
if (meshes.empty()) {
|
||||
for (const ModelVolume* v : mvs) {
|
||||
if (v->is_model_part())
|
||||
meshes.push_back(&v->mesh());
|
||||
bool force_raycaster_regeneration = false;
|
||||
if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) {
|
||||
// For sla printers we use the mesh generated by the backend
|
||||
const SLAPrintObject* po = get_pool()->selection_info()->print_object();
|
||||
assert(po != nullptr);
|
||||
m_sla_mesh_cache = po->get_mesh_to_print();
|
||||
if (!m_sla_mesh_cache.empty()) {
|
||||
m_sla_mesh_cache.transform(po->trafo().inverse());
|
||||
meshes.emplace_back(&m_sla_mesh_cache);
|
||||
force_raycaster_regeneration = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (meshes != m_old_meshes) {
|
||||
if (meshes.empty()) {
|
||||
const std::vector<ModelVolume*>& mvs = mo->volumes;
|
||||
for (const ModelVolume* mv : mvs) {
|
||||
if (mv->is_model_part())
|
||||
meshes.push_back(&mv->mesh());
|
||||
}
|
||||
}
|
||||
|
||||
if (force_raycaster_regeneration || meshes != m_old_meshes) {
|
||||
m_raycasters.clear();
|
||||
for (const TriangleMesh* mesh : meshes)
|
||||
#if ENABLE_RAYCAST_PICKING
|
||||
@ -399,25 +326,36 @@ void ObjectClipper::on_update()
|
||||
|
||||
// which mesh should be cut?
|
||||
std::vector<const TriangleMesh*> meshes;
|
||||
// bool has_hollowed = get_pool()->hollowed_mesh() && get_pool()->hollowed_mesh()->get_hollowed_mesh();
|
||||
// if (has_hollowed)
|
||||
// meshes.push_back(get_pool()->hollowed_mesh()->get_hollowed_mesh());
|
||||
std::vector<Geometry::Transformation> trafos;
|
||||
bool force_clipper_regeneration = false;
|
||||
if (wxGetApp().preset_bundle->printers.get_selected_preset().printer_technology() == ptSLA) {
|
||||
// For sla printers we use the mesh generated by the backend
|
||||
const SLAPrintObject* po = get_pool()->selection_info()->print_object();
|
||||
assert(po != nullptr);
|
||||
m_sla_mesh_cache = po->get_mesh_to_print();
|
||||
if (!m_sla_mesh_cache.empty()) {
|
||||
m_sla_mesh_cache.transform(po->trafo().inverse());
|
||||
meshes.emplace_back(&m_sla_mesh_cache);
|
||||
trafos.emplace_back(Geometry::Transformation());
|
||||
force_clipper_regeneration = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (meshes.empty())
|
||||
for (const ModelVolume* mv : mo->volumes)
|
||||
meshes.push_back(&mv->mesh());
|
||||
if (meshes.empty()) {
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
meshes.emplace_back(&mv->mesh());
|
||||
trafos.emplace_back(mv->get_transformation());
|
||||
}
|
||||
}
|
||||
|
||||
if (meshes != m_old_meshes) {
|
||||
if (force_clipper_regeneration || meshes != m_old_meshes) {
|
||||
m_clippers.clear();
|
||||
for (const TriangleMesh* mesh : meshes) {
|
||||
m_clippers.emplace_back(new MeshClipper);
|
||||
m_clippers.back()->set_mesh(*mesh);
|
||||
for (size_t i = 0; i < meshes.size(); ++i) {
|
||||
m_clippers.emplace_back(new MeshClipper, trafos[i]);
|
||||
m_clippers.back().first->set_mesh(*meshes[i]);
|
||||
}
|
||||
m_old_meshes = meshes;
|
||||
|
||||
// if (has_hollowed)
|
||||
// m_clippers.front()->set_negative_mesh(*get_pool()->hollowed_mesh()->get_hollowed_interior());
|
||||
|
||||
m_active_inst_bb_radius =
|
||||
mo->instance_bounding_box(get_pool()->selection_info()->get_active_instance()).radius();
|
||||
}
|
||||
@ -437,46 +375,27 @@ void ObjectClipper::render_cut() const
|
||||
{
|
||||
if (m_clp_ratio == 0.)
|
||||
return;
|
||||
|
||||
const SelectionInfo* sel_info = get_pool()->selection_info();
|
||||
int sel_instance_idx = sel_info->get_active_instance();
|
||||
if (sel_instance_idx < 0)
|
||||
return;
|
||||
const ModelObject* mo = sel_info->model_object();
|
||||
const Geometry::Transformation inst_trafo = mo->instances[sel_instance_idx]->get_transformation();
|
||||
|
||||
size_t clipper_id = 0;
|
||||
for (const ModelVolume* mv : mo->volumes) {
|
||||
const Geometry::Transformation vol_trafo = mv->get_transformation();
|
||||
Geometry::Transformation trafo = inst_trafo * vol_trafo;
|
||||
const Geometry::Transformation inst_trafo = sel_info->model_object()->instances[sel_info->get_active_instance()]->get_transformation();
|
||||
for (auto& clipper : m_clippers) {
|
||||
Geometry::Transformation trafo = inst_trafo * clipper.second;
|
||||
trafo.set_offset(trafo.get_offset() + Vec3d(0., 0., sel_info->get_sla_shift()));
|
||||
|
||||
auto& clipper = m_clippers[clipper_id];
|
||||
clipper->set_plane(*m_clp);
|
||||
clipper->set_transformation(trafo);
|
||||
clipper->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
|
||||
#if ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
clipper->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f });
|
||||
clipper->render_contour({ 1.f, 1.f, 1.f, 1.f});
|
||||
#else
|
||||
glsafe(::glPushMatrix());
|
||||
glsafe(::glColor3f(1.0f, 0.37f, 0.0f));
|
||||
clipper->render_cut();
|
||||
glsafe(::glColor3f(1.f, 1.f, 1.f));
|
||||
clipper->render_contour();
|
||||
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
|
||||
|
||||
++clipper_id;
|
||||
clipper.first->set_plane(*m_clp);
|
||||
clipper.first->set_transformation(trafo);
|
||||
clipper.first->set_limiting_plane(ClippingPlane(Vec3d::UnitZ(), -SINKING_Z_THRESHOLD));
|
||||
clipper.first->render_cut({ 1.0f, 0.37f, 0.0f, 1.0f });
|
||||
}
|
||||
}
|
||||
|
||||
bool ObjectClipper::is_projection_inside_cut(const Vec3d& point) const
|
||||
{
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [point](const std::unique_ptr<MeshClipper>& cl) { return cl->is_projection_inside_cut(point); });
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [point](const auto& cl) { return cl.first->is_projection_inside_cut(point); });
|
||||
}
|
||||
|
||||
bool ObjectClipper::has_valid_contour() const
|
||||
{
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const std::unique_ptr<MeshClipper>& cl) { return cl->has_valid_contour(); });
|
||||
return m_clp_ratio != 0. && std::any_of(m_clippers.begin(), m_clippers.end(), [](const auto& cl) { return cl.first->has_valid_contour(); });
|
||||
}
|
||||
|
||||
void ObjectClipper::set_position_by_ratio(double pos, bool keep_normal)
|
||||
@ -514,13 +433,13 @@ void ObjectClipper::set_behavior(bool hide_clipped, bool fill_cut, double contou
|
||||
{
|
||||
m_hide_clipped = hide_clipped;
|
||||
for (auto& clipper : m_clippers)
|
||||
clipper->set_behaviour(fill_cut, contour_width);
|
||||
clipper.first->set_behaviour(fill_cut, contour_width);
|
||||
}
|
||||
|
||||
void ObjectClipper::pass_mouse_click(const Vec3d& pt)
|
||||
{
|
||||
for (auto& clipper : m_clippers)
|
||||
clipper->pass_mouse_click(pt);
|
||||
clipper.first->pass_mouse_click(pt);
|
||||
}
|
||||
|
||||
std::vector<Vec3d> ObjectClipper::get_disabled_contours() const
|
||||
@ -586,7 +505,6 @@ void SupportsClipper::render_cut() const
|
||||
{
|
||||
const CommonGizmosDataObjects::ObjectClipper* ocl = get_pool()->object_clipper();
|
||||
if (ocl->get_position() == 0.
|
||||
|| ! get_pool()->instances_hider()->are_supports_shown()
|
||||
|| ! m_clipper)
|
||||
return;
|
||||
|
||||
|
@ -63,7 +63,6 @@ enum class CommonGizmosDataID {
|
||||
None = 0,
|
||||
SelectionInfo = 1 << 0,
|
||||
InstancesHider = 1 << 1,
|
||||
HollowedMesh = 1 << 2,
|
||||
Raycaster = 1 << 3,
|
||||
ObjectClipper = 1 << 4,
|
||||
SupportsClipper = 1 << 5,
|
||||
@ -187,8 +186,7 @@ public:
|
||||
CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
|
||||
#endif // NDEBUG
|
||||
|
||||
void show_supports(bool show);
|
||||
bool are_supports_shown() const { return m_show_supports; }
|
||||
void set_hide_full_scene(bool hide);
|
||||
void render_cut() const;
|
||||
|
||||
protected:
|
||||
@ -196,42 +194,13 @@ protected:
|
||||
void on_release() override;
|
||||
|
||||
private:
|
||||
bool m_show_supports = false;
|
||||
bool m_hide_full_scene{ false };
|
||||
std::vector<const TriangleMesh*> m_old_meshes;
|
||||
std::vector<std::unique_ptr<MeshClipper>> m_clippers;
|
||||
};
|
||||
|
||||
|
||||
|
||||
//class HollowedMesh : public CommonGizmosDataBase
|
||||
//{
|
||||
//public:
|
||||
// explicit HollowedMesh(CommonGizmosDataPool* cgdp)
|
||||
// : CommonGizmosDataBase(cgdp) {}
|
||||
//#ifndef NDEBUG
|
||||
// CommonGizmosDataID get_dependencies() const override { return CommonGizmosDataID::SelectionInfo; }
|
||||
//#endif // NDEBUG
|
||||
|
||||
// const sla::DrainHoles &get_drainholes() const { return m_drainholes; }
|
||||
|
||||
// const TriangleMesh* get_hollowed_mesh() const;
|
||||
// const TriangleMesh* get_hollowed_interior() const;
|
||||
|
||||
//protected:
|
||||
// void on_update() override;
|
||||
// void on_release() override;
|
||||
|
||||
//private:
|
||||
// std::unique_ptr<TriangleMesh> m_hollowed_mesh_transformed;
|
||||
// std::unique_ptr<TriangleMesh> m_hollowed_interior_transformed;
|
||||
// size_t m_old_hollowing_timestamp = 0;
|
||||
// int m_print_object_idx = -1;
|
||||
// int m_print_objects_count = 0;
|
||||
// sla::DrainHoles m_drainholes;
|
||||
//};
|
||||
|
||||
|
||||
|
||||
class Raycaster : public CommonGizmosDataBase
|
||||
{
|
||||
public:
|
||||
@ -251,6 +220,8 @@ protected:
|
||||
private:
|
||||
std::vector<std::unique_ptr<MeshRaycaster>> m_raycasters;
|
||||
std::vector<const TriangleMesh*> m_old_meshes;
|
||||
// Used to store the sla mesh coming from the backend
|
||||
TriangleMesh m_sla_mesh_cache;
|
||||
};
|
||||
|
||||
|
||||
@ -285,7 +256,9 @@ protected:
|
||||
|
||||
private:
|
||||
std::vector<const TriangleMesh*> m_old_meshes;
|
||||
std::vector<std::unique_ptr<MeshClipper>> m_clippers;
|
||||
// Used to store the sla mesh coming from the backend
|
||||
TriangleMesh m_sla_mesh_cache;
|
||||
std::vector<std::pair<std::unique_ptr<MeshClipper>, Geometry::Transformation>> m_clippers;
|
||||
std::unique_ptr<ClippingPlane> m_clp;
|
||||
double m_clp_ratio = 0.;
|
||||
double m_active_inst_bb_radius = 0.;
|
||||
|
@ -100,7 +100,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
|
||||
};
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
m_last_hit.reset();
|
||||
const_cast<std::optional<HitResult>*>(&m_last_hit)->reset();
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
|
||||
HitResult ret;
|
||||
@ -142,7 +142,7 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
|
||||
ret.raycaster_id = decode_id(ret.type, ret.raycaster_id);
|
||||
|
||||
#if ENABLE_RAYCAST_PICKING_DEBUG
|
||||
m_last_hit = ret;
|
||||
*const_cast<std::optional<HitResult>*>(&m_last_hit) = ret;
|
||||
#endif // ENABLE_RAYCAST_PICKING_DEBUG
|
||||
return ret;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user