Tech ENABLE_RAYCAST_PICKING - Raytraced picking of Gizmo Hollow

This commit is contained in:
enricoturri1966 2022-06-15 09:01:13 +02:00
parent f5e68a6ac6
commit c5c5c23ed2
5 changed files with 144 additions and 16 deletions

View File

@ -1958,12 +1958,6 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_hover_volume_idxs.clear();
#if ENABLE_RAYCAST_PICKING
GLGizmoBase* curr_gizmo = m_gizmos.get_current();
if (curr_gizmo != nullptr)
curr_gizmo->unregister_raycasters_for_picking();
#endif // ENABLE_RAYCAST_PICKING
struct ModelVolumeState {
ModelVolumeState(const GLVolume* volume) :
model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
@ -2416,6 +2410,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
}
// refresh gizmo elements raycasters for picking
GLGizmoBase* curr_gizmo = m_gizmos.get_current();
if (curr_gizmo != nullptr)
curr_gizmo->unregister_raycasters_for_picking();
m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Gizmo);
if (curr_gizmo != nullptr && !m_selection.is_empty())
curr_gizmo->register_raycasters_for_picking();

View File

@ -673,6 +673,10 @@ public:
m_scene_raycaster.remove_raycasters(type);
}
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters_for_picking(SceneRaycaster::EType type) {
return m_scene_raycaster.get_raycasters(type);
}
void set_raycaster_gizmos_on_top(bool value) {
m_scene_raycaster.set_gizmos_on_top(value);
}

View File

@ -55,6 +55,12 @@ void GLGizmoHollow::data_changed()
}
if (m_c->hollowed_mesh() && m_c->hollowed_mesh()->get_hollowed_mesh())
m_holes_in_drilled_mesh = mo->sla_drain_holes;
#if ENABLE_RAYCAST_PICKING
if (m_raycasters.empty())
on_register_raycasters_for_picking();
else
update_raycasters_for_picking_transform();
#endif // ENABLE_RAYCAST_PICKING
}
}
@ -62,8 +68,16 @@ void GLGizmoHollow::data_changed()
void GLGizmoHollow::on_render()
{
#if ENABLE_RAYCAST_PICKING
if (!m_cylinder.model.is_initialized()) {
indexed_triangle_set its = its_make_cylinder(1.0, 1.0);
m_cylinder.model.init_from(its);
m_cylinder.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
}
#else
if (!m_cylinder.is_initialized())
m_cylinder.init_from(its_make_cylinder(1.0, 1.0));
#endif // ENABLE_RAYCAST_PICKING
const Selection& selection = m_parent.get_selection();
const CommonGizmosDataObjects::SelectionInfo* sel_info = m_c->selection_info();
@ -80,7 +94,11 @@ void GLGizmoHollow::on_render()
glsafe(::glEnable(GL_DEPTH_TEST));
if (selection.is_from_single_instance())
#if ENABLE_RAYCAST_PICKING
render_points(selection);
#else
render_points(selection, false);
#endif // ENABLE_RAYCAST_PICKING
m_selection_rectangle.render(m_parent);
m_c->object_clipper()->render_cut();
@ -89,8 +107,29 @@ void GLGizmoHollow::on_render()
glsafe(::glDisable(GL_BLEND));
}
#if ENABLE_RAYCAST_PICKING
void GLGizmoHollow::on_register_raycasters_for_picking()
{
assert(m_raycasters.empty());
#if !ENABLE_RAYCAST_PICKING
set_sla_auxiliary_volumes_picking_state(false);
const CommonGizmosDataObjects::SelectionInfo* info = m_c->selection_info();
if (info != nullptr && info->model_object()->sla_drain_holes.size() > 0) {
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, Transform3d::Identity()));
}
update_raycasters_for_picking_transform();
}
}
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);
}
#else
void GLGizmoHollow::on_render_for_picking()
{
const Selection& selection = m_parent.get_selection();
@ -101,12 +140,20 @@ void GLGizmoHollow::on_render_for_picking()
glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, true);
}
#endif // !ENABLE_RAYCAST_PICKING
#endif // ENABLE_RAYCAST_PICKING
#if ENABLE_RAYCAST_PICKING
void GLGizmoHollow::render_points(const Selection& selection)
#else
void GLGizmoHollow::render_points(const Selection& selection, bool picking)
#endif // ENABLE_RAYCAST_PICKING
{
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
GLShaderProgram* shader = wxGetApp().get_shader("gouraud_light");
#else
GLShaderProgram* shader = picking ? wxGetApp().get_shader("flat") : wxGetApp().get_shader("gouraud_light");
#endif // ENABLE_RAYCAST_PICKING
if (shader == nullptr)
return;
@ -152,13 +199,22 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
const sla::DrainHole& drain_hole = drain_holes[i];
const bool point_selected = m_selected[i];
#if ENABLE_RAYCAST_PICKING
const bool clipped = is_mesh_point_clipped(drain_hole.pos.cast<double>());
m_raycasters[i]->set_active(!clipped);
if (clipped)
continue;
#else
if (is_mesh_point_clipped(drain_hole.pos.cast<double>()))
continue;
#endif // ENABLE_RAYCAST_PICKING
// First decide about the color of the point.
#if !ENABLE_RAYCAST_PICKING
if (picking)
render_color = picking_color_component(i);
else {
#endif // !ENABLE_RAYCAST_PICKING
if (size_t(m_hover_id) == i)
render_color = ColorRGBA::CYAN();
else if (m_c->hollowed_mesh() &&
@ -168,10 +224,16 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
}
else // neither hover nor picking
render_color = point_selected ? ColorRGBA(1.0f, 0.3f, 0.3f, 0.5f) : ColorRGBA(1.0f, 1.0f, 1.0f, 0.5f);
#if !ENABLE_RAYCAST_PICKING
}
#endif // !ENABLE_RAYCAST_PICKING
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
m_cylinder.model.set_color(render_color);
#else
m_cylinder.set_color(render_color);
#endif // ENABLE_RAYCAST_PICKING
// Inverse matrix of the instance scaling is applied so that the mark does not scale with the object.
const Transform3d hole_matrix = Geometry::assemble_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
#else
@ -200,7 +262,11 @@ void GLGizmoHollow::render_points(const Selection& selection, bool picking)
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
#if ENABLE_RAYCAST_PICKING
m_cylinder.model.render();
#else
m_cylinder.render();
#endif // ENABLE_RAYCAST_PICKING
if (vol->is_left_handed())
glsafe(::glFrontFace(GL_CCW));
@ -327,6 +393,10 @@ bool GLGizmoHollow::gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_pos
assert(m_selected.size() == mo->sla_drain_holes.size());
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();
#endif // ENABLE_RAYCAST_PICKING
}
else
return false;
@ -520,6 +590,47 @@ void GLGizmoHollow::hollow_mesh(bool postpone_error_messages)
});
}
#if ENABLE_RAYCAST_PICKING
void GLGizmoHollow::set_sla_auxiliary_volumes_picking_state(bool state)
{
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);
}
}
}
}
void GLGizmoHollow::update_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()) {
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();
for (size_t i = 0; i < drain_holes.size(); ++i) {
const sla::DrainHole& drain_hole = drain_holes[i];
const Transform3d hole_matrix = Geometry::translation_transform(drain_hole.pos.cast<double>()) * instance_scaling_matrix_inverse;
Eigen::Quaterniond q;
q.setFromTwoVectors(Vec3d::UnitZ(), instance_scaling_matrix_inverse * (-drain_hole.normal).cast<double>());
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);
}
}
}
}
#endif // ENABLE_RAYCAST_PICKING
std::vector<std::pair<const ConfigOption*, const ConfigOptionDef*>>
GLGizmoHollow::get_config_options(const std::vector<std::string>& keys) const

