WIP Cut: Fixed transformation of a cut plane and a clipper.

+ Fixed a picking of the scaled grabbers
+ Code refactoring
This commit is contained in:
YuSanka 2022-09-19 17:53:01 +02:00
parent 75f3d1bddb
commit e93ff4d087
2 changed files with 355 additions and 352 deletions

View File

@ -4,11 +4,6 @@
#include <GL/glew.h>
#include <wx/button.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
#include <wx/sizer.h>
#include <algorithm>
#include "slic3r/GUI/GUI_App.hpp"
@ -16,7 +11,6 @@
#include "slic3r/GUI/GUI_ObjectManipulation.hpp"
#include "slic3r/Utils/UndoRedo.hpp"
#include "libslic3r/AppConfig.hpp"
#include "libslic3r/Model.hpp"
#include "libslic3r/TriangleMeshSlicer.hpp"
#include "imgui/imgui_internal.h"
@ -34,6 +28,8 @@ const unsigned int ScaleLongEvery = 2;
const float ScaleLongTooth = 0.1f; // in percent of radius
const unsigned int SnapRegionsCount = 8;
using namespace Geometry;
// Generates mesh for a line
static GLModel::Geometry its_make_line(Vec3f beg_pos, Vec3f end_pos)
{
@ -51,6 +47,26 @@ static GLModel::Geometry its_make_line(Vec3f beg_pos, Vec3f end_pos)
return init_data;
}
// Generates mesh for a square plane
static GLModel::Geometry its_make_square_plane(float radius)
{
GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
init_data.reserve_vertices(4);
init_data.reserve_indices(6);
// vertices
init_data.add_vertex(Vec3f(-radius, -radius, 0.0));
init_data.add_vertex(Vec3f(radius , -radius, 0.0));
init_data.add_vertex(Vec3f(radius , radius , 0.0));
init_data.add_vertex(Vec3f(-radius, radius , 0.0));
// indices
init_data.add_triangle(0, 1, 2);
init_data.add_triangle(2, 3, 0);
return init_data;
}
//! -- #ysFIXME those functions bodies are ported from GizmoRotation
// Generates mesh for a circle
static void init_from_circle(GLModel& model, double radius)
@ -63,7 +79,7 @@ static void init_from_circle(GLModel& model, double radius)
// vertices + indices
for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * ScaleStepRad);
init_data.add_vertex(Vec3f(::cos(angle) * radius, ::sin(angle) * radius, 0.0f));
init_data.add_vertex(Vec3f(::cos(angle) * float(radius), ::sin(angle) * float(radius), 0.0f));
init_data.add_index(i);
}
@ -74,8 +90,8 @@ static void init_from_circle(GLModel& model, double radius)
// Generates mesh for a scale
static void init_from_scale(GLModel& model, double radius)
{
const float out_radius_long = radius * (1.0f + ScaleLongTooth);
const float out_radius_short = radius * (1.0f + 0.5f * ScaleLongTooth);
const float out_radius_long = float(radius) * (1.0f + ScaleLongTooth);
const float out_radius_short = float(radius) * (1.0f + 0.5f * ScaleLongTooth);
GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Lines, GLModel::Geometry::EVertexLayout::P3 };
@ -87,8 +103,8 @@ static void init_from_scale(GLModel& model, double radius)
const float angle = float(i * ScaleStepRad);
const float cosa = ::cos(angle);
const float sina = ::sin(angle);
const float in_x = cosa * radius;
const float in_y = sina * radius;
const float in_x = cosa * float(radius);
const float in_y = sina * float(radius);
const float out_x = (i % ScaleLongEvery == 0) ? cosa * out_radius_long : cosa * out_radius_short;
const float out_y = (i % ScaleLongEvery == 0) ? sina * out_radius_long : sina * out_radius_short;
@ -108,7 +124,7 @@ static void init_from_scale(GLModel& model, double radius)
static void init_from_snap_radii(GLModel& model, double radius)
{
const float step = 2.0f * float(PI) / float(SnapRegionsCount);
const float in_radius = radius / 3.0f;
const float in_radius = float(radius) / 3.0f;
const float out_radius = 2.0f * in_radius;
GLModel::Geometry init_data;
@ -118,7 +134,7 @@ static void init_from_snap_radii(GLModel& model, double radius)
// vertices + indices
for (unsigned int i = 0; i < ScaleStepsCount; ++i) {
const float angle = float(i * step);
const float angle = float(i) * step;
const float cosa = ::cos(angle);
const float sina = ::sin(angle);
const float in_x = cosa * in_radius;
@ -144,7 +160,7 @@ static void init_from_angle_arc(GLModel& model, double angle, double radius)
model.reset();
const float step_angle = float(angle) / float(AngleResolution);
const float ex_radius = radius;
const float ex_radius = float(radius);
GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::LineStrip, GLModel::Geometry::EVertexLayout::P3 };
@ -165,11 +181,10 @@ static void init_from_angle_arc(GLModel& model, double angle, double radius)
GLGizmoCut3D::GLGizmoCut3D(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: GLGizmoBase(parent, icon_filename, sprite_id)
, m_connectors_group_id (3)
, m_connector_type (CutConnectorType::Plug)
, m_connector_style (size_t(CutConnectorStyle::Prizm))
, m_connector_shape_id (size_t(CutConnectorShape::Circle))
, m_rotation_matrix(Slic3r::Matrix3d::Identity())
, m_connectors_group_id (3)
{
m_modes = { _u8L("Planar")//, _u8L("Grid")
// , _u8L("Radial"), _u8L("Modular")
@ -212,8 +227,7 @@ std::string GLGizmoCut3D::get_tooltip() const
}
if (tooltip.empty() && (m_hover_id == X || m_hover_id == Y)) {
std::string axis = m_hover_id == X ? "X" : "Y";
// return axis + ": " + format(float(Geometry::rad2deg(Geometry::Transformation(m_rotation_m).get_rotation()[m_hover_id])), 1) + _u8L("°");
return axis + ": " + format(float(Geometry::rad2deg(m_angle)), 1) + _u8L("°");
return axis + ": " + format(float(rad2deg(m_angle)), 1) + _u8L("°");
}
return tooltip;
@ -310,18 +324,9 @@ void GLGizmoCut3D::shift_cut_z(double delta)
set_center(new_cut_center);
}
void GLGizmoCut3D::rotate_vec3d_around_center(Vec3d& vec, const Vec3d& angles, const Vec3d& center)
void GLGizmoCut3D::rotate_vec3d_around_plane_center(Vec3d&vec)
{
if (m_rotations != angles) {
m_rotation_matrix = Eigen::AngleAxisd(angles[Z], Vec3d::UnitZ())
* Eigen::AngleAxisd(angles[Y], Vec3d::UnitY())
* Eigen::AngleAxisd(angles[X], Vec3d::UnitX());
m_rotations = angles;
}
vec -= center;
vec = m_rotation_matrix * vec;
vec += center;
vec = Transformation( assemble_transform(m_plane_center) * m_rotation_m * assemble_transform(-m_plane_center)).get_matrix() * vec;
}
void GLGizmoCut3D::put_connetors_on_cut_plane(const Vec3d& cp_normal, double cp_offset)
@ -345,17 +350,14 @@ void GLGizmoCut3D::put_connetors_on_cut_plane(const Vec3d& cp_normal, double cp_
void GLGizmoCut3D::update_clipper()
{
const Vec3d angles = Geometry::Transformation(m_rotation_m).get_rotation();
BoundingBoxf3 box = bounding_box();
double radius = box.radius();
Vec3d beg, end = beg = m_plane_center;
beg[Z] = box.center().z() - radius;//box.min.z();
end[Z] = box.center().z() + radius;//box.max.z();
beg[Z] = box.center().z() - m_radius;
end[Z] = box.center().z() + m_radius;
rotate_vec3d_around_center(beg, angles, m_plane_center);
rotate_vec3d_around_center(end, angles, m_plane_center);
rotate_vec3d_around_plane_center(beg);
rotate_vec3d_around_plane_center(end);
double dist = (m_plane_center - beg).norm();
@ -460,20 +462,20 @@ bool GLGizmoCut3D::render_slider_double_input(const std::string& label, double&
float value = (float)value_in;
if (m_imperial_units)
value *= ObjectManipulation::mm_to_in;
value *= float(ObjectManipulation::mm_to_in);
float old_val = value;
const BoundingBoxf3 bbox = bounding_box();
float mean_size = float((bbox.size().x() + bbox.size().y() + bbox.size().z()) / 9.0);
float min_size = 1.f;
if (m_imperial_units) {
mean_size *= ObjectManipulation::mm_to_in;
min_size *= ObjectManipulation::mm_to_in;
mean_size *= float(ObjectManipulation::mm_to_in);
min_size *= float(ObjectManipulation::mm_to_in);
}
std::string format = m_imperial_units ? "%.4f " + _u8L("in") : "%.2f " + _u8L("mm");
m_imgui->slider_float(("##" + label).c_str(), &value, min_size, mean_size, format.c_str());
value_in = (double)(value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0));
value_in = (double)(value) * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0);
ImGui::SameLine(m_label_width + m_control_width + 3);
ImGui::PushItemWidth(m_control_width * 0.3f);
@ -490,13 +492,13 @@ void GLGizmoCut3D::render_move_center_input(int axis)
ImGui::AlignTextToFramePadding();
m_imgui->text(m_axis_names[axis]+":");
ImGui::SameLine();
ImGui::PushItemWidth(0.3*m_control_width);
ImGui::PushItemWidth(0.3f*m_control_width);
Vec3d move = m_plane_center;
double in_val, value = in_val = move[axis];
if (m_imperial_units)
value *= ObjectManipulation::mm_to_in;
ImGui::InputDouble(("##move_" + m_axis_names[axis]).c_str(), &value, 0.0f, 0.0f, "%.2f", ImGuiInputTextFlags_CharsDecimal);
ImGui::InputDouble(("##move_" + m_axis_names[axis]).c_str(), &value, 0.0, 0.0, "%.2f", ImGuiInputTextFlags_CharsDecimal);
ImGui::SameLine();
double val = value * (m_imperial_units ? ObjectManipulation::in_to_mm : 1.0);
@ -570,36 +572,11 @@ void GLGizmoCut3D::render_cut_plane()
shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(
m_plane_center,
Geometry::Transformation(m_rotation_m).get_rotation(),
Vec3d::Ones(),
Vec3d::Ones()
);
const Transform3d view_model_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
if (!m_plane.is_initialized()) {
GLModel::Geometry init_data;
init_data.format = { GLModel::Geometry::EPrimitiveType::Triangles, GLModel::Geometry::EVertexLayout::P3 };
// init_data.color = { 0.8f, 0.8f, 0.8f, 0.5f };
init_data.reserve_vertices(4);
init_data.reserve_indices(6);
// vertices
float radius = (float)bounding_box().radius();
init_data.add_vertex(Vec3f(-radius, -radius, 0.0));
init_data.add_vertex(Vec3f( radius, -radius, 0.0));
init_data.add_vertex(Vec3f( radius, radius, 0.0));
init_data.add_vertex(Vec3f(-radius, radius, 0.0));
// indices
init_data.add_triangle(0, 1, 2);
init_data.add_triangle(2, 3, 0);
m_plane.init_from(std::move(init_data));
}
if (can_perform_cut())
m_plane.set_color({ 0.8f, 0.8f, 0.8f, 0.5f });
else
@ -612,7 +589,12 @@ void GLGizmoCut3D::render_cut_plane()
shader->stop_using();
}
void GLGizmoCut3D::render_cut_center_graber()
static float get_grabber_mean_size(const BoundingBoxf3& bb)
{
return float((bb.size().x() + bb.size().y() + bb.size().z()) / 3.0);
}
void GLGizmoCut3D::render_cut_center_grabber()
{
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
@ -623,12 +605,12 @@ void GLGizmoCut3D::render_cut_center_graber()
ColorRGBA color = m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR;
const Camera& camera = wxGetApp().plater()->get_camera();
const Grabber& graber = m_grabbers.front();
const Grabber& grabber = m_grabbers.front();
const BoundingBoxf3 box = bounding_box();
const double mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 3.0);
double size = m_dragging && m_hover_id == Z ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
const float mean_size = get_grabber_mean_size(box);
double size = m_dragging && m_hover_id == Z ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
Vec3d cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
Vec3d offset = 1.25 * size * Vec3d::UnitZ();
@ -637,7 +619,7 @@ void GLGizmoCut3D::render_cut_center_graber()
shader->set_uniform("emission_factor", 0.1f);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const Transform3d view_matrix = camera.get_view_matrix() * Geometry::translation_transform(m_plane_center) * m_rotation_m;
const Transform3d view_matrix = camera.get_view_matrix() * translation_transform(m_plane_center) * m_rotation_m;
auto render = [shader, this](GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix) {
shader->set_uniform("view_model_matrix", view_model_matrix);
@ -657,7 +639,7 @@ void GLGizmoCut3D::render_cut_center_graber()
line_shader->set_uniform("emission_factor", 0.1f);
line_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
const Transform3d trafo = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(1.0, 1.0, m_grabber_connection_len));
const Transform3d trafo = view_matrix * assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(1.0, 1.0, m_grabber_connection_len));
line_shader->set_uniform("view_model_matrix", trafo);
line_shader->set_uniform("normal_matrix", (Matrix3d)trafo.matrix().block(0, 0, 3, 3).inverse().transpose());
line_shader->set_uniform("width", 0.2f);
@ -674,9 +656,9 @@ void GLGizmoCut3D::render_cut_center_graber()
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform(m_plane_center) * m_start_dragging_m;
if (axis == X)
view_model_matrix = view_model_matrix * Geometry::rotation_transform(0.5 * PI * Vec3d::UnitY()) * Geometry::rotation_transform(-PI * Vec3d::UnitZ());
view_model_matrix = view_model_matrix * rotation_transform( 0.5 * PI * Vec3d::UnitY()) * rotation_transform(-PI * Vec3d::UnitZ());
else
view_model_matrix = view_model_matrix * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitY());
view_model_matrix = view_model_matrix * rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * rotation_transform(-0.5 * PI * Vec3d::UnitY());
shader->stop_using();
@ -710,33 +692,33 @@ void GLGizmoCut3D::render_cut_center_graber()
if ((!m_dragging && m_hover_id < 0))
render_grabber_connection(color);
render(m_sphere.model, color, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), size * Vec3d::Ones()));
render(m_sphere.model, color, view_matrix * assemble_transform(Vec3d::Zero(), Vec3d::Zero(), size * Vec3d::Ones()));
if (!m_dragging && m_hover_id < 0 || m_hover_id == Z)
{
const BoundingBoxf3 tbb = transformed_bounding_box();
if (tbb.min.z() <= 0.0)
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
if (tbb.max.z() >= 0.0)
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, Vec3d::Zero(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(offset, Vec3d::Zero(), cone_scale));
}
// render top sphere for X/Y grabbers
if ((!m_dragging && m_hover_id < 0) || m_hover_id == X || m_hover_id == Y)
{
size = m_dragging ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
size = m_dragging ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) :
m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::GRAY();
render(m_sphere.model, color, view_matrix * Geometry::assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
render(m_sphere.model, color, view_matrix * assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
}
// render X grabber
if ((!m_dragging && m_hover_id < 0) || m_hover_id == X)
{
size = m_dragging && m_hover_id == X ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
size = m_dragging && m_hover_id == X ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
@ -746,16 +728,16 @@ void GLGizmoCut3D::render_cut_center_graber()
}
offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
}
// render Y grabber
if ((!m_dragging && m_hover_id < 0) || m_hover_id == Y)
{
size = m_dragging && m_hover_id == Y ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
size = m_dragging && m_hover_id == Y ? double(grabber.get_dragging_half_size(mean_size)) : double(grabber.get_half_size(mean_size));
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
@ -765,9 +747,9 @@ void GLGizmoCut3D::render_cut_center_graber()
}
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
render(m_cone.model, color, view_matrix * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
}
shader->stop_using();
@ -826,7 +808,7 @@ void GLGizmoCut3D::on_load(cereal::BinaryInputArchive& ar)
m_ar_plane_center, m_ar_rotations);
set_center_pos(m_ar_plane_center, true);
m_rotation_m = Geometry::rotation_transform(m_ar_rotations);
m_rotation_m = rotation_transform(m_ar_rotations);
force_update_clipper_on_render = true;
@ -852,7 +834,7 @@ void GLGizmoCut3D::on_set_state()
// initiate archived values
m_ar_plane_center = m_plane_center;
m_ar_rotations = Geometry::Transformation(m_rotation_m).get_rotation();
m_ar_rotations = Transformation(m_rotation_m).get_rotation();
m_parent.request_extra_frame();
}
@ -872,7 +854,7 @@ void GLGizmoCut3D::on_register_raycasters_for_picking()
if (m_connectors_editing) {
if (CommonGizmosDataObjects::SelectionInfo* si = m_c->selection_info()) {
const CutConnectors& connectors = si->model_object()->cut_connectors;
for (size_t i = 0; i < connectors.size(); ++i)
for (int i = 0; i < int(connectors.size()); ++i)
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, i + m_connectors_group_id, *(m_shapes[connectors[i].attribs]).mesh_raycaster, Transform3d::Identity()));
}
}
@ -952,36 +934,36 @@ void GLGizmoCut3D::update_raycasters_for_picking_transform()
}
pos[Z] += sla_shift;
m_raycasters[i]->set_transform(Geometry::assemble_transform(
m_raycasters[i]->set_transform(assemble_transform(
pos,
Geometry::Transformation(m_rotation_m).get_rotation(),
Transformation(m_rotation_m).get_rotation(),
Vec3d(connector.radius, connector.radius, height)
));
}
}
else {
const Transform3d trafo = Geometry::translation_transform(m_plane_center) * m_rotation_m;
const Transform3d trafo = translation_transform(m_plane_center) * m_rotation_m;
const BoundingBoxf3 box = bounding_box();
const double mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 6.0);
const float mean_size = get_grabber_mean_size(box);
double size = double(m_grabbers.front().get_half_size(mean_size));
Vec3d scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
Vec3d offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
m_raycasters[0]->set_transform(trafo * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), scale));
m_raycasters[0]->set_transform(trafo * assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), scale));
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
m_raycasters[1]->set_transform(trafo * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), scale));
m_raycasters[1]->set_transform(trafo * assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), scale));
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
m_raycasters[2]->set_transform(trafo * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), scale));
m_raycasters[2]->set_transform(trafo * assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), scale));
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
m_raycasters[3]->set_transform(trafo * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), scale));
m_raycasters[3]->set_transform(trafo * assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), scale));
offset = 1.25 * size * Vec3d::UnitZ();
m_raycasters[4]->set_transform(trafo * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), size * Vec3d::Ones()));
m_raycasters[5]->set_transform(trafo * Geometry::assemble_transform(-offset, PI * Vec3d::UnitX(), scale));
m_raycasters[6]->set_transform(trafo * Geometry::assemble_transform(offset, Vec3d::Zero(), scale));
m_raycasters[4]->set_transform(trafo * assemble_transform(Vec3d::Zero(), Vec3d::Zero(), size * Vec3d::Ones()));
m_raycasters[5]->set_transform(trafo * assemble_transform(-offset, PI * Vec3d::UnitX(), scale));
m_raycasters[6]->set_transform(trafo * assemble_transform(offset, Vec3d::Zero(), scale));
}
}
@ -1039,7 +1021,7 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
if (m_hover_id == Z) {
Vec3d starting_box_center = m_plane_center - Vec3d::UnitZ();// some Margin
rotate_vec3d_around_center(starting_box_center, Geometry::Transformation(m_rotation_m).get_rotation(), m_plane_center);
rotate_vec3d_around_plane_center(starting_box_center);
const Vec3d& starting_drag_position = m_plane_center;
double projection = 0.0;
@ -1103,7 +1085,7 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
theta += 0.5 * PI;
rotation[m_hover_id] = theta;
m_rotation_m = m_start_dragging_m * Geometry::rotation_transform(rotation);
m_rotation_m = m_start_dragging_m * rotation_transform(rotation);
m_angle = theta;
while (m_angle > two_pi)
@ -1141,7 +1123,7 @@ void GLGizmoCut3D::on_stop_dragging()
m_angle_arc.reset();
m_angle = 0.0;
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Rotate cut plane"), UndoRedo::SnapshotType::GizmoAction);
m_ar_rotations = Geometry::Transformation(m_rotation_m).get_rotation();
m_ar_rotations = Transformation(m_rotation_m).get_rotation();
m_start_dragging_m = m_rotation_m;
}
@ -1190,8 +1172,8 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(bool revert_move /*= false*
Vec3d cut_center_offset = m_plane_center - instance_offset;
cut_center_offset[Z] -= m_c->selection_info()->get_sla_shift();
const auto move = Geometry::assemble_transform(-cut_center_offset);
const auto move2 = Geometry::assemble_transform(m_plane_center);
const auto move = assemble_transform(-cut_center_offset);
const auto move2 = assemble_transform(m_plane_center);
const auto cut_matrix = (revert_move ? move2 : Transform3d::Identity()) * m_rotation_m.inverse() * move;
@ -1202,17 +1184,16 @@ BoundingBoxf3 GLGizmoCut3D::transformed_bounding_box(bool revert_move /*= false*
// respect just to the solid parts for FFF and ignore pad and supports for SLA
if (!volume->is_modifier && !volume->is_sla_pad() && !volume->is_sla_support()) {
const auto instance_matrix = Geometry::assemble_transform(
const auto instance_matrix = assemble_transform(
Vec3d::Zero(), // don't apply offset
volume->get_instance_rotation().cwiseProduct(Vec3d(1.0, 1.0, 1.0)),
volume->get_instance_scaling_factor(),
volume->get_instance_mirror()
);
auto volume_travo = instance_matrix * volume->get_volume_transformation().get_matrix();
auto volume_offset = Geometry::Transformation(volume_travo).get_offset();
auto volume_trafo = instance_matrix * volume->get_volume_transformation().get_matrix();
ret.merge(volume->transformed_convex_hull_bounding_box(cut_matrix * volume_travo));
ret.merge(volume->transformed_convex_hull_bounding_box(cut_matrix * volume_trafo));
}
}
return ret;
@ -1274,15 +1255,8 @@ void GLGizmoCut3D::init_picking_models()
}
}
void GLGizmoCut3D::on_render()
void GLGizmoCut3D::init_rendering_items()
{
if (update_bb() || force_update_clipper_on_render) {
update_clipper_on_render();
m_c->object_clipper()->set_behavior(m_connectors_editing, m_connectors_editing, 0.4f);
}
init_picking_models();
if (!m_grabber_connection.is_initialized())
m_grabber_connection.init_from(its_make_line(Vec3f::Zero(), Vec3f::UnitZ()));
if (!m_circle.is_initialized())
@ -1298,6 +1272,21 @@ void GLGizmoCut3D::on_render()
if (!m_angle_arc.is_initialized() || m_angle != 0.0)
init_from_angle_arc(m_angle_arc, m_angle, m_grabber_connection_len);
if (!m_plane.is_initialized() && !m_hide_cut_plane && !m_connectors_editing)
m_plane.init_from(its_make_square_plane(float(m_radius)));
}
void GLGizmoCut3D::on_render()
{
if (update_bb() || force_update_clipper_on_render) {
update_clipper_on_render();
m_c->object_clipper()->set_behavior(m_connectors_editing, m_connectors_editing, 0.4f);
}
init_picking_models();
init_rendering_items();
render_connectors();
if (! m_connectors_editing)
@ -1308,27 +1297,41 @@ void GLGizmoCut3D::on_render()
if (!m_hide_cut_plane && !m_connectors_editing) {
render_cut_plane();
render_cut_center_graber();
render_cut_center_grabber();
}
render_cut_line();
}
void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
void GLGizmoCut3D::render_debug_block()
{
m_imgui->begin(wxString("DEBUG"));
static bool hide_clipped = false;
static bool fill_cut = false;
static float contour_width = 0.4f;
m_imgui->checkbox(_L("Hide cut plane and grabbers"), m_hide_cut_plane);
if (m_imgui->checkbox("hide_clipped", hide_clipped) && !hide_clipped)
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
m_imgui->checkbox("fill_cut", fill_cut);
m_imgui->slider_float("contour_width", &contour_width, 0.f, 3.f);
if (auto oc = m_c->object_clipper())
oc->set_behavior(hide_clipped || m_connectors_editing, fill_cut || m_connectors_editing, double(contour_width));
m_imgui->end();
}
void GLGizmoCut3D::adjust_window_position(float x, float y, float bottom_limit)
{
static float last_y = 0.0f;
static float last_h = 0.0f;
m_imgui->begin(_L("Cut"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
m_label_width = m_imgui->get_style_scaling() * 100.0f;
m_control_width = m_imgui->get_style_scaling() * 150.0f;
// adjust window position to avoid overlap the view toolbar
const float win_h = ImGui::GetWindowHeight();
y = std::min(y, bottom_limit - win_h);
ImGui::SetWindowPos(ImVec2(x, y), ImGuiCond_Always);
if (last_h != win_h || last_y != y) {
// ask canvas for another frame to render the window in the correct position
m_imgui->set_requires_extra_frame();
@ -1337,27 +1340,97 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
if (last_y != y)
last_y = y;
}
}
void GLGizmoCut3D::render_connectors_editing(CutConnectors &connectors)
{
// add shortcuts panel
if (m_imgui->button("? " + (m_show_shortcuts ? wxString(ImGui::CollapseBtn) : wxString(ImGui::ExpandBtn))))
m_show_shortcuts = !m_show_shortcuts;
if (m_show_shortcuts)
for (const auto&shortcut : m_shortcuts ){
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, shortcut.first);
ImGui::SameLine(m_label_width);
m_imgui->text(shortcut.second);
}
// Connectors section
ImGui::Separator();
// WIP : Auto : Need to implement
// m_imgui->text(_L("Mode"));
// render_connect_mode_radio_button(CutConnectorMode::Auto);
// render_connect_mode_radio_button(CutConnectorMode::Manual);
ImGui::AlignTextToFramePadding();
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Connectors"));
m_imgui->disabled_begin(connectors.empty());
ImGui::SameLine(m_label_width);
if (m_imgui->button(" " + _L("Reset") + " ##connectors"))
reset_connectors();
m_imgui->disabled_end();
m_imgui->text(_L("Type"));
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
if (type_changed)
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.type = CutConnectorType(m_connector_type);
if (render_combo(_u8L("Style"), m_connector_styles, m_connector_style))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.style = CutConnectorStyle(m_connector_style) ;
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.shape = CutConnectorShape(m_connector_shape_id);
if (render_slider_double_input(_u8L("Depth ratio"), m_connector_depth_ratio, m_connector_depth_ratio_tolerance))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx]) {
auto&connector = connectors[idx];
connector.height = float(m_connector_depth_ratio);
connector.height_tolerance = 0.01f * float(m_connector_depth_ratio_tolerance);
}
if (render_slider_double_input(_u8L("Size"), m_connector_size, m_connector_size_tolerance))
for (size_t idx = 0; idx < m_selected.size(); idx++)
if (m_selected[idx]) {
auto&connector = connectors[idx];
connector.radius = float(m_connector_size * 0.5);
connector.radius_tolerance = 0.01f * float(m_connector_size_tolerance);
}
if (m_imgui->button(_L("Confirm connectors"))) {
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
m_connectors_editing = false;
update_raycasters_for_picking();
std::fill(m_selected.begin(), m_selected.end(), false);
m_selected_count = 0;
}
m_parent.request_extra_frame();
}
void GLGizmoCut3D::render_cut_plane_editing(CutConnectors &connectors)
{
// WIP : cut plane mode
// render_combo(_u8L("Mode"), m_modes, m_mode);
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
bool cut_clicked = false;
bool revert_move{ false };
bool revert_rotation{ false };
bool fff_printer = wxGetApp().plater()->printer_technology() == ptFFF;
if (! m_connectors_editing) {
if (m_mode == size_t(CutMode::cutPlanar)) {
ImGui::AlignTextToFramePadding();
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Hold SHIFT key and connect some two points of an object to cut by line"));
ImGui::Separator();
////////
double koef = m_imperial_units ? ObjectManipulation::mm_to_in : 1.0;
std::string unit_str = m_imperial_units ? _u8L("inch") : _u8L("mm");
const BoundingBoxf3 tbb = transformed_bounding_box();
double top = (tbb.min.z() <= 0.0 ? tbb.max.z() : tbb.size().z()) * koef;
double bottom = (tbb.max.z() <= 0.0 ? tbb.size().z() : (tbb.min.z() * (-1))) * koef;
Vec3d tbb_sz = tbb.size();
wxString size = "X: " + double_to_string(tbb_sz.x() * koef, 2) + unit_str +
@ -1369,20 +1442,16 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
ImGui::SameLine(m_label_width);
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, size);
//static float v = 0.; // TODO: connect to cutting plane position
m_imgui->text(_L("Cut position: "));
render_move_center_input(Z);
//m_imgui->input_double(unit_str, v);
//v = std::clamp(v, 0.f, float(bottom+top));
if (m_imgui->button("Reset cutting plane")) {
set_center(bounding_box().center());
m_rotation_m = Transform3d::Identity();
m_angle_arc.reset();
update_clipper();
}
}
if (m_mode == size_t(CutMode::cutPlanar)) {
ImGui::Separator();
ImGui::AlignTextToFramePadding();
@ -1400,7 +1469,7 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->disabled_begin(!m_keep_upper);
m_imgui->disabled_begin(is_approx(Geometry::Transformation(m_rotation_m).get_rotation().x(), 0.) && is_approx(Geometry::Transformation(m_rotation_m).get_rotation().y(), 0.));
m_imgui->disabled_begin(is_approx(Transformation(m_rotation_m).get_rotation().x(), 0.) && is_approx(Transformation(m_rotation_m).get_rotation().y(), 0.));
if (m_imgui->checkbox(_L("Place on cut") + "##upper", m_place_on_cut_upper))
m_rotate_upper = false;
m_imgui->disabled_end();
@ -1432,9 +1501,7 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
m_imgui->disabled_end();
}
if (fff_printer) {
ImGui::Separator();
if (wxGetApp().plater()->printer_technology() == ptFFF) {
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower);
if (m_imgui->button(_L("Add/Edit connectors"))) {
m_connectors_editing = true;
@ -1442,40 +1509,25 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
}
m_imgui->disabled_end();
}
}
else { // connectors mode
if (m_imgui->button("? " + (m_show_shortcuts ? wxString(ImGui::CollapseBtn) : wxString(ImGui::ExpandBtn))))
m_show_shortcuts = !m_show_shortcuts;
if (m_show_shortcuts)
for (const auto& shortcut : m_shortcuts ){
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, shortcut.first);
ImGui::SameLine(m_label_width);
m_imgui->text(shortcut.second);
}
m_imgui->disabled_begin(!m_keep_lower || !m_keep_upper);
// Connectors section
ImGui::Separator();
ImGui::AlignTextToFramePadding();
m_imgui->text_colored(ImGuiWrapper::COL_ORANGE_LIGHT, _L("Connectors"));
m_imgui->disabled_begin(connectors.empty());
ImGui::SameLine(m_label_width);
if (m_imgui->button(" " + _L("Reset") + " ##connectors"))
reset_connectors();
m_imgui->disabled_begin(!can_perform_cut());
if((m_keep_upper || m_keep_lower) && m_imgui->button(_L("Perform cut")))
perform_cut(m_parent.get_selection());;
m_imgui->disabled_end();
/*
m_imgui->text(_L("Mode"));
render_connect_mode_radio_button(CutConnectorMode::Auto);
render_connect_mode_radio_button(CutConnectorMode::Manual);
*/
}
void GLGizmoCut3D::init_input_window_data(CutConnectors &connectors)
{
m_imperial_units = wxGetApp().app_config->get("use_inches") == "1";
m_label_width = m_imgui->get_style_scaling() * 100.0f;
m_control_width = m_imgui->get_style_scaling() * 150.0f;
if (m_selected_count == 1)
for (size_t idx = 0; idx < m_selected.size(); idx++)
if (m_selected[idx]) {
auto& connector = connectors[idx];
auto&connector = connectors[idx];
m_connector_depth_ratio = connector.height;
m_connector_depth_ratio_tolerance = 100 * connector.height_tolerance;
m_connector_size = 2. * connector.radius;
@ -1486,98 +1538,46 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
break;
}
}
m_imgui->text(_L("Type"));
bool type_changed = render_connect_type_radio_button(CutConnectorType::Plug);
type_changed |= render_connect_type_radio_button(CutConnectorType::Dowel);
if (type_changed)
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.type = CutConnectorType(m_connector_type);
if (render_combo(_u8L("Style"), m_connector_styles, m_connector_style))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.style = CutConnectorStyle(m_connector_style) ;
if (render_combo(_u8L("Shape"), m_connector_shapes, m_connector_shape_id))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx])
connectors[idx].attribs.shape = CutConnectorShape(m_connector_shape_id);
if (render_slider_double_input(_u8L("Depth ratio"), m_connector_depth_ratio, m_connector_depth_ratio_tolerance))
for (size_t idx = 0; idx < m_selected.size() ; idx++)
if (m_selected[idx]) {
auto& connector = connectors[idx];
connector.height = float(m_connector_depth_ratio);
connector.height_tolerance = 0.01f * m_connector_depth_ratio_tolerance;
}
if (render_slider_double_input(_u8L("Size"), m_connector_size, m_connector_size_tolerance))
for (size_t idx = 0; idx < m_selected.size(); idx++)
if (m_selected[idx]) {
auto& connector = connectors[idx];
connector.radius = float(m_connector_size * 0.5);
connector.radius_tolerance = 0.01f * m_connector_size_tolerance;
}
m_imgui->disabled_end();
if (m_imgui->button(_L("Confirm connectors"))) {
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
m_connectors_editing = false;
update_raycasters_for_picking();
std::fill(m_selected.begin(), m_selected.end(), false);
m_selected_count = 0;
}
m_parent.request_extra_frame();
}
ImGui::Separator();
if (fff_printer)
void GLGizmoCut3D::render_input_window_warning() const
{
if (wxGetApp().plater()->printer_technology() == ptFFF)
m_imgui->text(m_has_invalid_connector ? wxString(ImGui::WarningMarkerSmall) + _L("Invalid connectors detected.") : wxString());
if (!m_connectors_editing) {
m_imgui->disabled_begin(!can_perform_cut());
cut_clicked = m_imgui->button(_L("Perform cut"));
m_imgui->disabled_end();
}
if (!m_keep_upper && !m_keep_lower)
m_imgui->text(wxString(ImGui::WarningMarkerSmall) + _L("Invalid state. \nNo one part is selected for keep after cut"));
}
void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
{
m_imgui->begin(_L("Cut"), ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoMove | ImGuiWindowFlags_NoResize | ImGuiWindowFlags_NoCollapse);
// adjust window position to avoid overlap the view toolbar
adjust_window_position(x, y, bottom_limit);
CutConnectors& connectors = m_c->selection_info()->model_object()->cut_connectors;
init_input_window_data(connectors);
if (m_connectors_editing) // connectors mode
render_connectors_editing(connectors);
else
render_cut_plane_editing(connectors);
render_input_window_warning();
m_imgui->end();
////////
m_imgui->begin(wxString("DEBUG"));
static bool hide_clipped = false;
static bool fill_cut = false;
static float contour_width = 0.4f;
m_imgui->checkbox(_L("Hide cut plane and grabbers"), m_hide_cut_plane);
if (m_imgui->checkbox("hide_clipped", hide_clipped) && !hide_clipped)
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
m_imgui->checkbox("fill_cut", fill_cut);
m_imgui->slider_float("contour_width", &contour_width, 0.f, 3.f);
m_c->object_clipper()->set_behavior(hide_clipped || m_connectors_editing, fill_cut || m_connectors_editing, contour_width);
m_imgui->end();
////////
if (cut_clicked && (m_keep_upper || m_keep_lower))
perform_cut(m_parent.get_selection());
if (revert_move)
set_center(bounding_box().center());
if (revert_rotation) {
m_rotation_m = Transform3d::Identity();
m_angle_arc.reset();
update_clipper();
}
render_debug_block();
}
// get volume transformation regarding to the "border". Border is related from the size of connectors
Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) const
{
bool is_prizm_dowel = m_connector_type == CutConnectorType::Dowel && m_connector_style == size_t(CutConnectorStyle::Prizm);
const Transform3d connector_trafo = Geometry::assemble_transform(
const Transform3d connector_trafo = assemble_transform(
is_prizm_dowel ? Vec3d(0.0, 0.0, -m_connector_depth_ratio) : Vec3d::Zero(),
Geometry::Transformation(m_rotation_m).get_rotation(),
Transformation(m_rotation_m).get_rotation(),
Vec3d(0.5*m_connector_size, 0.5*m_connector_size, is_prizm_dowel ? 2 * m_connector_depth_ratio : m_connector_depth_ratio),
Vec3d::Ones());
const Vec3d connector_bb = m_connector_mesh.transformed_bounding_box(connector_trafo).size();
@ -1593,7 +1593,7 @@ Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) c
const Vec3d offset(vol_trans.x() * border_scale.x(), vol_trans.y() * border_scale.y(), vol_trans.z() * border_scale.z());
// scale and translate volume to suppress to put connectors too close to the border
return Geometry::assemble_transform(offset, Vec3d::Zero(), Vec3d::Ones() - border_scale, Vec3d::Ones()) * vol_matrix;
return assemble_transform(offset, Vec3d::Zero(), Vec3d::Ones() - border_scale, Vec3d::Ones()) * vol_matrix;
}
void GLGizmoCut3D::render_connectors()
@ -1636,7 +1636,7 @@ void GLGizmoCut3D::render_connectors()
const ClippingPlane* cp = m_c->object_clipper()->get_clipping_plane();
const Vec3d& normal = cp && cp->is_active() ? cp->get_normal() : m_clp_normal;
const Transform3d instance_trafo = Geometry::assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix();
const Transform3d instance_trafo = assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix();
m_has_invalid_connector = false;
@ -1682,9 +1682,9 @@ void GLGizmoCut3D::render_connectors()
m_shapes[connector.attribs].model.set_color(render_color);
const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(
const Transform3d view_model_matrix = camera.get_view_matrix() * assemble_transform(
pos,
Geometry::Transformation(m_rotation_m).get_rotation(),
Transformation(m_rotation_m).get_rotation(),
Vec3d(connector.radius, connector.radius, height)
);
shader->set_uniform("view_model_matrix", view_model_matrix);
@ -1727,7 +1727,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
if(!mo)
return;
Vec3d rotation = Geometry::Transformation(m_rotation_m).get_rotation();
Vec3d rotation = Transformation(m_rotation_m).get_rotation();
const bool has_connectors = !mo->cut_connectors.empty();
{
@ -1747,7 +1747,7 @@ void GLGizmoCut3D::perform_cut(const Selection& selection)
else {
// culculate shift of the connector center regarding to the position on the cut plane
Vec3d shifted_center = m_plane_center + Vec3d::UnitZ();
rotate_vec3d_around_center(shifted_center, rotation, m_plane_center);
rotate_vec3d_around_plane_center(shifted_center);
Vec3d norm = (shifted_center - m_plane_center).normalized();
connector.pos += norm * (0.5 * connector.height);
}
@ -1781,7 +1781,7 @@ bool GLGizmoCut3D::unproject_on_cut_plane(const Vec2d& mouse_position, std::pair
const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()];
const Transform3d instance_trafo = sla_shift > 0.0 ?
Geometry::assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix() : mi->get_transformation().get_matrix();
assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix() : mi->get_transformation().get_matrix();
const Camera& camera = wxGetApp().plater()->get_camera();
int mesh_id = -1;
@ -1861,8 +1861,8 @@ bool GLGizmoCut3D::process_cut_line(SLAGizmoEventType action, const Vec2d& mouse
const float sla_shift = m_c->selection_info()->get_sla_shift();
const ModelObject* mo = m_c->selection_info()->model_object();
const ModelInstance* mi = mo->instances[m_c->selection_info()->get_active_instance()];
Transform3d inst_trafo = sla_shift > 0.0 ?
Geometry::assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix() :
Transform3d inst_trafo = sla_shift > 0.f ?
assemble_transform(Vec3d(0.0, 0.0, sla_shift)) * mi->get_transformation().get_matrix() :
mi->get_transformation().get_matrix();
const Camera& camera = wxGetApp().plater()->get_camera();
@ -1930,7 +1930,7 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
Plater::TakeSnapshot snapshot(wxGetApp().plater(), _L("Add connector"), UndoRedo::SnapshotType::GizmoAction);
connectors.emplace_back(hit, Geometry::Transformation(m_rotation_m).get_rotation(),
connectors.emplace_back(hit, Transformation(m_rotation_m).get_rotation(),
float(m_connector_size * 0.5), float(m_connector_depth_ratio),
float(0.01f * m_connector_size_tolerance), float(0.01f * m_connector_depth_ratio_tolerance),
CutConnectorAttributes( CutConnectorType(m_connector_type),

View File

@ -2,11 +2,9 @@
#define slic3r_GLGizmoCut_hpp_
#include "GLGizmoBase.hpp"
#include "GLGizmoRotate.hpp"
#include "GLGizmoMove.hpp"
#include "slic3r/GUI/GLModel.hpp"
#include "libslic3r/TriangleMesh.hpp"
#include "libslic3r/ObjectID.hpp"
#include "libslic3r/Model.hpp"
namespace Slic3r {
@ -100,9 +98,6 @@ class GLGizmoCut3D : public GLGizmoBase
bool m_has_invalid_connector{ false };
Matrix3d m_rotation_matrix;
Vec3d m_rotations{ Vec3d::Zero() };
bool m_show_shortcuts{ false };
std::vector<std::pair<wxString, wxString>> m_shortcuts;
@ -150,7 +145,7 @@ public:
bool on_mouse(const wxMouseEvent &mouse_event) override;
void shift_cut_z(double delta);
void rotate_vec3d_around_center(Vec3d& vec, const Vec3d& angles, const Vec3d& center);
void rotate_vec3d_around_plane_center(Vec3d&vec);
void put_connetors_on_cut_plane(const Vec3d& cp_normal, double cp_offset);
void update_clipper();
void update_clipper_on_render();
@ -174,6 +169,13 @@ protected:
void on_stop_dragging() override;
void on_render() override;
void render_debug_block();
void adjust_window_position(float x, float y, float bottom_limit);
void render_connectors_editing(CutConnectors &connectors);
void render_cut_plane_editing(CutConnectors &connectors);
void init_input_window_data(CutConnectors &connectors);
void render_input_window_warning() const;
virtual void on_register_raycasters_for_picking() override;
virtual void on_unregister_raycasters_for_picking() override;
void update_raycasters_for_picking();
@ -204,12 +206,13 @@ private:
void discard_cut_line_processing();
void render_cut_plane();
void render_cut_center_graber();
void render_cut_center_grabber();
void render_cut_line();
void perform_cut(const Selection& selection);
void set_center_pos(const Vec3d& center_pos, bool force = false);
void perform_cut(const Selection&selection);
void set_center_pos(const Vec3d&center_pos, bool force = false);
bool update_bb();
void init_picking_models();
void init_rendering_items();
void reset_connectors();
void update_connector_shape();
void update_model_object();