Tech ENABLE_RAYCAST_PICKING - Raytraced picking of gizmos - Move Gizmo

This commit is contained in:
enricoturri1966 2022-06-13 13:09:24 +02:00
parent 36ec839767
commit df47ba7122
27 changed files with 330 additions and 74 deletions

View File

@ -253,7 +253,7 @@ bool Bed3D::set_shape(const Pointfs& bed_shape, const double max_print_height, c
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING
// unregister from picking // unregister from picking
wxGetApp().plater()->canvas3D()->remove_all_picking_raycasters(SceneRaycaster::EType::Bed); wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Bed);
#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_RAYCAST_PICKING
// Let the calee to update the UI. // Let the calee to update the UI.

View File

@ -29,10 +29,11 @@ void CoordAxes::render(float emission_factor)
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
auto render_axis = [this](GLShaderProgram& shader, const Transform3d& transform) { auto render_axis = [this](GLShaderProgram& shader, const Transform3d& transform) {
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
const Transform3d matrix = camera.get_view_matrix() * transform; const Transform3d& view_matrix = camera.get_view_matrix();
const Transform3d matrix = view_matrix * transform;
shader.set_uniform("view_model_matrix", matrix); shader.set_uniform("view_model_matrix", matrix);
shader.set_uniform("projection_matrix", camera.get_projection_matrix()); shader.set_uniform("projection_matrix", camera.get_projection_matrix());
shader.set_uniform("normal_matrix", (Matrix3d)matrix.matrix().block(0, 0, 3, 3).inverse().transpose()); shader.set_uniform("view_normal_matrix", (Matrix3d)(view_matrix.matrix().block(0, 0, 3, 3) * transform.matrix().block(0, 0, 3, 3).inverse().transpose()));
m_arrow.render(); m_arrow.render();
#else #else
auto render_axis = [this](const Transform3f& transform) { auto render_axis = [this](const Transform3f& transform) {

View File

@ -1958,6 +1958,12 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
m_hover_volume_idxs.clear(); 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 { struct ModelVolumeState {
ModelVolumeState(const GLVolume* volume) : ModelVolumeState(const GLVolume* volume) :
model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {} model_volume(nullptr), geometry_id(volume->geometry_id), volume_idx(-1) {}
@ -2403,11 +2409,16 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING
// refresh volume raycasters for picking // refresh volume raycasters for picking
m_scene_raycaster.reset(SceneRaycaster::EType::Volume); m_scene_raycaster.remove_raycasters(SceneRaycaster::EType::Volume);
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) { for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
assert(m_volumes.volumes[i]->mesh_raycaster != nullptr); assert(m_volumes.volumes[i]->mesh_raycaster != nullptr);
add_raycaster_for_picking(SceneRaycaster::EType::Volume, i, *m_volumes.volumes[i]->mesh_raycaster, m_volumes.volumes[i]->world_matrix()); add_raycaster_for_picking(SceneRaycaster::EType::Volume, i, *m_volumes.volumes[i]->mesh_raycaster, m_volumes.volumes[i]->world_matrix());
} }
// refresh gizmo elements 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();
#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_RAYCAST_PICKING
// and force this canvas to be redrawn. // and force this canvas to be redrawn.
@ -5432,9 +5443,14 @@ void GLCanvas3D::_refresh_if_shown_on_screen()
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING
void GLCanvas3D::_picking_pass() void GLCanvas3D::_picking_pass()
{ {
if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX)) if (!m_picking_enabled || m_mouse.dragging || m_mouse.position == Vec2d(DBL_MAX, DBL_MAX)) {
ImGuiWrapper& imgui = *wxGetApp().imgui();
imgui.begin(std::string("Hit result"), ImGuiWindowFlags_AlwaysAutoResize);
imgui.text("Picking disabled");
imgui.end();
return; return;
}
m_hover_volume_idxs.clear(); m_hover_volume_idxs.clear();
const ClippingPlane clipping_plane = m_gizmos.get_clipping_plane().inverted_normal(); const ClippingPlane clipping_plane = m_gizmos.get_clipping_plane().inverted_normal();

View File

@ -663,11 +663,18 @@ public:
void post_event(wxEvent &&event); void post_event(wxEvent &&event);
#if ENABLE_RAYCAST_PICKING #if ENABLE_RAYCAST_PICKING
int add_raycaster_for_picking(SceneRaycaster::EType type, int id, const MeshRaycaster& raycaster, const Transform3d& trafo) { void add_raycaster_for_picking(SceneRaycaster::EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) {
return m_scene_raycaster.add_raycaster(type, id, raycaster, trafo); m_scene_raycaster.add_raycaster(type, id, raycaster, trafo);
} }
void remove_all_picking_raycasters(SceneRaycaster::EType type) { void remove_raycasters_for_picking(SceneRaycaster::EType type, PickingId id) {
m_scene_raycaster.reset(type); m_scene_raycaster.remove_raycasters(type, id);
}
void remove_raycasters_for_picking(SceneRaycaster::EType type) {
m_scene_raycaster.remove_raycasters(type);
}
void set_raycaster_gizmos_on_top(bool value) {
m_scene_raycaster.set_gizmos_on_top(value);
} }
#endif // ENABLE_RAYCAST_PICKING #endif // ENABLE_RAYCAST_PICKING

View File

@ -18,16 +18,29 @@ const float GLGizmoBase::Grabber::SizeFactor = 0.05f;
const float GLGizmoBase::Grabber::MinHalfSize = 1.5f; const float GLGizmoBase::Grabber::MinHalfSize = 1.5f;
const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f; const float GLGizmoBase::Grabber::DraggingScaleFactor = 1.25f;
#if ENABLE_RAYCAST_PICKING
PickingModel GLGizmoBase::Grabber::s_cube;
PickingModel GLGizmoBase::Grabber::s_cone;
#else
GLModel GLGizmoBase::Grabber::s_cube; GLModel GLGizmoBase::Grabber::s_cube;
GLModel GLGizmoBase::Grabber::s_cone; GLModel GLGizmoBase::Grabber::s_cone;
#endif // ENABLE_RAYCAST_PICKING
GLGizmoBase::Grabber::~Grabber() GLGizmoBase::Grabber::~Grabber()
{ {
#if ENABLE_RAYCAST_PICKING
if (s_cube.model.is_initialized())
s_cube.model.reset();
if (s_cone.model.is_initialized())
s_cone.model.reset();
#else
if (s_cube.is_initialized()) if (s_cube.is_initialized())
s_cube.reset(); s_cube.reset();
if (s_cone.is_initialized()) if (s_cone.is_initialized())
s_cone.reset(); s_cone.reset();
#endif // ENABLE_RAYCAST_PICKING
} }
float GLGizmoBase::Grabber::get_half_size(float size) const float GLGizmoBase::Grabber::get_half_size(float size) const
@ -40,6 +53,21 @@ float GLGizmoBase::Grabber::get_dragging_half_size(float size) const
return get_half_size(size) * DraggingScaleFactor; return get_half_size(size) * DraggingScaleFactor;
} }
#if ENABLE_RAYCAST_PICKING
void GLGizmoBase::Grabber::register_raycasters_for_picking(int id)
{
picking_id = id;
assert(elements_registered_for_picking == false);
}
void GLGizmoBase::Grabber::unregister_raycasters_for_picking()
{
wxGetApp().plater()->canvas3D()->remove_raycasters_for_picking(SceneRaycaster::EType::Gizmo, picking_id);
picking_id = -1;
elements_registered_for_picking = false;
}
#endif // ENABLE_RAYCAST_PICKING
void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking) void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, bool picking)
{ {
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
@ -48,35 +76,69 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
return; return;
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
if (!s_cube.model.is_initialized()) {
#else
if (!s_cube.is_initialized()) { if (!s_cube.is_initialized()) {
#endif // ENABLE_RAYCAST_PICKING
// This cannot be done in constructor, OpenGL is not yet // This cannot be done in constructor, OpenGL is not yet
// initialized at that point (on Linux at least). // initialized at that point (on Linux at least).
indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0); indexed_triangle_set its = its_make_cube(1.0, 1.0, 1.0);
its_translate(its, -0.5f * Vec3f::Ones()); its_translate(its, -0.5f * Vec3f::Ones());
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
s_cube.model.init_from(its);
s_cube.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
#else
s_cube.init_from(its); s_cube.init_from(its);
#endif // ENABLE_RAYCAST_PICKING
#else #else
s_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } }); s_cube.init_from(its, BoundingBoxf3{ { -0.5, -0.5, -0.5 }, { 0.5, 0.5, 0.5 } });
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
#if ENABLE_RAYCAST_PICKING
if (!s_cone.model.is_initialized()) {
indexed_triangle_set its = its_make_cone(0.375, 1.5, double(PI) / 18.0);
s_cone.model.init_from(its);
s_cone.mesh_raycaster = std::make_unique<MeshRaycaster>(std::make_shared<const TriangleMesh>(std::move(its)));
}
#else
if (!s_cone.is_initialized()) if (!s_cone.is_initialized())
s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0)); s_cone.init_from(its_make_cone(0.375, 1.5, double(PI) / 18.0));
#endif // ENABLE_RAYCAST_PICKING
const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size); const float half_size = dragging ? get_dragging_half_size(size) : get_half_size(size);
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
s_cube.model.set_color(render_color);
s_cone.model.set_color(render_color);
#else
s_cube.set_color(render_color); s_cube.set_color(render_color);
s_cone.set_color(render_color); s_cone.set_color(render_color);
#endif // ENABLE_RAYCAST_PICKING
const Camera& camera = wxGetApp().plater()->get_camera(); const Camera& camera = wxGetApp().plater()->get_camera();
shader->set_uniform("projection_matrix", camera.get_projection_matrix());
#if ENABLE_RAYCAST_PICKING
const Transform3d& view_matrix = camera.get_view_matrix();
const Matrix3d view_matrix_no_offset = view_matrix.matrix().block(0, 0, 3, 3);
std::vector<Transform3d> elements_matrices(7, Transform3d::Identity()); // 1 + count of EGrabberExtensions == 7
elements_matrices[0] = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
Transform3d view_model_matrix = view_matrix * elements_matrices[0];
#else
const Transform3d& view_matrix = camera.get_view_matrix(); const Transform3d& view_matrix = camera.get_view_matrix();
const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones()); const Transform3d model_matrix = matrix * Geometry::assemble_transform(center, angles, 2.0 * half_size * Vec3d::Ones());
const Transform3d view_model_matrix = view_matrix * model_matrix; const Transform3d view_model_matrix = view_matrix * model_matrix;
#endif // ENABLE_RAYCAST_PICKING
shader->set_uniform("view_model_matrix", view_model_matrix); shader->set_uniform("view_model_matrix", view_model_matrix);
shader->set_uniform("projection_matrix", camera.get_projection_matrix()); #if ENABLE_RAYCAST_PICKING
Matrix3d view_normal_matrix = view_matrix_no_offset * elements_matrices[0].matrix().block(0, 0, 3, 3).inverse().transpose();
#else
const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose(); const Matrix3d view_normal_matrix = view_matrix.matrix().block(0, 0, 3, 3) * model_matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
#endif // ENABLE_RAYCAST_PICKING
shader->set_uniform("view_normal_matrix", view_normal_matrix); shader->set_uniform("view_normal_matrix", view_normal_matrix);
#else #else
s_cube.set_color(-1, render_color); s_cube.set_color(-1, render_color);
@ -88,32 +150,74 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0)); glsafe(::glRotated(Geometry::rad2deg(angles.x()), 1.0, 0.0, 0.0));
glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size)); glsafe(::glScaled(2.0 * half_size, 2.0 * half_size, 2.0 * half_size));
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
s_cube.model.render();
#else
s_cube.render(); s_cube.render();
#endif // ENABLE_RAYCAST_PICKING
auto render_extension = [&view_matrix, &view_matrix_no_offset, shader](const Transform3d& matrix) {
const Transform3d view_model_matrix = view_matrix * matrix;
shader->set_uniform("view_model_matrix", view_model_matrix);
const Matrix3d view_normal_matrix = view_matrix_no_offset * matrix.matrix().block(0, 0, 3, 3).inverse().transpose();
shader->set_uniform("view_normal_matrix", view_normal_matrix);
s_cone.model.render();
};
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[1] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0));
render_extension(elements_matrices[1]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0))); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitX(), Vec3d(0.0, 0.5 * double(PI), 0.0)));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[2] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0));
render_extension(elements_matrices[2]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0))); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitX(), Vec3d(0.0, -0.5 * double(PI), 0.0)));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[3] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0));
render_extension(elements_matrices[3]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0))); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitY(), Vec3d(-0.5 * double(PI), 0.0, 0.0)));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[4] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0));
render_extension(elements_matrices[4]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0))); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitY(), Vec3d(0.5 * double(PI), 0.0, 0.0)));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[5] = elements_matrices[0] * Geometry::assemble_transform(Vec3d::UnitZ());
render_extension(elements_matrices[5]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitZ())); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(Vec3d::UnitZ()));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0) {
#if ENABLE_RAYCAST_PICKING
elements_matrices[6] = elements_matrices[0] * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0));
render_extension(elements_matrices[6]);
#else
shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0))); shader->set_uniform("view_model_matrix", view_model_matrix * Geometry::assemble_transform(-Vec3d::UnitZ(), Vec3d(double(PI), 0.0, 0.0)));
s_cone.render(); s_cone.render();
#endif // ENABLE_RAYCAST_PICKING
} }
#else #else
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) { if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0) {
@ -161,20 +265,33 @@ void GLGizmoBase::Grabber::render(float size, const ColorRGBA& render_color, boo
#if !ENABLE_LEGACY_OPENGL_REMOVAL #if !ENABLE_LEGACY_OPENGL_REMOVAL
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #endif // !ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
if (!elements_registered_for_picking) {
GLCanvas3D& canvas = *wxGetApp().plater()->canvas3D();
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cube.mesh_raycaster, elements_matrices[0]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosX)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[1]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegX)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[2]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosY)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[3]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegY)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[4]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::PosZ)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[5]);
if ((int(extensions) & int(GLGizmoBase::EGrabberExtension::NegZ)) != 0)
canvas.add_raycaster_for_picking(SceneRaycaster::EType::Gizmo, picking_id, *s_cone.mesh_raycaster, elements_matrices[6]);
elements_registered_for_picking = true;
}
#endif // ENABLE_RAYCAST_PICKING
} }
GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id) GLGizmoBase::GLGizmoBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id)
: m_parent(parent) : m_parent(parent)
, m_group_id(-1)
, m_state(Off)
, m_shortcut_key(0)
, m_icon_filename(icon_filename) , m_icon_filename(icon_filename)
, m_sprite_id(sprite_id) , m_sprite_id(sprite_id)
, m_hover_id(-1)
, m_dragging(false)
, m_imgui(wxGetApp().imgui()) , m_imgui(wxGetApp().imgui())
, m_first_input_window_render(true)
, m_dirty(false)
{ {
} }
@ -198,6 +315,22 @@ bool GLGizmoBase::update_items_state()
return res; return res;
} }
#if ENABLE_RAYCAST_PICKING
void GLGizmoBase::register_grabbers_for_picking()
{
for (size_t i = 0; i < m_grabbers.size(); ++i) {
m_grabbers[i].register_raycasters_for_picking(i);
}
}
void GLGizmoBase::unregister_grabbers_for_picking()
{
for (size_t i = 0; i < m_grabbers.size(); ++i) {
m_grabbers[i].unregister_raycasters_for_picking();
}
}
#endif // ENABLE_RAYCAST_PICKING
ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const ColorRGBA GLGizmoBase::picking_color_component(unsigned int id) const
{ {
id = BASE_ID - id; id = BASE_ID - id;
@ -226,6 +359,7 @@ void GLGizmoBase::render_grabbers(float size) const
shader->stop_using(); shader->stop_using();
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
{ {
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
@ -246,6 +380,7 @@ void GLGizmoBase::render_grabbers_for_picking(const BoundingBoxf3& box) const
} }
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
#endif // !ENABLE_RAYCAST_PICKING
// help function to process grabbers // help function to process grabbers
// call start_dragging, stop_dragging, on_dragging // call start_dragging, stop_dragging, on_dragging

View File

@ -6,6 +6,9 @@
#include "slic3r/GUI/I18N.hpp" #include "slic3r/GUI/I18N.hpp"
#include "slic3r/GUI/GLModel.hpp" #include "slic3r/GUI/GLModel.hpp"
#if ENABLE_RAYCAST_PICKING
#include "slic3r/GUI/MeshUtils.hpp"
#endif // ENABLE_RAYCAST_PICKING
#include <cereal/archives/binary.hpp> #include <cereal/archives/binary.hpp>
@ -65,21 +68,38 @@ protected:
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
ColorRGBA color{ ColorRGBA::WHITE() }; ColorRGBA color{ ColorRGBA::WHITE() };
EGrabberExtension extensions{ EGrabberExtension::None }; EGrabberExtension extensions{ EGrabberExtension::None };
#if ENABLE_RAYCAST_PICKING
// the picking id shared by all the elements
int picking_id{ -1 };
bool elements_registered_for_picking{ false };
#endif // ENABLE_RAYCAST_PICKING
Grabber() = default; Grabber() = default;
~Grabber(); ~Grabber();
void render(bool hover, float size) { render(size, hover ? complementary(color) : color, false); } void render(bool hover, float size) { render(size, hover ? complementary(color) : color, false); }
#if !ENABLE_RAYCAST_PICKING
void render_for_picking(float size) { render(size, color, true); } void render_for_picking(float size) { render(size, color, true); }
#endif // !ENABLE_RAYCAST_PICKING
float get_half_size(float size) const; float get_half_size(float size) const;
float get_dragging_half_size(float size) const; float get_dragging_half_size(float size) const;
#if ENABLE_RAYCAST_PICKING
void register_raycasters_for_picking(int id);
void unregister_raycasters_for_picking();
#endif // ENABLE_RAYCAST_PICKING
private: private:
void render(float size, const ColorRGBA& render_color, bool picking); void render(float size, const ColorRGBA& render_color, bool picking);
#if ENABLE_RAYCAST_PICKING
static PickingModel s_cube;
static PickingModel s_cone;
#else
static GLModel s_cube; static GLModel s_cube;
static GLModel s_cone; static GLModel s_cone;
#endif // ENABLE_RAYCAST_PICKING
}; };
public: public:
@ -102,17 +122,19 @@ public:
protected: protected:
GLCanvas3D& m_parent; GLCanvas3D& m_parent;
int m_group_id; // TODO: remove only for rotate
EState m_state; int m_group_id{ -1 }; // TODO: remove only for rotate
int m_shortcut_key; EState m_state{ Off };
int m_shortcut_key{ 0 };
std::string m_icon_filename; std::string m_icon_filename;
unsigned int m_sprite_id; unsigned int m_sprite_id;
int m_hover_id; int m_hover_id{ -1 };
bool m_dragging; bool m_dragging{ false };
mutable std::vector<Grabber> m_grabbers; mutable std::vector<Grabber> m_grabbers;
ImGuiWrapper* m_imgui; ImGuiWrapper* m_imgui;
bool m_first_input_window_render; bool m_first_input_window_render{ true };
CommonGizmosDataPool* m_c; CommonGizmosDataPool* m_c{ nullptr };
public: public:
GLGizmoBase(GLCanvas3D& parent, GLGizmoBase(GLCanvas3D& parent,
const std::string& icon_filename, const std::string& icon_filename,
@ -153,7 +175,9 @@ public:
bool update_items_state(); bool update_items_state();
void render() { on_render(); } void render() { on_render(); }
#if !ENABLE_RAYCAST_PICKING
void render_for_picking() { on_render_for_picking(); } void render_for_picking() { on_render_for_picking(); }
#endif // !ENABLE_RAYCAST_PICKING
void render_input_window(float x, float y, float bottom_limit); void render_input_window(float x, float y, float bottom_limit);
/// <summary> /// <summary>
@ -174,6 +198,12 @@ public:
/// <param name="mouse_event">Keep information about mouse click</param> /// <param name="mouse_event">Keep information about mouse click</param>
/// <returns>Return True when use the information and don't want to propagate it otherwise False.</returns> /// <returns>Return True when use the information and don't want to propagate it otherwise False.</returns>
virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; } virtual bool on_mouse(const wxMouseEvent &mouse_event) { return false; }
#if ENABLE_RAYCAST_PICKING
void register_raycasters_for_picking() { register_grabbers_for_picking(); on_register_raycasters_for_picking(); }
void unregister_raycasters_for_picking() { unregister_grabbers_for_picking(); on_unregister_raycasters_for_picking(); }
#endif // ENABLE_RAYCAST_PICKING
protected: protected:
virtual bool on_init() = 0; virtual bool on_init() = 0;
virtual void on_load(cereal::BinaryInputArchive& ar) {} virtual void on_load(cereal::BinaryInputArchive& ar) {}
@ -193,16 +223,27 @@ protected:
virtual void on_dragging(const UpdateData& data) {} virtual void on_dragging(const UpdateData& data) {}
virtual void on_render() = 0; virtual void on_render() = 0;
#if !ENABLE_RAYCAST_PICKING
virtual void on_render_for_picking() = 0; virtual void on_render_for_picking() = 0;
#endif // !ENABLE_RAYCAST_PICKING
virtual void on_render_input_window(float x, float y, float bottom_limit) {} virtual void on_render_input_window(float x, float y, float bottom_limit) {}
#if ENABLE_RAYCAST_PICKING
void register_grabbers_for_picking();
void unregister_grabbers_for_picking();
virtual void on_register_raycasters_for_picking() {}
virtual void on_unregister_raycasters_for_picking() {}
#endif // ENABLE_RAYCAST_PICKING
// Returns the picking color for the given id, based on the BASE_ID constant // Returns the picking color for the given id, based on the BASE_ID constant
// No check is made for clashing with other picking color (i.e. GLVolumes) // No check is made for clashing with other picking color (i.e. GLVolumes)
ColorRGBA picking_color_component(unsigned int id) const; ColorRGBA picking_color_component(unsigned int id) const;
void render_grabbers(const BoundingBoxf3& box) const; void render_grabbers(const BoundingBoxf3& box) const;
void render_grabbers(float size) const; void render_grabbers(float size) const;
#if !ENABLE_RAYCAST_PICKING
void render_grabbers_for_picking(const BoundingBoxf3& box) const; void render_grabbers_for_picking(const BoundingBoxf3& box) const;
#endif // !ENABLE_RAYCAST_PICKING
std::string format(float value, unsigned int decimals) const; std::string format(float value, unsigned int decimals) const;
@ -225,7 +266,7 @@ protected:
private: private:
// Flag for dirty visible state of Gizmo // Flag for dirty visible state of Gizmo
// When True then need new rendering // When True then need new rendering
bool m_dirty; bool m_dirty{ false };
}; };
} // namespace GUI } // namespace GUI

