FDM supports gizmo: slight code refactoring
This commit is contained in:
parent
ed55ebba55
commit
1a38d39f82
2 changed files with 80 additions and 84 deletions
|
@ -233,8 +233,8 @@ void GLGizmoFdmSupports::update_from_model_object()
|
||||||
for (int i : list)
|
for (int i : list)
|
||||||
m_selected_facets[volume_id][i] = type;
|
m_selected_facets[volume_id][i] = type;
|
||||||
}
|
}
|
||||||
update_vertex_buffers(mv, volume_id, FacetSupportType::ENFORCER);
|
update_vertex_buffers(mesh, volume_id, FacetSupportType::ENFORCER);
|
||||||
update_vertex_buffers(mv, volume_id, FacetSupportType::BLOCKER);
|
update_vertex_buffers(mesh, volume_id, FacetSupportType::BLOCKER);
|
||||||
|
|
||||||
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
m_neighbors[volume_id].resize(3 * mesh->its.indices.size());
|
||||||
|
|
||||||
|
@ -333,7 +333,7 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
Vec3f closest_hit = Vec3f::Zero();
|
Vec3f closest_hit = Vec3f::Zero();
|
||||||
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
double closest_hit_squared_distance = std::numeric_limits<double>::max();
|
||||||
size_t closest_facet = 0;
|
size_t closest_facet = 0;
|
||||||
size_t closest_hit_mesh_id = size_t(-1);
|
int closest_hit_mesh_id = -1;
|
||||||
|
|
||||||
// Transformations of individual meshes
|
// Transformations of individual meshes
|
||||||
std::vector<Transform3d> trafo_matrices;
|
std::vector<Transform3d> trafo_matrices;
|
||||||
|
@ -376,17 +376,22 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
// We now know where the ray hit, let's save it and cast another ray
|
// 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
|
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);
|
some_mesh_was_hit = true;
|
||||||
|
|
||||||
|
if (some_mesh_was_hit) {
|
||||||
|
// Now propagate the hits
|
||||||
|
mesh_id = -1;
|
||||||
|
const TriangleMesh* mesh = nullptr;
|
||||||
|
for (const ModelVolume* mv : mo->volumes) {
|
||||||
|
if (! mv->is_model_part())
|
||||||
|
continue;
|
||||||
|
++mesh_id;
|
||||||
|
if (mesh_id == closest_hit_mesh_id) {
|
||||||
|
mesh = &mv->mesh();
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Now propagate the hits
|
|
||||||
mesh_id = -1;
|
|
||||||
for (const ModelVolume* mv : mo->volumes) {
|
|
||||||
|
|
||||||
if (! mv->is_model_part())
|
|
||||||
continue;
|
|
||||||
|
|
||||||
++mesh_id;
|
|
||||||
bool update_both = false;
|
bool update_both = false;
|
||||||
|
|
||||||
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
const Transform3d& trafo_matrix = trafo_matrices[mesh_id];
|
||||||
|
@ -397,98 +402,90 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
const float avg_scaling = (sf(0) + sf(1) + sf(2))/3.;
|
||||||
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
const float limit = pow(m_cursor_radius/avg_scaling , 2.f);
|
||||||
|
|
||||||
std::vector<size_t> new_facets;
|
const std::pair<Vec3f, size_t>& hit_and_facet = { closest_hit, closest_facet };
|
||||||
|
|
||||||
// For all hits on this mesh...
|
const std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
||||||
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 = &mv->mesh();
|
|
||||||
const std::vector<NeighborData>& neighbors = m_neighbors[mesh_id];
|
|
||||||
|
|
||||||
// Calculate direction from camera to the hit (in mesh coords):
|
// Calculate direction from camera to the hit (in mesh coords):
|
||||||
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
Vec3f dir = ((trafo_matrix.inverse() * camera.get_position()).cast<float>() - hit_and_facet.first).normalized();
|
||||||
|
|
||||||
// A lambda to calculate distance from the centerline:
|
// A lambda to calculate distance from the centerline:
|
||||||
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float {
|
auto squared_distance_from_line = [&hit_and_facet, &dir](const Vec3f& point) -> float {
|
||||||
Vec3f diff = hit_and_facet.first - point;
|
Vec3f diff = hit_and_facet.first - point;
|
||||||
return (diff - diff.dot(dir) * dir).squaredNorm();
|
return (diff - diff.dot(dir) * dir).squaredNorm();
|
||||||
};
|
};
|
||||||
|
|
||||||
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
// A lambda to determine whether this facet is potentionally visible (still can be obscured)
|
||||||
auto faces_camera = [&dir](const ModelVolume* mv, const size_t& facet) -> bool {
|
auto faces_camera = [&dir, &mesh](const size_t& facet) -> bool {
|
||||||
return (mv->mesh().stl.facet_start[facet].normal.dot(dir) > 0.);
|
return (mesh->stl.facet_start[facet].normal.dot(dir) > 0.);
|
||||||
};
|
};
|
||||||
// Now start with the facet the pointer points to and check all adjacent facets. neighbors vector stores
|
// 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
|
// 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.
|
// quickly found by finding a vertex in the list and read the respective facet ids.
|
||||||
std::vector<size_t> facets_to_select{hit_and_facet.second};
|
std::vector<size_t> facets_to_select{hit_and_facet.second};
|
||||||
NeighborData vertex = std::make_pair(0, 0);
|
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
|
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
|
size_t facet_idx = 0; // index into facets_to_select
|
||||||
auto it = neighbors.end();
|
auto it = neighbors.end();
|
||||||
while (facet_idx < facets_to_select.size()) {
|
while (facet_idx < facets_to_select.size()) {
|
||||||
size_t facet = facets_to_select[facet_idx];
|
size_t facet = facets_to_select[facet_idx];
|
||||||
if (! visited[facet]) {
|
if (! visited[facet]) {
|
||||||
// check all three vertices and in case they're close enough, find the remaining facets
|
// check all three vertices and in case they're close enough, find the remaining facets
|
||||||
// and add them to the list to be proccessed later
|
// and add them to the list to be proccessed later
|
||||||
for (size_t i=0; i<3; ++i) {
|
for (size_t i=0; i<3; ++i) {
|
||||||
vertex.first = mesh->its.indices[facet](i); // vertex index
|
vertex.first = mesh->its.indices[facet](i); // vertex index
|
||||||
float dist = squared_distance_from_line(mesh->its.vertices[vertex.first]);
|
float dist = squared_distance_from_line(mesh->its.vertices[vertex.first]);
|
||||||
if (dist < limit) {
|
if (dist < limit) {
|
||||||
it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex);
|
it = std::lower_bound(neighbors.begin(), neighbors.end(), vertex);
|
||||||
while (it != neighbors.end() && it->first == vertex.first) {
|
while (it != neighbors.end() && it->first == vertex.first) {
|
||||||
if (it->second != facet && faces_camera(mv, it->second))
|
if (it->second != facet && faces_camera(it->second))
|
||||||
facets_to_select.push_back(it->second);
|
facets_to_select.push_back(it->second);
|
||||||
++it;
|
++it;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
visited[facet] = true;
|
|
||||||
}
|
}
|
||||||
++facet_idx;
|
visited[facet] = true;
|
||||||
}
|
}
|
||||||
|
++facet_idx;
|
||||||
|
}
|
||||||
|
|
||||||
//std::vector<size_t> new_facets;
|
std::vector<size_t> new_facets;
|
||||||
//new_facets.clear();
|
new_facets.reserve(facets_to_select.size());
|
||||||
new_facets.reserve(facets_to_select.size());
|
|
||||||
|
|
||||||
// Now just select all facets that passed and remember which
|
// Now just select all facets that passed and remember which
|
||||||
// ones have really changed state.
|
// ones have really changed state.
|
||||||
for (size_t next_facet : facets_to_select) {
|
for (size_t next_facet : facets_to_select) {
|
||||||
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
FacetSupportType& facet = m_selected_facets[mesh_id][next_facet];
|
||||||
|
|
||||||
if (facet != new_state) {
|
if (facet != new_state) {
|
||||||
if (facet != FacetSupportType::NONE) {
|
if (facet != FacetSupportType::NONE) {
|
||||||
// this triangle is currently in the other VBA.
|
// this triangle is currently in the other VBA.
|
||||||
// Both VBAs need to be refreshed.
|
// Both VBAs need to be refreshed.
|
||||||
update_both = true;
|
update_both = true;
|
||||||
}
|
|
||||||
facet = new_state;
|
|
||||||
new_facets.push_back(next_facet);
|
|
||||||
}
|
}
|
||||||
|
facet = new_state;
|
||||||
|
new_facets.push_back(next_facet);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (! new_facets.empty()) {
|
if (! new_facets.empty()) {
|
||||||
if (new_state != FacetSupportType::NONE) {
|
if (new_state != FacetSupportType::NONE) {
|
||||||
// append triangles into the respective VBA
|
// append triangles into the respective VBA
|
||||||
update_vertex_buffers(mv, mesh_id, new_state, &new_facets);
|
update_vertex_buffers(mesh, mesh_id, new_state, &new_facets);
|
||||||
if (update_both) {
|
if (update_both) {
|
||||||
auto other = new_state == FacetSupportType::ENFORCER
|
auto other = new_state == FacetSupportType::ENFORCER
|
||||||
? FacetSupportType::BLOCKER
|
? FacetSupportType::BLOCKER
|
||||||
: FacetSupportType::ENFORCER;
|
: FacetSupportType::ENFORCER;
|
||||||
update_vertex_buffers(mv, mesh_id, other); // regenerate the other VBA
|
update_vertex_buffers(mesh, mesh_id, other); // regenerate the other VBA
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
update_vertex_buffers(mv, mesh_id, FacetSupportType::ENFORCER);
|
update_vertex_buffers(mesh, mesh_id, FacetSupportType::ENFORCER);
|
||||||
update_vertex_buffers(mv, mesh_id, FacetSupportType::BLOCKER);
|
update_vertex_buffers(mesh, mesh_id, FacetSupportType::BLOCKER);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (some_mesh_was_hit)
|
|
||||||
{
|
|
||||||
if (m_button_down == Button::None)
|
if (m_button_down == Button::None)
|
||||||
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
m_button_down = ((action == SLAGizmoEventType::LeftDown) ? Button::Left : Button::Right);
|
||||||
return true;
|
return true;
|
||||||
|
@ -516,13 +513,11 @@ bool GLGizmoFdmSupports::gizmo_event(SLAGizmoEventType action, const Vec2d& mous
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void GLGizmoFdmSupports::update_vertex_buffers(const ModelVolume* mv,
|
void GLGizmoFdmSupports::update_vertex_buffers(const TriangleMesh* mesh,
|
||||||
int mesh_id,
|
int mesh_id,
|
||||||
FacetSupportType type,
|
FacetSupportType type,
|
||||||
const std::vector<size_t>* new_facets)
|
const std::vector<size_t>* new_facets)
|
||||||
{
|
{
|
||||||
const TriangleMesh* mesh = &mv->mesh();
|
|
||||||
|
|
||||||
std::vector<GLIndexedVertexArray>& ivas = m_ivas[mesh_id][type == FacetSupportType::ENFORCER ? 0 : 1];
|
std::vector<GLIndexedVertexArray>& ivas = m_ivas[mesh_id][type == FacetSupportType::ENFORCER ? 0 : 1];
|
||||||
|
|
||||||
// lambda to push facet into vertex buffer
|
// lambda to push facet into vertex buffer
|
||||||
|
@ -598,8 +593,8 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool overwr
|
||||||
? FacetSupportType::BLOCKER
|
? FacetSupportType::BLOCKER
|
||||||
: FacetSupportType::ENFORCER;
|
: FacetSupportType::ENFORCER;
|
||||||
}
|
}
|
||||||
update_vertex_buffers(mv, mesh_id, FacetSupportType::ENFORCER);
|
update_vertex_buffers(&mv->mesh(), mesh_id, FacetSupportType::ENFORCER);
|
||||||
update_vertex_buffers(mv, mesh_id, FacetSupportType::BLOCKER);
|
update_vertex_buffers(&mv->mesh(), mesh_id, FacetSupportType::BLOCKER);
|
||||||
}
|
}
|
||||||
|
|
||||||
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
Plater::TakeSnapshot(wxGetApp().plater(), block ? _L("Block supports by angle")
|
||||||
|
@ -669,8 +664,8 @@ void GLGizmoFdmSupports::on_render_input_window(float x, float y, float bottom_l
|
||||||
if (mv->is_model_part()) {
|
if (mv->is_model_part()) {
|
||||||
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
m_selected_facets[idx].assign(m_selected_facets[idx].size(), FacetSupportType::NONE);
|
||||||
mv->m_supported_facets.clear();
|
mv->m_supported_facets.clear();
|
||||||
update_vertex_buffers(mv, idx, FacetSupportType::ENFORCER);
|
update_vertex_buffers(&mv->mesh(), idx, FacetSupportType::ENFORCER);
|
||||||
update_vertex_buffers(mv, idx, FacetSupportType::BLOCKER);
|
update_vertex_buffers(&mv->mesh(), idx, FacetSupportType::BLOCKER);
|
||||||
m_parent.set_as_dirty();
|
m_parent.set_as_dirty();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,11 +38,12 @@ private:
|
||||||
// other triangles. Enforcers and blockers are of course separate.
|
// other triangles. Enforcers and blockers are of course separate.
|
||||||
std::vector<std::array<std::vector<GLIndexedVertexArray>, 2>> m_ivas;
|
std::vector<std::array<std::vector<GLIndexedVertexArray>, 2>> m_ivas;
|
||||||
|
|
||||||
void update_vertex_buffers(const ModelVolume* mv,
|
void update_vertex_buffers(const TriangleMesh* mesh,
|
||||||
int mesh_id,
|
int mesh_id,
|
||||||
FacetSupportType type, // enforcers / blockers
|
FacetSupportType type, // enforcers / blockers
|
||||||
const std::vector<size_t>* new_facets = nullptr); // nullptr -> regenerate all
|
const std::vector<size_t>* new_facets = nullptr); // nullptr -> regenerate all
|
||||||
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
GLGizmoFdmSupports(GLCanvas3D& parent, const std::string& icon_filename, unsigned int sprite_id);
|
||||||
~GLGizmoFdmSupports() override;
|
~GLGizmoFdmSupports() override;
|
||||||
|
|
Loading…
Reference in a new issue