WIP
This commit is contained in:
parent
f275461354
commit
6d23c08d00
2 changed files with 61 additions and 45 deletions
|
@ -8,6 +8,7 @@
|
|||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/MeshUtils.hpp"
|
||||
#include "slic3r/GUI/PresetBundle.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
|
||||
|
||||
|
||||
|
@ -278,31 +279,6 @@ void GLGizmoFdmSupports::update_mesh()
|
|||
|
||||
|
||||
|
||||
// Unprojects the mouse position on the mesh and saves hit facet index into facet_idx
|
||||
// Position of the hit in mesh coords is copied into *position, if provided.
|
||||
// Returns false if no intersection was found, true otherwise.
|
||||
bool GLGizmoFdmSupports::unproject_on_mesh(size_t mesh_id, const Vec2d& mouse_pos, size_t& facet_idx, Vec3f* position)
|
||||
{
|
||||
// if the gizmo doesn't have the V, F structures for igl, calculate them first:
|
||||
//if (! m_meshes_raycaster[mesh_id])
|
||||
// update_mesh();
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Transform3d trafo_matrix =
|
||||
m_model_object->instances[selection.get_instance_idx()]->get_transformation().get_matrix() *
|
||||
m_model_object->volumes[mesh_id]->get_matrix();
|
||||
|
||||
// The raycaster query
|
||||
Vec3f hit;
|
||||
Vec3f normal;
|
||||
if (m_meshes_raycaster[mesh_id]->unproject_on_mesh(mouse_pos, trafo_matrix, camera, hit, normal, m_clipping_plane.get(), &facet_idx)) {
|
||||
if (position)
|
||||
*position = hit;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
bool operator<(const GLGizmoFdmSupports::NeighborData& a, const GLGizmoFdmSupports::NeighborData& b) {
|
||||
return a.first < b.first;
|
||||
|
@ -333,32 +309,74 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
}
|
||||
|
||||
if (action == SLAGizmoEventType::LeftDown || (action == SLAGizmoEventType::Dragging && m_wait_for_up_event)) {
|
||||
size_t facet = 0;
|
||||
Vec3f hit_pos;
|
||||
bool mesh_was_hit = false;
|
||||
bool select = ! shift_down;
|
||||
const Camera& camera = m_parent.get_camera();
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const Transform3d& instance_trafo = m_model_object->instances[selection.get_instance_idx()]->get_transformation().get_matrix();
|
||||
|
||||
for (size_t mesh_id=0; mesh_id<m_model_object->volumes.size(); ++mesh_id) {
|
||||
if (unproject_on_mesh(mesh_id, mouse_position, facet, &hit_pos)) {
|
||||
mesh_was_hit = true;
|
||||
// Precalculate transformations of individual meshes
|
||||
std::vector<Transform3d> trafo_matrices;
|
||||
for (const ModelVolume* mv : m_model_object->volumes)
|
||||
trafo_matrices.push_back(instance_trafo * mv->get_matrix());
|
||||
|
||||
std::vector<std::vector<std::pair<Vec3f, size_t>>> hit_positions_and_facet_ids(m_meshes.size());
|
||||
bool some_mesh_was_hit = false;
|
||||
|
||||
// Cast a ray on all meshes, pick the closest hit and save it for the respective mesh
|
||||
Vec3f normal = Vec3f::Zero();
|
||||
Vec3f hit = Vec3f::Zero();
|
||||
size_t facet = 0;
|
||||
Vec3f closest_hit = Vec3f::Zero();
|
||||
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||
size_t closest_facet = 0;
|
||||
size_t closest_hit_mesh_id = size_t(-1);
|
||||
|
||||
for (size_t mesh_id=0; mesh_id<m_meshes.size(); ++mesh_id) {
|
||||
|
||||
if (m_meshes_raycaster[mesh_id]->unproject_on_mesh(
|
||||
mouse_position,
|
||||
trafo_matrices[mesh_id],
|
||||
camera,
|
||||
hit,
|
||||
normal,
|
||||
m_clipping_plane.get(),
|
||||
&facet))
|
||||
{
|
||||
// Is this hit the closest to the camera so far?
|
||||
double hit_squared_distance = (camera.get_position()-trafo_matrices[mesh_id]*hit.cast<double>()).squaredNorm();
|
||||
if (hit_squared_distance < closest_hit_squared_distance) {
|
||||
closest_hit_squared_distance = hit_squared_distance;
|
||||
closest_facet = facet;
|
||||
closest_hit_mesh_id = mesh_id;
|
||||
closest_hit = hit;
|
||||
}
|
||||
}
|
||||
}
|
||||
// We now know where the ray hit, let's save it and cast another ray
|
||||
if (closest_hit_mesh_id != size_t(-1)) // only if there is at least one hit
|
||||
hit_positions_and_facet_ids[closest_hit_mesh_id].emplace_back(closest_hit, closest_facet);
|
||||
|
||||
|
||||
// Now propagate the hits
|
||||
for (size_t mesh_id=0; mesh_id<m_meshes.size(); ++mesh_id) {
|
||||
// For all hits on this mesh...
|
||||
for (const std::pair<Vec3f, size_t>& hit_and_facet : hit_positions_and_facet_ids[mesh_id]) {
|
||||
some_mesh_was_hit = true;
|
||||
const TriangleMesh* mesh = m_meshes[mesh_id];
|
||||
std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
||||
|
||||
bool select = ! shift_down;
|
||||
|
||||
// Calculate direction from camera to the hit (in mesh coords):
|
||||
const Selection& selection = m_parent.get_selection();
|
||||
const GLVolume* volume = selection.get_volume(*selection.get_volume_idxs().begin());
|
||||
Geometry::Transformation trafo = volume->get_instance_transformation();
|
||||
trafo.set_offset(trafo.get_offset());
|
||||
Vec3f dir = ((trafo.get_matrix().inverse() * m_parent.get_camera().get_position()).cast<float>() - hit_pos).normalized();
|
||||
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
||||
|
||||
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
||||
|
||||
// Calculate how far can a point be from the line (in mesh coords).
|
||||
// FIXME: This should account for (possibly non-uniform) scaling of the mesh.
|
||||
float limit = pow(m_cursor_radius, 2.f);
|
||||
|
||||
// A lambda to calculate distance from the line:
|
||||
auto squared_distance_from_line = [&hit_pos, &dir](const Vec3f point) -> float {
|
||||
Vec3f diff = hit_pos - point;
|
||||
// A lambda to calculate distance from the centerline:
|
||||
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f point) -> float {
|
||||
Vec3f diff = hit_and_facet.first - point;
|
||||
return (diff - diff.dot(dir) * dir).squaredNorm();
|
||||
};
|
||||
|
||||
|
@ -369,7 +387,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
// Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores
|
||||
// pairs of vertex_idx - facet_idx and is sorted with respect to the former. Neighboring facet index can be
|
||||
// quickly found by finding a vertex in the list and read the respective facet ids.
|
||||
std::vector<size_t> facets_to_select{facet};
|
||||
std::vector<size_t> facets_to_select{hit_and_facet.second};
|
||||
NeighborData vertex = std::make_pair(0, 0);
|
||||
std::vector<bool> visited(m_selected_facets[mesh_id].size(), false); // keep track of facets we already processed
|
||||
size_t facet_idx = 0; // index into facets_to_select
|
||||
|
@ -401,7 +419,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
|||
}
|
||||
}
|
||||
|
||||
if (mesh_was_hit)
|
||||
if (some_mesh_was_hit)
|
||||
{
|
||||
m_wait_for_up_event = true;
|
||||
m_parent.set_as_dirty();
|
||||
|
|
|
@ -22,8 +22,6 @@ private:
|
|||
std::vector<ObjectID> m_volumes_ids;
|
||||
int m_active_instance = -1;
|
||||
float m_active_instance_bb_radius; // to cache the bb
|
||||
bool unproject_on_mesh(size_t mesh_id, const Vec2d& mouse_pos, size_t& facet_idx, Vec3f* position = nullptr);
|
||||
|
||||
|
||||
GLUquadricObj* m_quadric;
|
||||
|
||||
|
|
Loading…
Reference in a new issue