Cut WIP: Raycasters for picking are applied

+ Added snapping for rotation of the cut plane
This commit is contained in:
YuSanka 2022-08-10 11:25:04 +02:00
parent dda346b70a
commit df8f7e1069
3 changed files with 280 additions and 111 deletions

View File

@ -404,14 +404,14 @@ bool GLGizmoBase::use_grabbers(const wxMouseEvent &mouse_event) {
if (mouse_event.LeftDown()) {
Selection &selection = m_parent.get_selection();
if (!selection.is_empty() && m_hover_id != -1 &&
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))) {
if (!selection.is_empty() && m_hover_id != -1 /* &&
(m_grabbers.empty() || m_hover_id < static_cast<int>(m_grabbers.size()))*/) {
selection.setup_cache();
m_dragging = true;
for (auto &grabber : m_grabbers) grabber.dragging = false;
if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size()))
m_grabbers[m_hover_id].dragging = true;
// if (!m_grabbers.empty() && m_hover_id < int(m_grabbers.size()))
// m_grabbers[m_hover_id].dragging = true;
on_start_dragging();

View File

@ -241,8 +241,14 @@ bool GLGizmoCut3D::on_mouse(const wxMouseEvent &mouse_event)
return false;
if (use_grabbers(mouse_event)) {
if (m_hover_id >= m_connectors_group_id && mouse_event.LeftUp() && !mouse_event.ShiftDown())
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
if (m_hover_id >= m_connectors_group_id) {
if (mouse_event.LeftDown()) {
std::fill(m_selected.begin(), m_selected.end(), false);
m_selected_count = 0;
}
if (mouse_event.LeftUp() && !mouse_event.ShiftDown())
gizmo_event(SLAGizmoEventType::LeftUp, mouse_pos, mouse_event.ShiftDown(), mouse_event.AltDown(), mouse_event.CmdDown());
}
return true;
}
@ -366,6 +372,11 @@ void GLGizmoCut3D::update_clipper()
m_c->object_clipper()->set_range_and_pos(normal, offset, dist);
put_connetors_on_cut_plane(normal, offset);
if (m_raycasters.empty())
on_register_raycasters_for_picking();
else
update_raycasters_for_picking_transform();
}
void GLGizmoCut3D::update_clipper_on_render()
@ -599,21 +610,15 @@ void GLGizmoCut3D::render_cut_plane()
shader->stop_using();
}
void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
void GLGizmoCut3D::render_cut_center_graber()
{
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (!shader)
return;
#if ENABLE_GL_CORE_PROFILE
if (!OpenGLManager::get_gl_info().is_core_profile())
#endif // ENABLE_GL_CORE_PROFILE
glsafe(::glLineWidth(m_hover_id != -1 ? 2.0f : 1.5f));
ColorRGBA color = picking ? picking_decode(BASE_ID - Z) :
m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR;
ColorRGBA color = m_hover_id == Z ? complementary(GRABBER_COLOR) : GRABBER_COLOR;
const Camera& camera = wxGetApp().plater()->get_camera();
const Grabber& graber = m_grabbers.front();
@ -631,7 +636,6 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
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_grabber_connection_matrix = view_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), Vec3d(1.0, 1.0, m_grabber_connection_len));
auto render = [shader, this](GLModel& model, const ColorRGBA& color, Transform3d view_model_matrix) {
shader->set_uniform("view_model_matrix", view_model_matrix);
@ -640,6 +644,29 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
model.render();
};
auto render_grabber_connection = [shader, camera, view_matrix, this](const ColorRGBA& color)
{
shader->stop_using();
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
if (!line_shader)
return;
line_shader->start_using();
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));
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);
m_grabber_connection.set_color(color);
m_grabber_connection.render();
line_shader->stop_using();
shader->start_using();
};
auto render_rotation_snapping = [shader, camera, this](Axis axis, const ColorRGBA& color)
{
Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::translation_transform(m_plane_center) * m_start_dragging_m;
@ -649,33 +676,48 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
else
view_model_matrix = view_model_matrix * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitZ()) * Geometry::rotation_transform(-0.5 * PI * Vec3d::UnitY());
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
shader->stop_using();
GLShaderProgram* line_shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
if (!line_shader)
return;
line_shader->start_using();
line_shader->set_uniform("emission_factor", 0.1f);
line_shader->set_uniform("projection_matrix", camera.get_projection_matrix());
line_shader->set_uniform("view_model_matrix", view_model_matrix);
line_shader->set_uniform("normal_matrix", (Matrix3d)view_model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose());
line_shader->set_uniform("width", 0.25f);
m_circle.render();
m_scale.render();
m_snap_radii.render();
m_reference_radius.render();
if (m_dragging) {
line_shader->set_uniform("width", 1.5f);
m_angle_arc.set_color(color);
m_angle_arc.render();
}
line_shader->stop_using();
shader->start_using();
};
// render Z grabber
if ((!m_dragging && m_hover_id < 0))
render(m_grabber_connection, color, view_grabber_connection_matrix);
render(m_sphere, color, view_matrix * Geometry::assemble_transform(Vec3d::Zero(), Vec3d::Zero(), size * Vec3d::Ones()));
render_grabber_connection(color);
render(m_sphere.model, color, view_matrix * Geometry::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, color, view_matrix * Geometry::assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(-offset, PI * Vec3d::UnitX(), cone_scale));
if (tbb.max.z() >= 0.0)
render(m_cone, color, view_matrix * Geometry::assemble_transform(offset, Vec3d::Zero(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, Vec3d::Zero(), cone_scale));
}
// render top sphere for X/Y grabbers
@ -685,7 +727,7 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
size = m_dragging ? double(graber.get_dragging_half_size(mean_size)) : double(graber.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, color, view_matrix * Geometry::assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
render(m_sphere.model, color, view_matrix * Geometry::assemble_transform(m_grabber_connection_len * Vec3d::UnitZ(), Vec3d::Zero(), size * Vec3d::Ones()));
}
// render X grabber
@ -694,20 +736,17 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
{
size = m_dragging && m_hover_id == X ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
if (picking)
color = picking_decode(BASE_ID - X);
else
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
color = m_hover_id == X ? complementary(ColorRGBA::RED()) : ColorRGBA::RED();
if (m_hover_id == X) {
render(m_grabber_connection, color, view_grabber_connection_matrix);
render_grabber_connection(color);
render_rotation_snapping(X, color);
}
offset = Vec3d(0.0, 1.25 * size, m_grabber_connection_len);
render(m_cone, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitX(), cone_scale));
offset = Vec3d(0.0, -1.25 * size, m_grabber_connection_len);
render(m_cone, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitX(), cone_scale));
}
// render Y grabber
@ -716,20 +755,17 @@ void GLGizmoCut3D::render_cut_center_graber(bool picking /* = false*/)
{
size = m_dragging && m_hover_id == Y ? double(graber.get_dragging_half_size(mean_size)) : double(graber.get_half_size(mean_size));
cone_scale = Vec3d(0.75 * size, 0.75 * size, 1.8 * size);
if (picking)
color = picking_decode(BASE_ID - Y);
else
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
color = m_hover_id == Y ? complementary(ColorRGBA::GREEN()) : ColorRGBA::GREEN();
if (m_hover_id == Y) {
render(m_grabber_connection, color, view_grabber_connection_matrix);
render_grabber_connection(color);
render_rotation_snapping(Y, color);
}
offset = Vec3d(1.25 * size, 0.0, m_grabber_connection_len);
render(m_cone, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, 0.5 * PI * Vec3d::UnitY(), cone_scale));
offset = Vec3d(-1.25 * size, 0.0, m_grabber_connection_len);
render(m_cone, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
render(m_cone.model, color, view_matrix * Geometry::assemble_transform(offset, -0.5 * PI * Vec3d::UnitY(), cone_scale));
}
shader->stop_using();
@ -742,15 +778,15 @@ void GLGizmoCut3D::render_cut_line()
glsafe(::glEnable(GL_DEPTH_TEST));
glsafe(::glClear(GL_DEPTH_BUFFER_BIT));
glsafe(::glLineWidth(2.0f));
GLShaderProgram* shader = wxGetApp().get_shader("flat");
GLShaderProgram* shader = OpenGLManager::get_gl_info().is_core_profile() ? wxGetApp().get_shader("dashed_thick_lines") : wxGetApp().get_shader("flat");
if (shader != nullptr) {
shader->start_using();
const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("view_model_matrix", camera.get_view_matrix());
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
shader->set_uniform("width", 0.25f);
m_cut_line.reset();
m_cut_line.init_from(its_make_line((Vec3f)m_line_beg.cast<float>(), (Vec3f)m_line_end.cast<float>()));
@ -824,24 +860,122 @@ void GLGizmoCut3D::on_set_state()
force_update_clipper_on_render = m_state == On;
}
#if ENABLE_RAYCAST_PICKING
void GLGizmoCut3D::on_register_raycasters_for_picking()
{
// the gizmo grabbers are rendered on top of the scene, so the raytraced picker should take it into account
m_parent.set_raycaster_gizmos_on_top(true);
assert(m_raycasters.empty());
set_volumes_picking_state(false);
init_picking_models();
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)
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()));
}
}
else {
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, X, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Y, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Y, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_sphere.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_cone.mesh_raycaster, Transform3d::Identity()));
m_raycasters.emplace_back(m_parent.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, Z, *m_cone.mesh_raycaster, Transform3d::Identity()));
}
update_raycasters_for_picking_transform();
}
void GLGizmoCut3D::on_unregister_raycasters_for_picking()
{
m_parent.set_raycaster_gizmos_on_top(false);
m_parent.remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo);
m_raycasters.clear();
set_volumes_picking_state(true);
}
#else
void GLGizmoCut3D::on_render_for_picking()
void GLGizmoCut3D::set_volumes_picking_state(bool state)
{
render_cut_center_graber(true);
render_connectors(true);
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);
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);
}
}
}
void GLGizmoCut3D::update_raycasters_for_picking_transform()
{
if (m_connectors_editing) {
CommonGizmosDataObjects::SelectionInfo* si = m_c->selection_info();
if (!si)
return;
const ModelObject* mo = si->model_object();
const CutConnectors& connectors = mo->cut_connectors;
if (connectors.empty())
return;
auto inst_id = m_c->selection_info()->get_active_instance();
if (inst_id < 0)
return;
const Vec3d& instance_offset = mo->instances[inst_id]->get_offset();
const float sla_shift = m_c->selection_info()->get_sla_shift();
const ClippingPlane* cp = m_c->object_clipper()->get_clipping_plane();
const Vec3d& normal = cp && cp->is_active() ? cp->get_normal() : m_clp_normal;
for (size_t i = 0; i < connectors.size(); ++i) {
const CutConnector& connector = connectors[i];
double height = connector.height;
// recalculate connector position to world position
Vec3d pos = connector.pos + instance_offset;
if (connector.attribs.type == CutConnectorType::Dowel &&
connector.attribs.style == CutConnectorStyle::Prizm) {
pos -= height * normal;
height *= 2;
}
pos[Z] += sla_shift;
m_raycasters[i]->set_transform(Geometry::assemble_transform(
pos,
Geometry::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 BoundingBoxf3 box = bounding_box();
const double mean_size = float((box.size().x() + box.size().y() + box.size().z()) / 6.0);
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));
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));
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));
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));
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));
}
}
#endif // ENABLE_RAYCAST_PICKING
void GLGizmoCut3D::on_set_hover_id()
{
@ -856,7 +990,7 @@ bool GLGizmoCut3D::on_is_activable() const
Vec3d GLGizmoCut3D::mouse_position_in_local_plane(Axis axis, const Linef3& mouse_ray) const
{
double half_pi = 0.5 * double(PI);
double half_pi = 0.5 * PI;
Transform3d m = Transform3d::Identity();
@ -882,8 +1016,7 @@ Vec3d GLGizmoCut3D::mouse_position_in_local_plane(Axis axis, const Linef3& mouse
}
}
m = m * m_rotation_m.inverse();
m = m * m_start_dragging_m.inverse();
m.translate(-m_plane_center);
return transform(mouse_ray, m).intersect_plane(0.0);
@ -945,17 +1078,29 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
if (cross2(orig_dir, new_dir) < 0.0)
theta = two_pi - theta;
const double len = mouse_pos.norm();
// snap to coarse snap region
if (m_snap_coarse_in_radius <= len && len <= m_snap_coarse_out_radius) {
const double step = two_pi / double(SnapRegionsCount);
theta = step * std::round(theta / step);
}
else {
// snap to fine snap region (scale)
if (m_snap_fine_in_radius <= len && len <= m_snap_fine_out_radius) {
const double step = two_pi / double(ScaleStepsCount);
theta = step * std::round(theta / step);
}
}
if (theta == two_pi)
theta = 0.0;
if (m_hover_id == X)
theta += 0.5 * PI;
rotation[m_hover_id] = theta;
m_rotation_m = m_start_dragging_m * Geometry::rotation_transform(rotation);
m_rotation_m = m_rotation_m * Geometry::rotation_transform(rotation);
m_angle += (float)theta;
m_angle = theta;
while (m_angle > two_pi)
m_angle -= two_pi;
if (m_angle < 0.0)
@ -964,13 +1109,13 @@ void GLGizmoCut3D::on_dragging(const UpdateData& data)
update_clipper();
}
else if (m_hover_id >= m_connectors_group_id && m_connector_mode == CutConnectorMode::Manual)
{
std::pair<Vec3d, Vec3d> pos_and_normal;
if (!unproject_on_cut_plane(data.mouse_pos.cast<double>(), pos_and_normal))
return;
connectors[m_hover_id - m_connectors_group_id].pos = pos_and_normal.first;
update_raycasters_for_picking_transform();
}
}
@ -1081,6 +1226,11 @@ bool GLGizmoCut3D::update_bb()
m_grabber_connection_len = std::min<double>(0.75 * m_radius, 35.0);
m_grabber_radius = m_grabber_connection_len * 0.85;
m_snap_coarse_in_radius = m_grabber_radius / 3.0f;
m_snap_coarse_out_radius = 2.0f * m_snap_coarse_in_radius;
m_snap_fine_in_radius = m_grabber_connection_len * 0.85;
m_snap_fine_out_radius = m_grabber_connection_len * 1.15f;
m_plane.reset();
m_cone.reset();
m_sphere.reset();
@ -1099,18 +1249,29 @@ bool GLGizmoCut3D::update_bb()
return false;
}
void GLGizmoCut3D::init_picking_models()
{
if (!m_cone.model.is_initialized()) {
indexed_triangle_set its = its_make_cone(1.0, 1.0, PI / 12.0);
m_cone.model.init_from(its);
m_cone.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
}
if (!m_sphere.model.is_initialized()) {
indexed_triangle_set its = its_make_sphere(1.0, PI / 12.0);
m_sphere.model.init_from(its);
m_sphere.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
}
}
void GLGizmoCut3D::on_render()
{
if (update_bb())
update_clipper_on_render();
if (!m_cone.is_initialized())
m_cone.init_from(its_make_cone(1.0, 1.0, double(PI) / 12.0));
if (!m_sphere.is_initialized())
m_sphere.init_from(its_make_sphere(1.0, double(PI) / 12.0));
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())
init_from_circle(m_circle, m_grabber_radius);
if (!m_scale.is_initialized())
@ -1124,10 +1285,12 @@ 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 (force_update_clipper_on_render)
if (force_update_clipper_on_render) {
update_clipper_on_render();
m_c->object_clipper()->set_behavior(m_connectors_editing, m_connectors_editing, 0.4f);
}
render_connectors(false);
render_connectors();
if (! m_connectors_editing)
::glDisable(GL_DEPTH_TEST);
@ -1265,8 +1428,10 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
ImGui::Separator();
m_imgui->disabled_begin(!m_keep_upper || !m_keep_lower);
if (m_imgui->button(_L("Add/Edit connectors")))
if (m_imgui->button(_L("Add/Edit connectors"))) {
m_connectors_editing = true;
on_unregister_raycasters_for_picking();
}
m_imgui->disabled_end();
}
}
@ -1353,6 +1518,7 @@ void GLGizmoCut3D::on_render_input_window(float x, float y, float bottom_limit)
if (m_imgui->button(_L("Confirm connectors"))) {
m_clp_normal = m_c->object_clipper()->get_clipping_plane()->get_normal();
m_connectors_editing = false;
on_unregister_raycasters_for_picking();
std::fill(m_selected.begin(), m_selected.end(), false);
m_selected_count = 0;
}
@ -1422,9 +1588,9 @@ Transform3d GLGizmoCut3D::get_volume_transformation(const ModelVolume* volume) c
return Geometry::assemble_transform(offset, Vec3d::Zero(), Vec3d::Ones() - border_scale, Vec3d::Ones()) * vol_matrix;
}
void GLGizmoCut3D::render_connectors(bool picking)
void GLGizmoCut3D::render_connectors()
{
if (picking && ! m_connectors_editing)
if (!m_connectors_editing)
return;
::glEnable(GL_DEPTH_TEST);
@ -1443,7 +1609,7 @@ void GLGizmoCut3D::render_connectors(bool picking)
m_selected.resize(connectors.size(), false);
}
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
if (shader == nullptr)
return;
@ -1480,37 +1646,33 @@ void GLGizmoCut3D::render_connectors(bool picking)
pos[Z] += sla_shift;
// First decide about the color of the point.
if (picking)
render_color = picking_decode(BASE_ID - i - m_connectors_group_id);
else {
if (size_t(m_hover_id- m_connectors_group_id) == i)
render_color = ColorRGBA::CYAN();
else if (m_selected[i])
render_color = ColorRGBA::DARK_GRAY();
else // neither hover nor picking
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
if (size_t(m_hover_id- m_connectors_group_id) == i)
render_color = ColorRGBA::CYAN();
else if (m_selected[i])
render_color = ColorRGBA::DARK_GRAY();
else // neither hover nor picking
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
// ! #ysFIXME rework get_volume_transformation
if (0) { // else { // neither hover nor picking
int mesh_id = -1;
for (const ModelVolume* mv : mo->volumes) {
++mesh_id;
if (!mv->is_model_part())
continue;
// ! #ysFIXME rework get_volume_transformation
if (0) { // else { // neither hover nor picking
int mesh_id = -1;
for (const ModelVolume* mv : mo->volumes) {
++mesh_id;
if (!mv->is_model_part())
continue;
const Transform3d volume_trafo = get_volume_transformation(mv);
const Transform3d volume_trafo = get_volume_transformation(mv);
if (m_c->raycaster()->raycasters()[mesh_id]->is_valid_intersection(pos, -normal, instance_trafo * volume_trafo)) {
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : /*ColorRGBA(0.5f, 0.5f, 0.5f, 1.f)*/ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
break;
}
render_color = ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
m_has_invalid_connector = true;
if (m_c->raycaster()->raycasters()[mesh_id]->is_valid_intersection(pos, -normal, instance_trafo * volume_trafo)) {
render_color = m_connectors_editing ? ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f) : /*ColorRGBA(0.5f, 0.5f, 0.5f, 1.f)*/ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
break;
}
render_color = ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f);
m_has_invalid_connector = true;
}
}
m_shapes[connector.attribs].set_color(render_color);
m_shapes[connector.attribs].model.set_color(render_color);
const Transform3d view_model_matrix = camera.get_view_matrix() * Geometry::assemble_transform(
pos,
@ -1520,7 +1682,7 @@ void GLGizmoCut3D::render_connectors(bool picking)
shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
m_shapes[connector.attribs].render();
m_shapes[connector.attribs].model.render();
}
}
@ -1657,7 +1819,8 @@ void GLGizmoCut3D::update_connector_shape()
CutConnectorAttributes attribs = { m_connector_type, CutConnectorStyle(m_connector_style), CutConnectorShape(m_connector_shape_id) };
if (m_shapes.find(attribs) == m_shapes.end()) {
const indexed_triangle_set its = ModelObject::get_connector_mesh(attribs);
m_shapes[attribs].init_from(its);
m_shapes[attribs].model.init_from(its);
m_shapes[attribs].mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));;
}
const indexed_triangle_set its = ModelObject::get_connector_mesh(attribs);
@ -1665,16 +1828,16 @@ void GLGizmoCut3D::update_connector_shape()
m_connector_mesh = TriangleMesh(its);
}
void GLGizmoCut3D::update_model_object() const
void GLGizmoCut3D::update_model_object()
{
/* const Selection& selection = m_parent.get_selection();
const GLVolume* first_glvolume = selection.get_first_volume();
const BoundingBoxf3& box = first_glvolume->transformed_convex_hull_bounding_box();*/
const ModelObjectPtrs& mos = wxGetApp().model().objects;
ModelObject* mo = m_c->selection_info()->model_object();
wxGetApp().obj_list()->update_info_items(std::find(mos.begin(), mos.end(), mo) - mos.begin());
m_parent.post_event(SimpleEvent(EVT_GLCANVAS_SCHEDULE_BACKGROUND_PROCESS));
on_unregister_raycasters_for_picking();
on_register_raycasters_for_picking();
}
bool GLGizmoCut3D::cut_line_processing() const
@ -1763,10 +1926,10 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
CutConnectorAttributes( CutConnectorType(m_connector_type),
CutConnectorStyle(m_connector_style),
CutConnectorShape(m_connector_shape_id)));
update_model_object();
std::fill(m_selected.begin(), m_selected.end(), false);
m_selected.push_back(true);
assert(m_selected.size() == connectors.size());
update_model_object();
m_parent.set_as_dirty();
return true;
@ -1801,9 +1964,9 @@ bool GLGizmoCut3D::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_posi
size_t connector_id = m_hover_id - m_connectors_group_id;
connectors.erase(connectors.begin() + connector_id);
update_model_object();
m_selected.erase(m_selected.begin() + connector_id);
assert(m_selected.size() == connectors.size());
update_model_object();
m_parent.set_as_dirty();
return true;

