NEW:add "select triangle" mode in "lay on face" gizmo
jira: STUDIO-10200 Change-Id: I7ce594a527ef220ef9dec56d370b9de2616ad92a (cherry picked from commit ab89fa6ea1bb3345182b41d64acde27ec3e3c24a)
This commit is contained in:
parent
6781a874b5
commit
fcfe5648ca
|
@ -11376,6 +11376,19 @@ GLVolume *get_selected_gl_volume(const GLCanvas3D &canvas)
|
|||
return nullptr;
|
||||
}
|
||||
|
||||
ModelObject *get_selected_model_object(GLCanvas3D &canvas) {
|
||||
auto v = get_selected_gl_volume(canvas);
|
||||
if (v) {
|
||||
auto mo = get_model_object(*v, canvas.get_model()->objects);
|
||||
return mo;
|
||||
}
|
||||
else {
|
||||
int out_object_idx;
|
||||
return canvas.get_selection().get_selected_single_object(out_object_idx);
|
||||
}
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
ModelObject *get_model_object(const GLVolume &gl_volume, const Model &model) { return get_model_object(gl_volume, model.objects); }
|
||||
|
||||
ModelObject *get_model_object(const GLVolume &gl_volume, const ModelObjectPtrs &objects)
|
||||
|
|
|
@ -1351,6 +1351,7 @@ ModelVolume *get_model_volume(const GLVolume &v, const ModelObject &object);
|
|||
GLVolume *get_first_hovered_gl_volume(const GLCanvas3D &canvas);
|
||||
GLVolume *get_selected_gl_volume(const GLCanvas3D &canvas);
|
||||
|
||||
ModelObject *get_selected_model_object(GLCanvas3D &canvas);
|
||||
ModelObject *get_model_object(const GLVolume &gl_volume, const Model &model);
|
||||
ModelObject *get_model_object(const GLVolume &gl_volume, const ModelObjectPtrs &objects);
|
||||
|
||||
|
|
|
@ -33,17 +33,17 @@ bool GLGizmoFlatten::on_init()
|
|||
|
||||
void GLGizmoFlatten::on_set_state()
|
||||
{
|
||||
m_hit_facet = -1;
|
||||
m_last_hit_facet = -1;
|
||||
}
|
||||
|
||||
CommonGizmosDataID GLGizmoFlatten::on_get_requirements() const
|
||||
{
|
||||
return CommonGizmosDataID::SelectionInfo;
|
||||
return CommonGizmosDataID(int(CommonGizmosDataID::SelectionInfo) | int(CommonGizmosDataID::InstancesHider) | int(CommonGizmosDataID::Raycaster) |
|
||||
int(CommonGizmosDataID::ObjectClipper));
|
||||
}
|
||||
|
||||
void GLGizmoFlatten::on_render_input_window(float x, float y, float bottom_limit) {
|
||||
if (!m_show_warning) {
|
||||
return;
|
||||
}
|
||||
double screen_scale = wxDisplay(wxGetApp().plater()).GetScaleFactor();
|
||||
static float last_y = 0.0f;
|
||||
static float last_h = 0.0f;
|
||||
|
@ -59,6 +59,31 @@ void GLGizmoFlatten::on_render_input_window(float x, float y, float bottom_limit
|
|||
ImGuiWrapper::push_toolbar_style(m_parent.get_scale());
|
||||
GizmoImguiBegin(on_get_name(), ImGuiWindowFlags_NoMove | ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_NoTitleBar);
|
||||
|
||||
float space_size = m_imgui->get_style_scaling() * 8;
|
||||
float mode_cap = m_imgui->calc_text_size(_L("Mode") + ":").x;
|
||||
float caption_size = mode_cap + space_size + ImGui::GetStyle().WindowPadding.x;
|
||||
ImGui::AlignTextToFramePadding();
|
||||
m_imgui->text(_L("Mode") + ":");
|
||||
ImGui::SameLine();//ImGui::SameLine(caption_size);
|
||||
bool faltten_type_defult = m_faltten_type == FlattenType::Default;
|
||||
auto first_mode_str = _L("Convex hull");
|
||||
if (m_imgui->bbl_checkbox(first_mode_str, faltten_type_defult)) {
|
||||
if (faltten_type_defult) {
|
||||
m_faltten_type = FlattenType::Default;
|
||||
} else {
|
||||
m_faltten_type = FlattenType::Triangle;
|
||||
}
|
||||
}
|
||||
ImGui::SameLine();//ImGui::SameLine(new_label_width);
|
||||
bool faltten_type_tri = m_faltten_type == FlattenType::Triangle;
|
||||
if (m_imgui->bbl_checkbox(_L("Triangular facet"), faltten_type_tri)) {
|
||||
if (!faltten_type_tri) {
|
||||
m_faltten_type = FlattenType::Default;
|
||||
} else {
|
||||
m_faltten_type = FlattenType::Triangle;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_show_warning) {
|
||||
m_imgui->warning_text(_L("Warning: All triangle areas are too small,The current function is not working."));
|
||||
}
|
||||
|
@ -87,11 +112,59 @@ void GLGizmoFlatten::on_start_dragging()
|
|||
{
|
||||
if (m_hover_id != -1) {
|
||||
assert(m_planes_valid);
|
||||
m_normal = m_planes[m_hover_id].normal;
|
||||
if (m_faltten_type == FlattenType::Default) {
|
||||
m_normal = m_planes[m_hover_id].normal;
|
||||
}
|
||||
else {
|
||||
m_normal = m_hit_object_normal.cast<double>();
|
||||
}
|
||||
m_starting_center = m_parent.get_selection().get_bounding_box().center();
|
||||
}
|
||||
}
|
||||
|
||||
bool GLGizmoFlatten::update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector<Transform3d> &trafo_matrices, int &cur_facet)
|
||||
{
|
||||
/*if (m_rr.mouse_position == mouse_position) {
|
||||
return false;
|
||||
}*/
|
||||
|
||||
Vec3f normal = Vec3f::Zero();
|
||||
Vec3f hit = Vec3f::Zero();
|
||||
Vec3f closest_hit = Vec3f::Zero();
|
||||
Vec3f closest_nromal = Vec3f::Zero();
|
||||
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||
int closest_hit_mesh_id = -1;
|
||||
size_t facet = 0;
|
||||
// Cast a ray on all meshes, pick the closest hit and save it for the respective mesh
|
||||
for (int mesh_id = 0; mesh_id < int(trafo_matrices.size()); ++mesh_id) {
|
||||
if (m_c->raycaster()->raycasters()[mesh_id]->unproject_on_mesh(mouse_position, trafo_matrices[mesh_id], camera, hit, normal, m_c->object_clipper()->get_clipping_plane(),
|
||||
&facet)) {
|
||||
// In case this hit is clipped, skip it.
|
||||
//if (is_mesh_point_clipped(hit.cast<double>(), trafo_matrices[mesh_id])) continue;
|
||||
|
||||
double hit_squared_distance = (camera.get_position() - trafo_matrices[mesh_id] * hit.cast<double>()).squaredNorm();
|
||||
if (hit_squared_distance < closest_hit_squared_distance) {
|
||||
closest_hit_squared_distance = hit_squared_distance;
|
||||
closest_hit_mesh_id = mesh_id;
|
||||
closest_hit = hit;
|
||||
closest_nromal = normal;
|
||||
if (m_faltten_type == FlattenType::Triangle) {
|
||||
auto mo = m_c->selection_info()->model_object();
|
||||
auto mv = mo->volumes[mesh_id];
|
||||
m_hit_object_normal = mv->get_matrix().cast<float>() * closest_nromal;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (closest_hit_mesh_id >= 0) {
|
||||
m_rr = {mouse_position, closest_hit_mesh_id, closest_hit, closest_nromal}; // update_raycast_cache berfor click down
|
||||
cur_facet = (int)facet;
|
||||
return true;
|
||||
}
|
||||
cur_facet = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
void GLGizmoFlatten::on_render()
|
||||
{
|
||||
const auto& p_flat_shader = wxGetApp().get_shader("flat");
|
||||
|
@ -105,21 +178,66 @@ void GLGizmoFlatten::on_render()
|
|||
|
||||
glsafe(::glEnable(GL_DEPTH_TEST));
|
||||
glsafe(::glEnable(GL_BLEND));
|
||||
|
||||
wxGetApp().bind_shader(p_flat_shader);
|
||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||
p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
if (selection.is_single_full_instance()) {
|
||||
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
||||
const Camera& camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
||||
if (m_faltten_type == FlattenType::Default) {
|
||||
const Transform3d &m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
||||
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
if (this->is_plane_update_necessary())
|
||||
update_planes();
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
p_flat_shader->set_uniform("uniform_color", i == m_hover_id ? GLGizmoBase::FLATTEN_HOVER_COLOR : GLGizmoBase::FLATTEN_COLOR);
|
||||
m_planes[i].vbo.render(p_flat_shader);
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) *
|
||||
m;
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
if (this->is_plane_update_necessary()) update_planes();
|
||||
for (int i = 0; i < (int) m_planes.size(); ++i) {
|
||||
p_flat_shader->set_uniform("uniform_color", i == m_hover_id ? GLGizmoBase::FLATTEN_HOVER_COLOR : GLGizmoBase::FLATTEN_COLOR);
|
||||
m_planes[i].vbo.render(p_flat_shader);
|
||||
}
|
||||
}
|
||||
else {
|
||||
Vec2d mouse_pos = m_parent.get_local_mouse_position();
|
||||
const Camera &camera = wxGetApp().plater()->get_camera();
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix();
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
|
||||
const Selection & selection = m_parent.get_selection();
|
||||
auto mo = get_selected_model_object(m_parent);
|
||||
if (mo) {
|
||||
const ModelInstance * mi = mo->instances[selection.get_instance_idx()];
|
||||
std::vector<Transform3d> trafo_matrices;
|
||||
for (const ModelVolume *mv : mo->volumes) {
|
||||
if (mv->is_model_part())
|
||||
trafo_matrices.emplace_back(mi->get_transformation().get_matrix() * mv->get_matrix());
|
||||
}
|
||||
update_raycast_cache(mouse_pos, camera, trafo_matrices,m_hit_facet);
|
||||
if (m_hit_facet >= 0) {
|
||||
if (m_last_hit_facet != m_hit_facet) {
|
||||
m_last_hit_facet = m_hit_facet;
|
||||
m_one_tri_model.reset();
|
||||
auto mv = mo->volumes[m_rr.mesh_id];
|
||||
auto world_tran = (mo->instances[selection.get_instance_idx()]->get_transformation().get_matrix() * mv->get_matrix()).cast<float>();
|
||||
auto &vertices = mv->mesh().its.vertices;
|
||||
auto &cur_faces = mv->mesh().its.indices;
|
||||
if (m_hit_facet < cur_faces.size()) {
|
||||
auto v0 = world_tran * vertices[cur_faces[m_hit_facet][0]] + m_rr.normal * 0.05;
|
||||
auto v1 = world_tran * vertices[cur_faces[m_hit_facet][1]] + m_rr.normal * 0.05;
|
||||
auto v2 = world_tran * vertices[cur_faces[m_hit_facet][2]] + m_rr.normal * 0.05;
|
||||
indexed_triangle_set temp_its;
|
||||
temp_its.indices.push_back({0, 1, 2});
|
||||
temp_its.vertices.push_back(v0);
|
||||
temp_its.vertices.push_back(v1);
|
||||
temp_its.vertices.push_back(v2);
|
||||
m_one_tri_model.init_from(temp_its);
|
||||
}
|
||||
}
|
||||
if (m_one_tri_model.is_initialized()) {
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
m_one_tri_model.set_color(GLGizmoBase::FLATTEN_HOVER_COLOR);
|
||||
m_one_tri_model.render_geometry();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -142,26 +260,35 @@ void GLGizmoFlatten::on_render_for_picking()
|
|||
glsafe(::glDisable(GL_BLEND));
|
||||
|
||||
wxGetApp().bind_shader(p_flat_shader);
|
||||
|
||||
const Camera &camera = wxGetApp().plater()->get_picking_camera();
|
||||
p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
if (selection.is_single_full_instance() && !wxGetKeyState(WXK_CONTROL)) {
|
||||
const Transform3d& m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
||||
const Camera& camera = wxGetApp().plater()->get_picking_camera();
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) * m;
|
||||
if (m_faltten_type == FlattenType::Default) {
|
||||
const Transform3d &m = selection.get_volume(*selection.get_volume_idxs().begin())->get_instance_transformation().get_matrix();
|
||||
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
p_flat_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
|
||||
if (this->is_plane_update_necessary())
|
||||
update_planes();
|
||||
for (int i = 0; i < (int)m_planes.size(); ++i) {
|
||||
p_flat_shader->set_uniform("uniform_color", picking_color_component(i));
|
||||
m_planes[i].vbo.render(p_flat_shader);
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix() *
|
||||
Geometry::assemble_transform(selection.get_volume(*selection.get_volume_idxs().begin())->get_sla_shift_z() * Vec3d::UnitZ()) *
|
||||
m;
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
|
||||
if (this->is_plane_update_necessary()) update_planes();
|
||||
for (int i = 0; i < (int) m_planes.size(); ++i) {
|
||||
p_flat_shader->set_uniform("uniform_color", picking_color_component(i));
|
||||
m_planes[i].vbo.render(p_flat_shader);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (m_one_tri_model.is_initialized()) {
|
||||
glsafe(::glDisable(GL_CULL_FACE));
|
||||
const Transform3d view_model_matrix = camera.get_view_matrix();
|
||||
p_flat_shader->set_uniform("view_model_matrix", view_model_matrix);
|
||||
m_one_tri_model.set_color(picking_color_component(0));
|
||||
m_one_tri_model.render_geometry();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
wxGetApp().unbind_shader();
|
||||
|
||||
|
||||
glsafe(::glEnable(GL_CULL_FACE));
|
||||
}
|
||||
|
||||
|
@ -374,7 +501,7 @@ void GLGizmoFlatten::update_planes()
|
|||
planes.pop_back();
|
||||
}
|
||||
};
|
||||
const int plane_count = 20;
|
||||
const int plane_count = 30;
|
||||
for (size_t i = 0; i < m_planes.size(); i++) {
|
||||
if (m_planes[i].area < experted_minimal_area) {
|
||||
if (i + 1 >= plane_count) {
|
||||
|
|
|
@ -3,16 +3,12 @@
|
|||
|
||||
#include "GLGizmoBase.hpp"
|
||||
#include "slic3r/GUI/3DScene.hpp"
|
||||
|
||||
#include "libslic3r/Model.hpp"
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
enum class ModelVolumeType : int;
|
||||
|
||||
|
||||
namespace GUI {
|
||||
|
||||
|
||||
class GLGizmoFlatten : public GLGizmoBase
|
||||
{
|
||||
// This gizmo does not use grabbers. The m_hover_id relates to polygon managed by the class itself.
|
||||
|
@ -42,6 +38,12 @@ private:
|
|||
void update_planes();
|
||||
bool is_plane_update_necessary() const;
|
||||
|
||||
enum FlattenType {
|
||||
Default,
|
||||
Triangle,
|
||||
};
|
||||
FlattenType m_faltten_type{FlattenType::Default};
|
||||
|
||||
public:
|
||||
GLGizmoFlatten(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||
|
||||
|
@ -61,6 +63,14 @@ protected:
|
|||
virtual void on_render_input_window(float x, float y, float bottom_limit) override;
|
||||
private:
|
||||
bool m_show_warning{false};
|
||||
mutable RaycastResult m_rr;
|
||||
mutable int m_hit_facet;
|
||||
mutable int m_last_hit_facet;
|
||||
mutable GLModel m_one_tri_model;
|
||||
Vec3f m_hit_object_normal;
|
||||
|
||||
private:
|
||||
bool update_raycast_cache(const Vec2d &mouse_position, const Camera &camera, const std::vector<Transform3d> &trafo_matrices, int &facet);
|
||||
};
|
||||
|
||||
} // namespace GUI
|
||||
|
|
|
@ -1411,16 +1411,11 @@ void Selection::flattening_rotate(const Vec3d& normal)
|
|||
for (unsigned int i : m_list) {
|
||||
GLVolume& v = *(*m_volumes)[i];
|
||||
// Normal transformed from the object coordinate space to the world coordinate space.
|
||||
const auto &voldata = m_cache.volumes_data[i];
|
||||
Vec3d tnormal = (Geometry::assemble_transform(
|
||||
Vec3d::Zero(), voldata.get_instance_rotation(),
|
||||
voldata.get_instance_scaling_factor().cwiseInverse(), voldata.get_instance_mirror()) * normal).normalized();
|
||||
const Geometry::Transformation &old_inst_trafo = v.get_instance_transformation();
|
||||
const Vec3d tnormal = old_inst_trafo.get_matrix_no_offset() * normal;
|
||||
// Additional rotation to align tnormal with the down vector in the world coordinate space.
|
||||
auto extra_rotation = Eigen::Quaterniond().setFromTwoVectors(tnormal, - Vec3d::UnitZ());
|
||||
v.set_instance_rotation(Geometry::extract_euler_angles(extra_rotation.toRotationMatrix() * m_cache.volumes_data[i].get_instance_rotation_matrix()));
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "flattening_rotate " << (*m_volumes)[i]->name << std::fixed << std::setprecision(4) << ": tnormal=" << tnormal.transpose() << "; extra_rotation=" << Geometry::extract_euler_angles(extra_rotation.toRotationMatrix()).transpose();
|
||||
flush_logs();
|
||||
const Transform3d rotation_matrix = Transform3d(Eigen::Quaterniond().setFromTwoVectors(tnormal, -Vec3d::UnitZ()));
|
||||
v.set_instance_transformation(old_inst_trafo.get_offset_matrix() * rotation_matrix * old_inst_trafo.get_matrix_no_offset());
|
||||
}
|
||||
|
||||
#if !DISABLE_INSTANCES_SYNCH
|
||||
|
|
|
@ -616,7 +616,7 @@ void SyncAmsInfoDialog::add_two_image_control()
|
|||
void SyncAmsInfoDialog::to_next_plate(wxCommandEvent &event) {
|
||||
auto cobox_idx = m_combobox_plate->GetSelection();
|
||||
cobox_idx++;
|
||||
if (cobox_idx >= m_combobox_plate->GetCount()) {
|
||||
if (cobox_idx >= (int)m_combobox_plate->GetCount()) {
|
||||
return;
|
||||
}
|
||||
m_combobox_plate->SetSelection(cobox_idx);
|
||||
|
|
Loading…
Reference in New Issue