Implementation of ShortEdgeCollapse
Replaced QEC by edge collapse in occlusion computation
This commit is contained in:
parent
b5b39195f4
commit
1e7b4a6720
@ -205,6 +205,8 @@ add_library(libslic3r STATIC
|
||||
QuadricEdgeCollapse.cpp
|
||||
QuadricEdgeCollapse.hpp
|
||||
Semver.cpp
|
||||
ShortEdgeCollapse.cpp
|
||||
ShortEdgeCollapse.hpp
|
||||
ShortestPath.cpp
|
||||
ShortestPath.hpp
|
||||
SLAPrint.cpp
|
||||
|
@ -17,7 +17,7 @@
|
||||
#include "libslic3r/Layer.hpp"
|
||||
|
||||
#include "libslic3r/Geometry/Curves.hpp"
|
||||
#include "libslic3r/QuadricEdgeCollapse.hpp"
|
||||
#include "libslic3r/ShortEdgeCollapse.hpp"
|
||||
#include "libslic3r/TriangleSetSampling.hpp"
|
||||
|
||||
#include "libslic3r/Utils.hpp"
|
||||
@ -585,7 +585,8 @@ std::pair<size_t, size_t> find_previous_and_next_perimeter_point(const std::vect
|
||||
}
|
||||
|
||||
// Computes all global model info - transforms object, performs raycasting
|
||||
void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, std::function<void(void)> throw_if_canceled) {
|
||||
void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po,
|
||||
std::function<void(void)> throw_if_canceled) {
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: gather occlusion meshes: start";
|
||||
auto obj_transform = po->trafo_centered();
|
||||
@ -607,20 +608,19 @@ void compute_global_occlusion(GlobalModelInfo &result, const PrintObject *po, st
|
||||
}
|
||||
throw_if_canceled();
|
||||
|
||||
size_t negative_volumes_start_index = triangle_set.indices.size();
|
||||
its_merge(triangle_set, negative_volumes_set);
|
||||
its_transform(triangle_set, obj_transform);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: gather occlusion meshes: end";
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: decimate: start";
|
||||
float target_error = 1.0f;
|
||||
its_quadric_edge_collapse(triangle_set, 0, &target_error, throw_if_canceled);
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: decimate: end";
|
||||
<< "SeamPlacer: decimate: start";
|
||||
its_short_edge_collpase(triangle_set, 25000);
|
||||
its_short_edge_collpase(negative_volumes_set, 25000);
|
||||
|
||||
size_t negative_volumes_start_index = triangle_set.indices.size();
|
||||
its_merge(triangle_set, negative_volumes_set);
|
||||
its_transform(triangle_set, obj_transform);
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: decimate: end";
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug)
|
||||
<< "SeamPlacer: Compute visibility sample points: start";
|
||||
|
@ -122,9 +122,9 @@ struct PrintObjectSeamData
|
||||
class SeamPlacer {
|
||||
public:
|
||||
// Number of samples generated on the mesh. There are sqr_rays_per_sample_point*sqr_rays_per_sample_point rays casted from each samples
|
||||
static constexpr size_t raycasting_visibility_samples_count = 25000;
|
||||
static constexpr size_t raycasting_visibility_samples_count = 30000;
|
||||
//square of number of rays per sample point
|
||||
static constexpr size_t sqr_rays_per_sample_point = 8;
|
||||
static constexpr size_t sqr_rays_per_sample_point = 5;
|
||||
|
||||
// arm length used during angles computation
|
||||
static constexpr float polygon_local_angles_arm_distance = 0.3f;
|
||||
|
166
src/libslic3r/ShortEdgeCollapse.cpp
Normal file
166
src/libslic3r/ShortEdgeCollapse.cpp
Normal file
@ -0,0 +1,166 @@
|
||||
#include "ShortEdgeCollapse.hpp"
|
||||
|
||||
#include <unordered_map>
|
||||
#include <unordered_set>
|
||||
#include <random>
|
||||
#include <algorithm>
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_count) {
|
||||
std::unordered_map<size_t, size_t> vertices_index_mapping; // this map has two usages:
|
||||
// in the first step, it contains mapping from original vertex index to final vertex index (which is different from original only for removed vertices)
|
||||
|
||||
std::unordered_set<size_t> vertices_to_remove;
|
||||
std::unordered_set<size_t> faces_to_remove;
|
||||
std::vector<Vec3i> triangles_neighbors;
|
||||
std::vector<Vec3f> face_normals;
|
||||
std::vector<Vec3f> vertex_normals;
|
||||
std::vector<size_t> face_indices;
|
||||
std::random_device rd;
|
||||
std::mt19937 generator(rd());
|
||||
|
||||
float decimation_ratio = 1.0f;
|
||||
float edge_size = 0.2f;
|
||||
size_t triangle_count = mesh.indices.size();
|
||||
|
||||
while (triangle_count > target_triangle_count) {
|
||||
if (decimation_ratio < 0.4) {
|
||||
edge_size *= 1.5f;
|
||||
}
|
||||
if (decimation_ratio < 0.05) {
|
||||
edge_size *= 1.5f;
|
||||
}
|
||||
|
||||
float max_edge_len_squared = edge_size * edge_size;
|
||||
triangles_neighbors = its_face_neighbors_par(mesh);
|
||||
face_normals = its_face_normals(mesh);
|
||||
|
||||
vertex_normals.resize(mesh.vertices.size());
|
||||
face_indices.resize(mesh.indices.size());
|
||||
for (size_t face_idx = 0; face_idx < mesh.indices.size(); ++face_idx) {
|
||||
Vec3i t = mesh.indices[face_idx];
|
||||
Vec3f n = face_normals[face_idx];
|
||||
vertex_normals[t[0]] = n;
|
||||
vertex_normals[t[1]] = n;
|
||||
vertex_normals[t[2]] = n;
|
||||
|
||||
face_indices[face_idx] = face_idx;
|
||||
}
|
||||
|
||||
std::vector<float> min_vertex_score(mesh.vertices.size(), 1);
|
||||
for (size_t face_idx = 0; face_idx < mesh.indices.size(); ++face_idx) {
|
||||
Vec3i t = mesh.indices[face_idx];
|
||||
Vec3f n = face_normals[face_idx];
|
||||
min_vertex_score[t[0]] = std::min(min_vertex_score[t[0]], n.dot(vertex_normals[t[0]]));
|
||||
min_vertex_score[t[1]] = std::min(min_vertex_score[t[1]], n.dot(vertex_normals[t[1]]));
|
||||
min_vertex_score[t[2]] = std::min(min_vertex_score[t[2]], n.dot(vertex_normals[t[2]]));
|
||||
}
|
||||
|
||||
for (size_t vertex_index = 0; vertex_index < mesh.vertices.size(); ++vertex_index) {
|
||||
vertices_index_mapping[vertex_index] = vertex_index;
|
||||
}
|
||||
|
||||
std::shuffle(face_indices.begin(), face_indices.end(), generator);
|
||||
|
||||
for (const size_t &face_idx : face_indices) {
|
||||
if (faces_to_remove.find(face_idx) != faces_to_remove.end()) {
|
||||
continue;
|
||||
}
|
||||
for (size_t edge_idx = 0; edge_idx < 3; ++edge_idx) {
|
||||
size_t vertex_index_keep = mesh.indices[face_idx][edge_idx];
|
||||
size_t vertex_index_remove = mesh.indices[face_idx][(edge_idx + 1) % 3];
|
||||
|
||||
if ((mesh.vertices[vertex_index_keep] - mesh.vertices[vertex_index_remove]).squaredNorm()
|
||||
> max_edge_len_squared) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (min_vertex_score[vertex_index_remove] < min_vertex_score[vertex_index_keep]) {
|
||||
size_t tmp = vertex_index_keep;
|
||||
vertex_index_keep = vertex_index_remove;
|
||||
vertex_index_remove = tmp;
|
||||
}
|
||||
|
||||
if (min_vertex_score[vertex_index_remove] < -1.0f) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (vertices_to_remove.find(vertex_index_keep) != vertices_to_remove.end()
|
||||
|| vertices_to_remove.find(vertex_index_remove) != vertices_to_remove.end()) {
|
||||
break;
|
||||
}
|
||||
|
||||
int neighbor_face_idx = triangles_neighbors[face_idx][edge_idx];
|
||||
if (neighbor_face_idx > 0 && faces_to_remove.find(neighbor_face_idx) != faces_to_remove.end()) {
|
||||
continue;
|
||||
}
|
||||
|
||||
faces_to_remove.insert(face_idx);
|
||||
faces_to_remove.insert(neighbor_face_idx);
|
||||
vertices_to_remove.insert(vertex_index_remove);
|
||||
vertices_index_mapping[vertex_index_remove] = vertices_index_mapping[vertex_index_keep];
|
||||
min_vertex_score[vertex_index_keep] = -2.0;
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//flatten the mapping
|
||||
for (auto &pair : vertices_index_mapping) {
|
||||
while (vertices_index_mapping[pair.second] != pair.second) {
|
||||
pair.second = vertices_index_mapping[pair.second];
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec3f> new_vertices;
|
||||
new_vertices.reserve(mesh.vertices.size() - vertices_to_remove.size());
|
||||
for (size_t vertex_index = 0; vertex_index < mesh.vertices.size(); ++vertex_index) {
|
||||
if (vertices_to_remove.find(vertex_index) == vertices_to_remove.end()) { //not removed
|
||||
new_vertices.push_back(mesh.vertices[vertex_index]);
|
||||
assert(vertices_index_mapping[vertex_index] == vertex_index);
|
||||
vertices_index_mapping[vertex_index] = new_vertices.size() - 1;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<Vec3i> new_indices;
|
||||
new_indices.reserve(mesh.indices.size() - faces_to_remove.size());
|
||||
for (size_t face_idx = 0; face_idx < mesh.indices.size(); ++face_idx) {
|
||||
if (faces_to_remove.find(face_idx) != faces_to_remove.end()) {
|
||||
continue; //skip removed triangles
|
||||
}
|
||||
Vec3i new_triangle;
|
||||
for (int t_vertex_idx = 0; t_vertex_idx < 3; ++t_vertex_idx) {
|
||||
size_t orig_index = mesh.indices[face_idx][t_vertex_idx];
|
||||
if (vertices_to_remove.find(orig_index) == vertices_to_remove.end()) { //this vertex was not removed
|
||||
new_triangle[t_vertex_idx] = vertices_index_mapping[orig_index];
|
||||
} else { // this vertex was removed, so use the vertex mapping points to
|
||||
new_triangle[t_vertex_idx] = vertices_index_mapping[vertices_index_mapping[orig_index]];
|
||||
}
|
||||
}
|
||||
if (new_triangle[0] == new_triangle[1] || new_triangle[1] == new_triangle[2]
|
||||
|| new_triangle[2] == new_triangle[0]) {
|
||||
continue; //skip degenerate
|
||||
}
|
||||
new_indices.push_back(new_triangle);
|
||||
}
|
||||
|
||||
decimation_ratio = float(faces_to_remove.size()) / float(mesh.indices.size());
|
||||
|
||||
// std::cout << " DECIMATION RATIO: " << decimation_ratio << std::endl;
|
||||
|
||||
mesh.vertices = new_vertices;
|
||||
mesh.indices = new_indices;
|
||||
|
||||
vertices_index_mapping.clear();
|
||||
vertices_to_remove.clear();
|
||||
faces_to_remove.clear();
|
||||
triangles_neighbors.clear();
|
||||
face_normals.clear();
|
||||
vertex_normals.clear();
|
||||
face_indices.clear();
|
||||
triangle_count = mesh.indices.size();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
16
src/libslic3r/ShortEdgeCollapse.hpp
Normal file
16
src/libslic3r/ShortEdgeCollapse.hpp
Normal file
@ -0,0 +1,16 @@
|
||||
#ifndef SRC_LIBSLIC3R_SHORTEDGECOLLAPSE_HPP_
|
||||
#define SRC_LIBSLIC3R_SHORTEDGECOLLAPSE_HPP_
|
||||
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
namespace Slic3r{
|
||||
|
||||
// Decimates the model by collapsing short edges. It starts with very small edges and gradually increases the collapsible length,
|
||||
// until the target triangle count is reached (the algorithm will certainly undershoot the target count, result will have less triangles than target count)
|
||||
// The algorithm does not check for triangle flipping, disconnections, self intersections or any other degeneration that can appear during mesh processing.
|
||||
void its_short_edge_collpase(indexed_triangle_set &mesh, size_t target_triangle_count);
|
||||
|
||||
}
|
||||
|
||||
|
||||
#endif /* SRC_LIBSLIC3R_SHORTEDGECOLLAPSE_HPP_ */
|
Loading…
Reference in New Issue
Block a user