View File

@ -269,11 +269,13 @@ void GLGizmoCut::on_render()
#endif // !ENABLE_GL_CORE_PROFILE #endif // !ENABLE_GL_CORE_PROFILE
} }
void GLGizmoCut::on_render_for_picking() #if !ENABLE_RAYCAST_PICKING
void GLGizmoCut::on_render_for_picking()
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box()); render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
} }
#endif // !ENABLE_RAYCAST_PICKING
void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit) void GLGizmoCut::on_render_input_window(float x, float y, float bottom_limit)
{ {

View File

@ -68,7 +68,9 @@ protected:
virtual void on_start_dragging() override; virtual void on_start_dragging() override;
virtual void on_dragging(const UpdateData& data) override; virtual void on_dragging(const UpdateData& data) override;
virtual void on_render() override; virtual void on_render() override;
#if !ENABLE_RAYCAST_PICKING
virtual void on_render_for_picking() override; virtual void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
virtual void on_render_input_window(float x, float y, float bottom_limit) override; virtual void on_render_input_window(float x, float y, float bottom_limit) override;
private: private:

View File

@ -154,6 +154,7 @@ void GLGizmoFlatten::on_render()
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoFlatten::on_render_for_picking() void GLGizmoFlatten::on_render_for_picking()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
@ -204,6 +205,7 @@ void GLGizmoFlatten::on_render_for_picking()
shader->stop_using(); shader->stop_using();
#endif // ENABLE_LEGACY_OPENGL_REMOVAL #endif // ENABLE_LEGACY_OPENGL_REMOVAL
} }
#endif // !ENABLE_RAYCAST_PICKING
void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object) void GLGizmoFlatten::set_flattening_data(const ModelObject* model_object)
{ {

View File

@ -67,7 +67,9 @@ protected:
std::string on_get_name() const override; std::string on_get_name() const override;
bool on_is_activable() const override; bool on_is_activable() const override;
void on_render() override; void on_render() override;
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override; void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
void on_set_state() override; void on_set_state() override;
CommonGizmosDataID on_get_requirements() const override; CommonGizmosDataID on_get_requirements() const override;
}; };