View File

@ -41,11 +41,15 @@ class GLGizmoCut3D : public GLGizmoBase
double m_grabber_radius{ 0.0 };
double m_grabber_connection_len{ 0.0 };
double m_snap_coarse_in_radius{ 0.0 };
double m_snap_coarse_out_radius{ 0.0 };
double m_snap_fine_in_radius{ 0.0 };
double m_snap_fine_out_radius{ 0.0 };
// dragging angel in hovered axes
Transform3d m_start_dragging_m{ Transform3d::Identity() };
double m_angle{ 0.0 };
std::map<CutConnectorAttributes, GLModel> m_shapes;
TriangleMesh m_connector_mesh;
// workaround for using of the clipping plane normal
Vec3d m_clp_normal{ Vec3d::Ones() };
@ -53,12 +57,14 @@ class GLGizmoCut3D : public GLGizmoBase
Vec3d m_line_beg{ Vec3d::Zero() };
Vec3d m_line_end{ Vec3d::Zero() };
#if ENABLE_LEGACY_OPENGL_REMOVAL
GLModel m_plane;
GLModel m_grabber_connection;
GLModel m_cut_line;
GLModel m_cone;
GLModel m_sphere;
PickingModel m_sphere;
PickingModel m_cone;
std::map<CutConnectorAttributes, PickingModel> m_shapes;
std::vector<std::shared_ptr<SceneRaycasterItem>> m_raycasters;
GLModel m_circle;
GLModel m_scale;
@ -67,7 +73,6 @@ class GLGizmoCut3D : public GLGizmoBase
GLModel m_angle_arc;
Vec3d m_old_center;
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
bool m_keep_upper{ true };
bool m_keep_lower{ true };
@ -168,12 +173,12 @@ protected:
void on_start_dragging() override;
void on_stop_dragging() override;
void on_render() override;
#if ENABLE_RAYCAST_PICKING
virtual void on_register_raycasters_for_picking() override;
virtual void on_unregister_raycasters_for_picking() override;
#else
virtual void on_render_for_picking() override;
#endif // ENABLE_RAYCAST_PICKING
void set_volumes_picking_state(bool state);
void update_raycasters_for_picking_transform();
void on_render_input_window(float x, float y, float bottom_limit) override;
bool wants_enter_leave_snapshots() const override { return true; }
@ -191,21 +196,22 @@ private:
bool render_revert_button(const std::string& label);
bool render_connect_type_radio_button(CutConnectorType type);
Transform3d get_volume_transformation(const ModelVolume* volume) const;
void render_connectors(bool picking);
void render_connectors();
bool can_perform_cut() const;
bool cut_line_processing() const;
void discard_cut_line_processing();
void render_cut_plane();
void render_cut_center_graber(bool picking = false);
void render_cut_center_graber();
void render_cut_line();
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 reset_connectors();
void update_connector_shape();
void update_model_object() const;
void update_model_object();
bool process_cut_line(SLAGizmoEventType action, const Vec2d& mouse_position);
};