View File

@ -28,8 +28,7 @@ private:
public:
GLGizmoHollow(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
virtual ~GLGizmoHollow() = default;
void data_changed() override;
void data_changed() override;
bool gizmo_event(SLAGizmoEventType action, const Vec2d& mouse_position, bool shift_down, bool alt_down, bool control_down);
void delete_selected_points();
bool is_selection_rectangle_dragging() const {
@ -43,20 +42,37 @@ public:
/// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information otherwise False.</returns>
bool on_mouse(const wxMouseEvent &mouse_event) override;
private:
protected:
bool on_init() override;
void on_render() override;
#if !ENABLE_RAYCAST_PICKING
#if ENABLE_RAYCAST_PICKING
virtual void on_register_raycasters_for_picking() override;
virtual void on_unregister_raycasters_for_picking() override;
#else
void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
#endif // ENABLE_RAYCAST_PICKING
private:
#if ENABLE_RAYCAST_PICKING
void render_points(const Selection& selection);
#else
void render_points(const Selection& selection, bool picking = false);
#endif // ENABLE_RAYCAST_PICKING
void hollow_mesh(bool postpone_error_messages = false);
bool unsaved_changes() const;
#if ENABLE_RAYCAST_PICKING
void set_sla_auxiliary_volumes_picking_state(bool state);
void update_raycasters_for_picking_transform();
#endif // ENABLE_RAYCAST_PICKING
ObjectID m_old_mo_id = -1;
#if ENABLE_RAYCAST_PICKING
PickingModel m_cylinder;
std::vector<std::shared_ptr<SceneRaycasterItem>> m_raycasters;
#else
GLModel m_cylinder;
#endif // ENABLE_RAYCAST_PICKING
float m_new_hole_radius = 2.f; // Size of a new hole.
float m_new_hole_height = 6.f;

View File

@ -88,6 +88,8 @@ public:
void remove_raycasters(EType type);
void remove_raycaster(std::shared_ptr<SceneRaycasterItem> item);
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type);
void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; }
HitResult hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane = nullptr);
@ -101,8 +103,6 @@ public:
#endif // ENABLE_RAYCAST_PICKING_DEBUG
private:
std::vector<std::shared_ptr<SceneRaycasterItem>>* get_raycasters(EType type);
static PickingId encode_id(EType type, PickingId id);
static PickingId decode_id(EType type, PickingId id);
static PickingId base_id(EType type);