View File

@ -90,6 +90,7 @@ void GLGizmoHollow::on_render()
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoHollow::on_render_for_picking() void GLGizmoHollow::on_render_for_picking()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
@ -100,6 +101,7 @@ void GLGizmoHollow::on_render_for_picking()
glsafe(::glEnable(GL_DEPTH_TEST)); glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, true); render_points(selection, true);
} }
#endif // !ENABLE_RAYCAST_PICKING
void GLGizmoHollow::render_points(const Selection& selection, bool picking) void GLGizmoHollow::render_points(const Selection& selection, bool picking)
{ {

View File

@ -46,7 +46,9 @@ public:
private: private:
bool on_init() override; bool on_init() override;
void on_render() override; void on_render() override;
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override; void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
void render_points(const Selection& selection, bool picking = false); void render_points(const Selection& selection, bool picking = false);
void hollow_mesh(bool postpone_error_messages = false); void hollow_mesh(bool postpone_error_messages = false);

View File

@ -360,6 +360,18 @@ void GLGizmoMove3D::on_render()
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
#if ENABLE_RAYCAST_PICKING
void GLGizmoMove3D::on_register_raycasters_for_picking()
{
// this gizmo is rendered on top of the scene, so the raytraced picker should take it into account
m_parent.set_raycaster_gizmos_on_top(true);
}
void GLGizmoMove3D::on_unregister_raycasters_for_picking()
{
m_parent.set_raycaster_gizmos_on_top(false);
}
#else
void GLGizmoMove3D::on_render_for_picking() void GLGizmoMove3D::on_render_for_picking()
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
@ -384,6 +396,7 @@ void GLGizmoMove3D::on_render_for_picking()
render_grabbers_for_picking(box); render_grabbers_for_picking(box);
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
#endif // ENABLE_RAYCAST_PICKING
double GLGizmoMove3D::calc_projection(const UpdateData& data) const double GLGizmoMove3D::calc_projection(const UpdateData& data) const
{ {

View File

@ -62,7 +62,12 @@ protected:
void on_stop_dragging() override; void on_stop_dragging() override;
void on_dragging(const UpdateData& data) override; void on_dragging(const UpdateData& data) override;
void on_render() 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
void on_render_for_picking() override; void on_render_for_picking() override;
#endif // ENABLE_RAYCAST_PICKING
private: private:
double calc_projection(const UpdateData& data) const; double calc_projection(const UpdateData& data) const;

View File

@ -138,7 +138,10 @@ private:
ObjectID m_old_mo_id; ObjectID m_old_mo_id;
size_t m_old_volumes_size = 0; size_t m_old_volumes_size = 0;
void on_render() override {} void on_render() override {}
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override {} void on_render_for_picking() override {}
#endif // !ENABLE_RAYCAST_PICKING
public: public:
GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id); GLGizmoPainterBase(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
~GLGizmoPainterBase() override; ~GLGizmoPainterBase() override;

View File

@ -251,6 +251,7 @@ void GLGizmoRotate::on_render()
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #endif // !ENABLE_LEGACY_OPENGL_REMOVAL
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoRotate::on_render_for_picking() void GLGizmoRotate::on_render_for_picking()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
@ -275,6 +276,7 @@ void GLGizmoRotate::on_render_for_picking()
glsafe(::glPopMatrix()); glsafe(::glPopMatrix());
#endif // !ENABLE_LEGACY_OPENGL_REMOVAL #endif // !ENABLE_LEGACY_OPENGL_REMOVAL
} }
#endif // !ENABLE_RAYCAST_PICKING
#if ENABLE_WORLD_COORDINATE #if ENABLE_WORLD_COORDINATE
void GLGizmoRotate::init_data_from_selection(const Selection& selection) void GLGizmoRotate::init_data_from_selection(const Selection& selection)

View File

@ -90,7 +90,9 @@ protected:
void on_start_dragging() override; void on_start_dragging() override;
void on_dragging(const UpdateData &data) override; void on_dragging(const UpdateData &data) override;
void on_render() override; void on_render() override;
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override; void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
private: private:
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
@ -175,11 +177,13 @@ protected:
void on_dragging(const UpdateData &data) override; void on_dragging(const UpdateData &data) override;
void on_render() override; void on_render() override;
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override { void on_render_for_picking() override {
for (GLGizmoRotate& g : m_gizmos) { for (GLGizmoRotate& g : m_gizmos) {
g.render_for_picking(); g.render_for_picking();
} }
} }
#endif // !ENABLE_RAYCAST_PICKING
void on_render_input_window(float x, float y, float bottom_limit) override; void on_render_input_window(float x, float y, float bottom_limit) override;

View File

@ -643,6 +643,7 @@ void GLGizmoScale3D::on_render()
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoScale3D::on_render_for_picking() void GLGizmoScale3D::on_render_for_picking()
{ {
glsafe(::glDisable(GL_DEPTH_TEST)); glsafe(::glDisable(GL_DEPTH_TEST));
@ -664,6 +665,7 @@ void GLGizmoScale3D::on_render_for_picking()
render_grabbers_for_picking(m_parent.get_selection().get_bounding_box()); render_grabbers_for_picking(m_parent.get_selection().get_bounding_box());
#endif // ENABLE_WORLD_COORDINATE #endif // ENABLE_WORLD_COORDINATE
} }
#endif // !ENABLE_RAYCAST_PICKING
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL
void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color) void GLGizmoScale3D::render_grabbers_connection(unsigned int id_1, unsigned int id_2, const ColorRGBA& color)

View File

@ -93,7 +93,9 @@ protected:
virtual void on_stop_dragging() override; virtual void on_stop_dragging() override;
virtual void on_dragging(const UpdateData& data) override; virtual void on_dragging(const UpdateData& data) override;
virtual void on_render() override; virtual void on_render() override;
#if !ENABLE_RAYCAST_PICKING
virtual void on_render_for_picking() override; virtual void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
private: private:
#if ENABLE_LEGACY_OPENGL_REMOVAL #if ENABLE_LEGACY_OPENGL_REMOVAL

View File

@ -38,7 +38,9 @@ protected:
// must implement // must implement
virtual bool on_init() override { return true;}; virtual bool on_init() override { return true;};
virtual void on_render() override; virtual void on_render() override;
virtual void on_render_for_picking() override{}; #if !ENABLE_RAYCAST_PICKING
virtual void on_render_for_picking() override{};
#endif // !ENABLE_RAYCAST_PICKING
CommonGizmosDataID on_get_requirements() const override; CommonGizmosDataID on_get_requirements() const override;

View File

@ -111,12 +111,14 @@ void GLGizmoSlaSupports::on_render()
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmoSlaSupports::on_render_for_picking() void GLGizmoSlaSupports::on_render_for_picking()
{ {
const Selection& selection = m_parent.get_selection(); const Selection& selection = m_parent.get_selection();
//glsafe(::glEnable(GL_DEPTH_TEST)); //glsafe(::glEnable(GL_DEPTH_TEST));
render_points(selection, true); render_points(selection, true);
} }
#endif // !ENABLE_RAYCAST_PICKING
void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking) void GLGizmoSlaSupports::render_points(const Selection& selection, bool picking)
{ {

View File

@ -80,7 +80,9 @@ public:
private: private:
bool on_init() override; bool on_init() override;
void on_render() override; void on_render() override;
#if !ENABLE_RAYCAST_PICKING
void on_render_for_picking() override; void on_render_for_picking() override;
#endif // !ENABLE_RAYCAST_PICKING
void render_points(const Selection& selection, bool picking = false); void render_points(const Selection& selection, bool picking = false);
bool unsaved_changes() const; bool unsaved_changes() const;

View File

@ -73,7 +73,7 @@ enum class CommonGizmosDataID {
// by GLGizmoManager, the gizmos keep a pointer to it. // by GLGizmoManager, the gizmos keep a pointer to it.
class CommonGizmosDataPool { class CommonGizmosDataPool {
public: public:
CommonGizmosDataPool(GLCanvas3D* canvas); explicit CommonGizmosDataPool(GLCanvas3D* canvas);
// Update all resources and release what is not used. // Update all resources and release what is not used.
// Accepts a bitmask of currently required resources. // Accepts a bitmask of currently required resources.

View File

@ -331,6 +331,7 @@ void GLGizmosManager::render_painter_gizmo()
gizmo->render_painter_gizmo(); gizmo->render_painter_gizmo();
} }
#if !ENABLE_RAYCAST_PICKING
void GLGizmosManager::render_current_gizmo_for_picking_pass() const void GLGizmosManager::render_current_gizmo_for_picking_pass() const
{ {
if (! m_enabled || m_current == Undefined) if (! m_enabled || m_current == Undefined)
@ -339,6 +340,7 @@ void GLGizmosManager::render_current_gizmo_for_picking_pass() const
m_gizmos[m_current]->render_for_picking(); m_gizmos[m_current]->render_for_picking();
} }
#endif // !ENABLE_RAYCAST_PICKING
void GLGizmosManager::render_overlay() void GLGizmosManager::render_overlay()
{ {
@ -1117,6 +1119,10 @@ bool GLGizmosManager::activate_gizmo(EType type)
if (old_gizmo.get_state() != GLGizmoBase::Off) if (old_gizmo.get_state() != GLGizmoBase::Off)
return false; // gizmo refused to be turned off, do nothing. return false; // gizmo refused to be turned off, do nothing.
#if ENABLE_RAYCAST_PICKING
old_gizmo.unregister_raycasters_for_picking();
#endif // ENABLE_RAYCAST_PICKING
if (!m_serializing && old_gizmo.wants_enter_leave_snapshots()) if (!m_serializing && old_gizmo.wants_enter_leave_snapshots())
Plater::TakeSnapshot Plater::TakeSnapshot
snapshot(wxGetApp().plater(), snapshot(wxGetApp().plater(),
@ -1146,6 +1152,10 @@ bool GLGizmosManager::activate_gizmo(EType type)
return false; // gizmo refused to be turned on. return false; // gizmo refused to be turned on.
} }
#if ENABLE_RAYCAST_PICKING
new_gizmo.register_raycasters_for_picking();
#endif // ENABLE_RAYCAST_PICKING
// sucessful activation of gizmo // sucessful activation of gizmo
return true; return true;
} }

View File

@ -213,7 +213,9 @@ public:
bool is_hiding_instances() const; bool is_hiding_instances() const;
void render_current_gizmo() const; void render_current_gizmo() const;
#if !ENABLE_RAYCAST_PICKING
void render_current_gizmo_for_picking_pass() const; void render_current_gizmo_for_picking_pass() const;
#endif // !ENABLE_RAYCAST_PICKING
void render_painter_gizmo(); void render_painter_gizmo();
void render_overlay(); void render_overlay();

View File

@ -33,28 +33,48 @@ SceneRaycaster::SceneRaycaster() {
#endif // ENABLE_RAYCAST_PICKING_DEBUG #endif // ENABLE_RAYCAST_PICKING_DEBUG
} }
int SceneRaycaster::add_raycaster(EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo) void SceneRaycaster::add_raycaster(EType type, PickingId id, const MeshRaycaster& raycaster, const Transform3d& trafo)
{ {
switch (type) { switch (type) {
case EType::Bed: { case EType::Bed: {
m_bed.emplace_back(encode_id(type, id), raycaster, trafo); m_bed.emplace_back(encode_id(type, id), raycaster, trafo);
return m_bed.size() - 1; break;
} }
case EType::Volume: { case EType::Volume: {
m_volumes.emplace_back(encode_id(type, id), raycaster, trafo); m_volumes.emplace_back(encode_id(type, id), raycaster, trafo);
return m_volumes.size() - 1; break;
} }
case EType::Gizmo: { case EType::Gizmo: {
m_gizmos.emplace_back(encode_id(type, id), raycaster, trafo); m_gizmos.emplace_back(encode_id(type, id), raycaster, trafo);
return m_gizmos.size() - 1; break;
} }
default: { break; }
}; };
// signal error
return -1;
} }
void SceneRaycaster::set_raycaster_active_state(EType type, int id, bool active) void SceneRaycaster::remove_raycasters(EType type, PickingId id)
{
std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type);
auto it = raycasters->begin();
while (it != raycasters->end()) {
if (it->get_id() == encode_id(type, id))
it = raycasters->erase(it);
else
++it;
}
}
void SceneRaycaster::remove_raycasters(EType type)
{
switch (type) {
case EType::Bed: { m_bed.clear(); break; }
case EType::Volume: { m_volumes.clear(); break; }
case EType::Gizmo: { m_gizmos.clear(); break; }
default: { break; }
};
}
void SceneRaycaster::set_raycaster_active_state(EType type, PickingId id, bool active)
{ {
std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type); std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type);
for (SceneRaycasterItem& item : *raycasters) { for (SceneRaycasterItem& item : *raycasters) {
@ -65,7 +85,7 @@ void SceneRaycaster::set_raycaster_active_state(EType type, int id, bool active)
} }
} }
void SceneRaycaster::set_raycaster_transform(EType type, int id, const Transform3d& trafo) void SceneRaycaster::set_raycaster_transform(EType type, PickingId id, const Transform3d& trafo)
{ {
std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type); std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type);
for (SceneRaycasterItem& item : *raycasters) { for (SceneRaycasterItem& item : *raycasters) {
@ -76,31 +96,6 @@ void SceneRaycaster::set_raycaster_transform(EType type, int id, const Transform
} }
} }
void SceneRaycaster::remove_raycaster(EType type, int id)
{
std::vector<SceneRaycasterItem>* raycasters = get_raycasters(type);
if (0 <= id && id < raycasters->size())
raycasters->erase(raycasters->begin() + id);
}
void SceneRaycaster::reset(EType type)
{
switch (type) {
case EType::Bed: {
m_bed.clear();
break;
}
case EType::Volume: {
m_volumes.clear();
break;
}
case EType::Gizmo: {
m_gizmos.clear();
break;
}
};
}
SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane) SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Camera& camera, const ClippingPlane* clipping_plane)
{ {
double closest_hit_squared_distance = std::numeric_limits<double>::max(); double closest_hit_squared_distance = std::numeric_limits<double>::max();
@ -140,11 +135,14 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
} }
}; };
test_raycasters(EType::Gizmo); if (!m_gizmos.empty())
if (!m_gizmos_on_top || ret.is_valid()) { test_raycasters(EType::Gizmo);
if (camera.is_looking_downward())
if (!m_gizmos_on_top || !ret.is_valid()) {
if (camera.is_looking_downward() && !m_bed.empty())
test_raycasters(EType::Bed); test_raycasters(EType::Bed);
test_raycasters(EType::Volume); if (!m_volumes.empty())
test_raycasters(EType::Volume);
} }
if (ret.is_valid()) if (ret.is_valid())

View File

@ -83,15 +83,12 @@ private:
public: public:
SceneRaycaster(); SceneRaycaster();
// returns the internal index of the added raycaster void add_raycaster(EType type, PickingId picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo);
// can be used with remove_raycaster() void remove_raycasters(EType type, PickingId id);
int add_raycaster(EType type, PickingId picking_id, const MeshRaycaster& raycaster, const Transform3d& trafo); void remove_raycasters(EType type);
void set_raycaster_active_state(EType type, PickingId picking_id, bool active); void set_raycaster_active_state(EType type, PickingId picking_id, bool active);
void set_raycaster_transform(EType type, PickingId picking_id, const Transform3d& trafo); void set_raycaster_transform(EType type, PickingId picking_id, const Transform3d& trafo);
// id: the value returned by add_raycaster()
void remove_raycaster(EType type, int id);
void reset(EType type);
void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; } void set_gizmos_on_top(bool value) { m_gizmos_on_top = value; }