Tech ENABLE_RAYCAST_PICKING - Raytraced picking of volumes

This commit is contained in:
enricoturri1966 2022-06-10 14:56:15 +02:00
parent cfc3988b9f
commit 6c6713c4ad
5 changed files with 241 additions and 2 deletions

View file

@ -618,6 +618,9 @@ public:
// The triangular model.
const TriangleMesh& mesh() const { return *m_mesh.get(); }
#if ENABLE_RAYCAST_PICKING
std::shared_ptr<const TriangleMesh> mesh_ptr() const { return m_mesh; }
#endif // ENABLE_RAYCAST_PICKING
void set_mesh(const TriangleMesh &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }
void set_mesh(TriangleMesh &&mesh) { m_mesh = std::make_shared<const TriangleMesh>(std::move(mesh)); }
void set_mesh(const indexed_triangle_set &mesh) { m_mesh = std::make_shared<const TriangleMesh>(mesh); }

View file

@ -804,15 +804,24 @@ int GLVolumeCollection::load_object_volume(
const ModelVolume *model_volume = model_object->volumes[volume_idx];
const int extruder_id = model_volume->extruder_id();
const ModelInstance *instance = model_object->instances[instance_idx];
#if ENABLE_RAYCAST_PICKING
std::shared_ptr<const TriangleMesh> mesh = model_volume->mesh_ptr();
#else
const TriangleMesh &mesh = model_volume->mesh();
#endif // ENABLE_RAYCAST_PICKING
this->volumes.emplace_back(new GLVolume());
GLVolume& v = *this->volumes.back();
v.set_color(color_from_model_volume(*model_volume));
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_SMOOTH_NORMALS
v.model.init_from(mesh, true);
#else
#if ENABLE_RAYCAST_PICKING
v.model.init_from(*mesh);
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh);
#else
v.model.init_from(mesh);
#endif // ENABLE_RAYCAST_PICKING
#endif // ENABLE_SMOOTH_NORMALS
#else
#if ENABLE_SMOOTH_NORMALS
@ -877,8 +886,11 @@ void GLVolumeCollection::load_object_auxiliary(
v.model.init_from(mesh, true);
#else
v.model.init_from(mesh);
#endif // ENABLE_SMOOTH_NORMALS
v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
#if ENABLE_RAYCAST_PICKING
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
#endif // ENABLE_RAYCAST_PICKING
#endif // ENABLE_SMOOTH_NORMALS
#else
#if ENABLE_SMOOTH_NORMALS
v.indexed_vertex_array.load_mesh(mesh, true);
@ -941,8 +953,112 @@ int GLVolumeCollection::load_wipe_tower_preview(
// Too narrow tower would interfere with the teeth. The estimate is not precise anyway.
depth = std::max(depth, 10.f);
float min_width = 30.f;
#if ENABLE_RAYCAST_PICKING
const float scaled_brim_height = 0.2f / height;
#endif // ENABLE_RAYCAST_PICKING
// We'll now create the box with jagged edge. y-coordinates of the pre-generated model
// are shifted so that the front edge has y=0 and centerline of the back edge has y=depth:
#if ENABLE_RAYCAST_PICKING
// We split the box in three main pieces,
// the two laterals are identical and the central is the one containing the jagged geometry
// lateral parts generator
auto generate_lateral = [&](float min_x, float max_x) {
const std::vector<Vec3f> vertices = {
{ min_x, -(depth + brim_width), 0.0f },
{ max_x, -(depth + brim_width), 0.0f },
{ min_x, -(depth + brim_width), scaled_brim_height },
{ max_x, -(depth + brim_width), scaled_brim_height },
{ min_x, -depth, scaled_brim_height },
{ max_x, -depth, scaled_brim_height },
{ min_x, -depth, 1.0f },
{ max_x, -depth, 1.0f },
{ min_x, 0.0f, 1.0f },
{ max_x, 0.0f, 1.0f },
{ min_x, 0.0f, scaled_brim_height },
{ max_x, 0.0f, scaled_brim_height },
{ min_x, brim_width, scaled_brim_height },
{ max_x, brim_width, scaled_brim_height },
{ min_x, brim_width, 0.0f },
{ max_x, brim_width, 0.0f }
};
const std::vector<Vec3i> triangles = {
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 5 }, { 2, 5, 4 }, { 4, 5, 7 }, { 4, 7, 6 }, { 6, 7, 9 }, { 6, 9, 8 },
{ 8, 9, 11 }, { 8, 11, 10 }, { 10, 11, 13 }, { 10, 13, 12 }, { 12, 13, 15 }, { 12, 15, 14 }, { 14, 15, 1 }, { 14, 1, 0 }
};
indexed_triangle_set its;
its.vertices.reserve(vertices.size());
for (const Vec3f& v : vertices) {
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
}
its.indices.reserve(triangles.size());
for (const Vec3i& t : triangles) {
its.indices.emplace_back(t);
}
return its;
};
// central parts generator
auto generate_central = [&]() {
const std::vector<Vec3f> vertices = {
{ 38.453f, -(depth + brim_width), 0.0f },
{ 61.547f, -(depth + brim_width), 0.0f },
{ 38.453f, -(depth + brim_width), scaled_brim_height },
{ 61.547f, -(depth + brim_width), scaled_brim_height },
{ 38.453f, -depth, scaled_brim_height },
{ 61.547f, -depth, scaled_brim_height },
{ 38.453f, -depth, 1.0f },
{ 61.547f, -depth, 1.0f },
{ 38.453f, 0.0f, 1.0f },
{ 38.453f + 0.57735f * brim_width, brim_width, 1.0f },
{ 44.2265f, 10.0f, 1.0f },
{ 50.0f - 0.57735f * brim_width, brim_width, 1.0f },
{ 50.0f, 0.0f, 1.0f },
{ 55.7735f, -10.0f, 1.0f },
{ 61.547f, 0.0f, 1.0f },
{ 38.453f, 0.0f, scaled_brim_height },
{ 38.453f, brim_width, scaled_brim_height },
{ 38.453f + 0.57735f * brim_width, brim_width, scaled_brim_height },
{ 50.0f - 0.57735f * brim_width, brim_width, scaled_brim_height },
{ 50.0f, 0.0f, scaled_brim_height },
{ 55.7735f, -10.0f, scaled_brim_height },
{ 61.547f, 0.0f, scaled_brim_height },
{ 61.547f, brim_width, scaled_brim_height },
{ 38.453f, brim_width, 0.0f },
{ 38.453f + 0.57735f * brim_width, brim_width, 0.0f },
{ 44.2265f, 10.0f, 0.0f },
{ 50.0f - 0.57735f * brim_width, brim_width, 0.0f },
{ 61.547f, brim_width, 0.0f }
};
const std::vector<Vec3i> triangles = {
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 5 }, { 2, 5, 4 }, { 4, 5, 7 }, { 4, 7, 6 }, { 7, 14, 13 }, { 7, 13, 6 },
{ 6, 13, 12 }, { 6, 12, 8 }, { 8, 12, 11 }, { 8, 11, 9 }, { 9, 11, 10 }, { 18, 19, 22 }, { 22, 19, 21 }, { 19, 20, 21 },
{ 15, 17, 16 }, { 17, 15, 8 }, { 17, 8, 9 }, { 21, 13, 14 }, { 21, 20, 13 }, { 20, 19, 12 }, { 20, 12, 13 }, { 19, 18, 11 },
{ 19, 11, 12 }, { 27, 26, 18 }, { 27, 18, 22 }, { 26, 25, 18 }, { 18, 25, 11 }, { 11, 25, 10 }, { 25, 24, 17 }, { 25, 17, 9 },
{ 25, 9, 10 }, { 24, 23, 16 }, { 24, 16, 17 }, { 1, 26, 27 }, { 1, 23, 26 }, { 1, 0, 23 }, { 0, 23, 24 }, { 24, 25, 26 }
};
indexed_triangle_set its;
its.vertices.reserve(vertices.size());
for (const Vec3f& v : vertices) {
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
}
its.indices.reserve(triangles.size());
for (const Vec3i& t : triangles) {
its.indices.emplace_back(t);
}
return its;
};
TriangleMesh tooth_mesh;
tooth_mesh.merge(TriangleMesh(std::move(generate_lateral(0.0f, 38.453f))));
tooth_mesh.merge(TriangleMesh(std::move(generate_central())));
tooth_mesh.merge(TriangleMesh(std::move(generate_lateral(61.547f, 100.0f))));
#else
float out_points_idx[][3] = { { 0, -depth, 0 }, { 0, 0, 0 }, { 38.453f, 0, 0 }, { 61.547f, 0, 0 }, { 100.0f, 0, 0 }, { 100.0f, -depth, 0 }, { 55.7735f, -10.0f, 0 }, { 44.2265f, 10.0f, 0 },
{ 38.453f, 0, 1 }, { 0, 0, 1 }, { 0, -depth, 1 }, { 100.0f, -depth, 1 }, { 100.0f, 0, 1 }, { 61.547f, 0, 1 }, { 55.7735f, -10.0f, 1 }, { 44.2265f, 10.0f, 1 } };
static constexpr const int out_facets_idx[][3] = {
@ -957,6 +1073,7 @@ int GLVolumeCollection::load_wipe_tower_preview(
for (const int *face : out_facets_idx)
its.indices.emplace_back(face);
TriangleMesh tooth_mesh(std::move(its));
#endif // ENABLE_RAYCAST_PICKING
// We have the mesh ready. It has one tooth and width of min_width. We will now
// append several of these together until we are close to the required width
@ -964,24 +1081,108 @@ int GLVolumeCollection::load_wipe_tower_preview(
size_t n = std::max(1, int(width / min_width)); // How many shall be merged?
for (size_t i = 0; i < n; ++i) {
mesh.merge(tooth_mesh);
#if ENABLE_RAYCAST_PICKING
tooth_mesh.translate(100.0f, 0.0f, 0.0f);
#else
tooth_mesh.translate(min_width, 0.f, 0.f);
#endif // ENABLE_RAYCAST_PICKING
}
#if ENABLE_RAYCAST_PICKING
// Now we add the caps along the X axis
const float scaled_brim_width_x = brim_width * n * width / min_width;
auto generate_negx_cap = [&]() {
const std::vector<Vec3f> vertices = {
{ -scaled_brim_width_x, -(depth + brim_width), 0.0f },
{ 0.0f, -(depth + brim_width), 0.0f },
{ -scaled_brim_width_x, -(depth + brim_width), scaled_brim_height },
{ 0.0f, -(depth + brim_width), scaled_brim_height },
{ 0.0f, -depth, scaled_brim_height },
{ 0.0f, -depth, 1.0f },
{ 0.0f, 0.0f, 1.0f },
{ 0.0f, 0.0f, scaled_brim_height },
{ 0.0f, brim_width, scaled_brim_height },
{ -scaled_brim_width_x, brim_width, scaled_brim_height },
{ 0.0f, brim_width, 0.0f },
{ -scaled_brim_width_x, brim_width, 0.0f }
};
const std::vector<Vec3i> triangles = {
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 4 }, { 2, 4, 9 }, { 9, 4, 7 }, { 9, 7, 8 }, { 9, 8, 10 }, { 9, 10, 11 },
{ 11, 10, 1 }, { 11, 1, 0 }, { 11, 0, 2 }, { 11, 2, 9 }, { 7, 4, 5 }, { 7, 5, 6 }
};
indexed_triangle_set its;
its.vertices.reserve(vertices.size());
for (const Vec3f& v : vertices) {
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
}
its.indices.reserve(triangles.size());
for (const Vec3i& t : triangles) {
its.indices.emplace_back(t);
}
return its;
};
auto generate_posx_cap = [&]() {
const float posx_cap_x = n * 100.0f;
const std::vector<Vec3f> vertices = {
{ posx_cap_x, -(depth + brim_width), 0.0f },
{ posx_cap_x + scaled_brim_width_x, -(depth + brim_width), 0.0f },
{ posx_cap_x, -(depth + brim_width), scaled_brim_height },
{ posx_cap_x + scaled_brim_width_x, -(depth + brim_width), scaled_brim_height },
{ posx_cap_x, -depth, scaled_brim_height },
{ posx_cap_x, -depth, 1.0f },
{ posx_cap_x, 0.0f, 1.0f },
{ posx_cap_x, 0.0f, scaled_brim_height },
{ posx_cap_x, brim_width, scaled_brim_height },
{ posx_cap_x + scaled_brim_width_x, brim_width, scaled_brim_height },
{ posx_cap_x, brim_width, 0.0f },
{ posx_cap_x + scaled_brim_width_x, brim_width, 0.0f }
};
const std::vector<Vec3i> triangles = {
{ 0, 1, 3 }, { 0, 3, 2 }, { 2, 3, 4 }, { 4, 3, 9 }, { 4, 9, 7 }, { 7, 9, 8 }, { 8, 9, 11 }, { 8, 11, 10 },
{ 10, 11, 1 }, { 10, 1, 0 }, { 1, 11, 9 }, { 1, 9, 3 }, { 4, 7, 6 }, { 4, 6, 5 }
};
indexed_triangle_set its;
its.vertices.reserve(vertices.size());
for (const Vec3f& v : vertices) {
its.vertices.emplace_back(v.x(), v.y() + depth, v.z());
}
its.indices.reserve(triangles.size());
for (const Vec3i& t : triangles) {
its.indices.emplace_back(t);
}
return its;
};
mesh.merge(TriangleMesh(std::move(generate_negx_cap())));
mesh.merge(TriangleMesh(std::move(generate_posx_cap())));
mesh.scale(Vec3f(width / (n * 100.0f), 1.0f, height)); // Scaling to proper width
#else
mesh.scale(Vec3f(width / (n * min_width), 1.f, height)); // Scaling to proper width
#endif // ENABLE_RAYCAST_PICKING
}
else
mesh = make_cube(width, depth, height);
#if !ENABLE_RAYCAST_PICKING
// We'll make another mesh to show the brim (fixed layer height):
TriangleMesh brim_mesh = make_cube(width + 2.f * brim_width, depth + 2.f * brim_width, 0.2f);
brim_mesh.translate(-brim_width, -brim_width, 0.f);
mesh.merge(brim_mesh);
#endif // !ENABLE_RAYCAST_PICKING
volumes.emplace_back(new GLVolume(color));
GLVolume& v = *volumes.back();
#if ENABLE_LEGACY_OPENGL_REMOVAL
v.model.init_from(mesh);
v.model.set_color(color);
#if ENABLE_RAYCAST_PICKING
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
#endif // ENABLE_RAYCAST_PICKING
#else
v.indexed_vertex_array.load_mesh(mesh);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL

View file

@ -10,6 +10,9 @@
#include "libslic3r/Color.hpp"
#include "GLModel.hpp"
#if ENABLE_RAYCAST_PICKING
#include "MeshUtils.hpp"
#endif // ENABLE_RAYCAST_PICKING
#include <functional>
#include <optional>
@ -392,6 +395,10 @@ public:
#if ENABLE_LEGACY_OPENGL_REMOVAL
GUI::GLModel model;
#if ENABLE_RAYCAST_PICKING
// raycaster used for picking
std::unique_ptr<GUI::MeshRaycaster> mesh_raycaster;
#endif // ENABLE_RAYCAST_PICKING
#else
// Interleaved triangles & normals with indexed triangles & quads.
GLIndexedVertexArray indexed_vertex_array;

View file

@ -2229,6 +2229,9 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
#else
#if ENABLE_LEGACY_OPENGL_REMOVAL
volume.model.init_from(mesh);
#if ENABLE_RAYCAST_PICKING
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
#endif // ENABLE_RAYCAST_PICKING
#else
volume.indexed_vertex_array.load_mesh(mesh);
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@ -2244,7 +2247,13 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
#else
#if ENABLE_LEGACY_OPENGL_REMOVAL
#if ENABLE_RAYCAST_PICKING
const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
volume.model.init_from(new_mesh);
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
#else
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
#endif // ENABLE_RAYCAST_PICKING
#else
volume.indexed_vertex_array.load_mesh(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh());
#endif // ENABLE_LEGACY_OPENGL_REMOVAL
@ -2392,6 +2401,15 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
manip->set_dirty();
}
#if ENABLE_RAYCAST_PICKING
// refresh volume raycasters for picking
m_scene_raycaster.reset(SceneRaycaster::EType::Volume);
for (size_t i = 0; i < m_volumes.volumes.size(); ++i) {
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());
}
#endif // ENABLE_RAYCAST_PICKING
// and force this canvas to be redrawn.
m_dirty = true;
}
@ -3658,6 +3676,10 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
}
}
else if (evt.LeftUp() || evt.MiddleUp() || evt.RightUp()) {
#if ENABLE_RAYCAST_PICKING
m_mouse.position = pos.cast<double>();
#endif // ENABLE_RAYCAST_PICKING
if (m_layers_editing.state != LayersEditing::Unknown) {
m_layers_editing.state = LayersEditing::Unknown;
_stop_timer();
@ -3682,7 +3704,9 @@ void GLCanvas3D::on_mouse(wxMouseEvent& evt)
deselect_all();
}
else if (evt.RightUp()) {
#if !ENABLE_RAYCAST_PICKING
m_mouse.position = pos.cast<double>();
#endif // !ENABLE_RAYCAST_PICKING
// forces a frame render to ensure that m_hover_volume_idxs is updated even when the user right clicks while
// the context menu is already shown
render();

View file

@ -112,7 +112,9 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
return ret;
};
#if ENABLE_RAYCAST_PICKING_DEBUG
m_last_hit.reset();
#endif // ENABLE_RAYCAST_PICKING_DEBUG
HitResult ret;
@ -148,7 +150,9 @@ SceneRaycaster::HitResult SceneRaycaster::hit(const Vec2d& mouse_pos, const Came
if (ret.is_valid())
ret.raycaster_id = decode_id(ret.type, ret.raycaster_id);
#if ENABLE_RAYCAST_PICKING_DEBUG
m_last_hit = ret;
#endif // ENABLE_RAYCAST_PICKING_DEBUG
return ret;
}
@ -172,7 +176,7 @@ void SceneRaycaster::render_hit(const Camera& camera)
Transform3d m = Transform3d::Identity();
m.matrix().block(0, 0, 3, 3) = q.setFromTwoVectors(Vec3d::UnitZ(), m_last_hit.value().normal.cast<double>()).toRotationMatrix();
const Transform3d line_view_model_matrix = sphere_view_model_matrix * m * Geometry::scale_transform(6.25);
const Transform3d line_view_model_matrix = sphere_view_model_matrix * m * Geometry::scale_transform(10.0);
shader->set_uniform("view_model_matrix", line_view_model_matrix);
m_line.render();