Removed the PRUS format parser. WIP: admesh eradication:
stl_stats are newly only accessed by TriangleMesh::stats(), most of the direct access to TriangleMesh::stl is gone with the exception of parsing input files (3MF, AMF, obj).
This commit is contained in:
parent
1c6ecd9c1a
commit
58d8ab3dea
@ -145,7 +145,7 @@ void IndexedVertexArray::load_mesh(const TriangleMesh &mesh)
|
||||
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
|
||||
|
||||
int vertices_count = 0;
|
||||
for (size_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||
for (size_t i = 0; i < mesh.facets_count(); ++i) {
|
||||
const stl_facet &facet = mesh.stl.facet_start[i];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));
|
||||
|
@ -78,8 +78,6 @@ add_library(libslic3r STATIC
|
||||
Format/OBJ.hpp
|
||||
Format/objparser.cpp
|
||||
Format/objparser.hpp
|
||||
Format/PRUS.cpp
|
||||
Format/PRUS.hpp
|
||||
Format/STL.cpp
|
||||
Format/STL.hpp
|
||||
Format/SL1.hpp
|
||||
|
@ -9,7 +9,6 @@
|
||||
|
||||
#include "Format/AMF.hpp"
|
||||
#include "Format/OBJ.hpp"
|
||||
#include "Format/PRUS.hpp"
|
||||
#include "Format/STL.hpp"
|
||||
#include "Format/3mf.hpp"
|
||||
|
||||
@ -118,8 +117,6 @@ Model Model::read_from_file(const std::string& input_file, DynamicPrintConfig* c
|
||||
else if (boost::algorithm::iends_with(input_file, ".3mf"))
|
||||
//FIXME options & LoadAttribute::CheckVersion ?
|
||||
result = load_3mf(input_file.c_str(), *config, *config_substitutions, &model, false);
|
||||
else if (boost::algorithm::iends_with(input_file, ".prusa"))
|
||||
result = load_prus(input_file.c_str(), &model);
|
||||
else
|
||||
throw Slic3r::RuntimeError("Unknown file format. Input file must have .stl, .obj, .amf(.xml) or .prusa extension.");
|
||||
|
||||
@ -1154,7 +1151,7 @@ size_t ModelObject::facets_count() const
|
||||
size_t num = 0;
|
||||
for (const ModelVolume *v : this->volumes)
|
||||
if (v->is_model_part())
|
||||
num += v->mesh().stl.stats.number_of_facets;
|
||||
num += v->mesh().facets_count();
|
||||
return num;
|
||||
}
|
||||
|
||||
@ -1508,9 +1505,9 @@ double ModelObject::get_instance_min_z(size_t instance_idx) const
|
||||
|
||||
const Transform3d mv = mi * v->get_matrix();
|
||||
const TriangleMesh& hull = v->get_convex_hull();
|
||||
for (const stl_facet &facet : hull.stl.facet_start)
|
||||
for (const stl_triangle_vertex_indices facet : hull.its.indices)
|
||||
for (int i = 0; i < 3; ++ i)
|
||||
min_z = std::min(min_z, (mv * facet.vertex[i].cast<double>()).z());
|
||||
min_z = std::min(min_z, (mv * hull.its.vertices[facet[i]].cast<double>()).z());
|
||||
}
|
||||
|
||||
return min_z + inst->get_offset(Z);
|
||||
@ -1529,9 +1526,9 @@ double ModelObject::get_instance_max_z(size_t instance_idx) const
|
||||
|
||||
const Transform3d mv = mi * v->get_matrix();
|
||||
const TriangleMesh& hull = v->get_convex_hull();
|
||||
for (const stl_facet& facet : hull.stl.facet_start)
|
||||
for (const stl_triangle_vertex_indices facet : hull.its.indices)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
max_z = std::max(max_z, (mv * facet.vertex[i].cast<double>()).z());
|
||||
max_z = std::max(max_z, (mv * hull.its.vertices[facet[i]].cast<double>()).z());
|
||||
}
|
||||
|
||||
return max_z + inst->get_offset(Z);
|
||||
@ -1584,26 +1581,26 @@ void ModelObject::print_info() const
|
||||
cout << "max_x = " << bb.max(0) << endl;
|
||||
cout << "max_y = " << bb.max(1) << endl;
|
||||
cout << "max_z = " << bb.max(2) << endl;
|
||||
cout << "number_of_facets = " << mesh.stl.stats.number_of_facets << endl;
|
||||
cout << "number_of_facets = " << mesh.facets_count() << endl;
|
||||
cout << "manifold = " << (mesh.is_manifold() ? "yes" : "no") << endl;
|
||||
|
||||
mesh.repair(); // this calculates number_of_parts
|
||||
if (mesh.needed_repair()) {
|
||||
mesh.repair();
|
||||
if (mesh.stl.stats.degenerate_facets > 0)
|
||||
cout << "degenerate_facets = " << mesh.stl.stats.degenerate_facets << endl;
|
||||
if (mesh.stl.stats.edges_fixed > 0)
|
||||
cout << "edges_fixed = " << mesh.stl.stats.edges_fixed << endl;
|
||||
if (mesh.stl.stats.facets_removed > 0)
|
||||
cout << "facets_removed = " << mesh.stl.stats.facets_removed << endl;
|
||||
if (mesh.stl.stats.facets_added > 0)
|
||||
cout << "facets_added = " << mesh.stl.stats.facets_added << endl;
|
||||
if (mesh.stl.stats.facets_reversed > 0)
|
||||
cout << "facets_reversed = " << mesh.stl.stats.facets_reversed << endl;
|
||||
if (mesh.stl.stats.backwards_edges > 0)
|
||||
cout << "backwards_edges = " << mesh.stl.stats.backwards_edges << endl;
|
||||
if (mesh.stats().degenerate_facets > 0)
|
||||
cout << "degenerate_facets = " << mesh.stats().degenerate_facets << endl;
|
||||
if (mesh.stats().edges_fixed > 0)
|
||||
cout << "edges_fixed = " << mesh.stats().edges_fixed << endl;
|
||||
if (mesh.stats().facets_removed > 0)
|
||||
cout << "facets_removed = " << mesh.stats().facets_removed << endl;
|
||||
if (mesh.stats().facets_added > 0)
|
||||
cout << "facets_added = " << mesh.stats().facets_added << endl;
|
||||
if (mesh.stats().facets_reversed > 0)
|
||||
cout << "facets_reversed = " << mesh.stats().facets_reversed << endl;
|
||||
if (mesh.stats().backwards_edges > 0)
|
||||
cout << "backwards_edges = " << mesh.stats().backwards_edges << endl;
|
||||
}
|
||||
cout << "number_of_parts = " << mesh.stl.stats.number_of_parts << endl;
|
||||
cout << "number_of_parts = " << mesh.stats().number_of_parts << endl;
|
||||
cout << "volume = " << mesh.volume() << endl;
|
||||
}
|
||||
|
||||
@ -1630,7 +1627,7 @@ std::string ModelObject::get_export_filename() const
|
||||
stl_stats ModelObject::get_object_stl_stats() const
|
||||
{
|
||||
if (this->volumes.size() == 1)
|
||||
return this->volumes[0]->mesh().stl.stats;
|
||||
return this->volumes[0]->mesh().stats();
|
||||
|
||||
stl_stats full_stats;
|
||||
full_stats.volume = 0.f;
|
||||
@ -1638,7 +1635,7 @@ stl_stats ModelObject::get_object_stl_stats() const
|
||||
// fill full_stats from all objet's meshes
|
||||
for (ModelVolume* volume : this->volumes)
|
||||
{
|
||||
const stl_stats& stats = volume->mesh().stl.stats;
|
||||
const stl_stats& stats = volume->mesh().stats();
|
||||
|
||||
// initialize full_stats (for repaired errors)
|
||||
full_stats.degenerate_facets += stats.degenerate_facets;
|
||||
@ -1734,7 +1731,7 @@ void ModelVolume::calculate_convex_hull()
|
||||
|
||||
int ModelVolume::get_mesh_errors_count() const
|
||||
{
|
||||
const stl_stats& stats = this->mesh().stl.stats;
|
||||
const stl_stats &stats = this->mesh().stats();
|
||||
|
||||
return stats.degenerate_facets + stats.edges_fixed + stats.facets_removed +
|
||||
stats.facets_added + stats.facets_reversed + stats.backwards_edges;
|
||||
|
@ -774,7 +774,7 @@ private:
|
||||
assert(this->id() != this->supported_facets.id());
|
||||
assert(this->id() != this->seam_facets.id());
|
||||
assert(this->id() != this->mmu_segmentation_facets.id());
|
||||
if (mesh.stl.stats.number_of_facets > 1)
|
||||
if (mesh.facets_count() > 1)
|
||||
calculate_convex_hull();
|
||||
}
|
||||
ModelVolume(ModelObject *object, TriangleMesh &&mesh, TriangleMesh &&convex_hull, ModelVolumeType type = ModelVolumeType::MODEL_PART) :
|
||||
@ -830,7 +830,7 @@ private:
|
||||
assert(this->config.id() == other.config.id());
|
||||
this->set_material_id(other.material_id());
|
||||
this->config.set_new_unique_id();
|
||||
if (mesh.stl.stats.number_of_facets > 1)
|
||||
if (mesh.facets_count() > 1)
|
||||
calculate_convex_hull();
|
||||
assert(this->config.id().valid());
|
||||
assert(this->config.id() != other.config.id());
|
||||
|
@ -39,23 +39,6 @@ LayerPtrs new_layers(
|
||||
return out;
|
||||
}
|
||||
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
// This function will go away once we get rid of admesh from ModelVolume.
|
||||
static indexed_triangle_set get_mesh_its_fix_mesh_connectivity(TriangleMesh mesh)
|
||||
{
|
||||
assert(mesh.repaired && mesh.has_shared_vertices());
|
||||
if (mesh.stl.stats.number_of_facets > 0) {
|
||||
assert(mesh.repaired && mesh.has_shared_vertices());
|
||||
auto nr_degenerated = mesh.stl.stats.degenerate_facets;
|
||||
stl_check_facets_exact(&mesh.stl);
|
||||
if (nr_degenerated != mesh.stl.stats.degenerate_facets)
|
||||
// stl_check_facets_exact() removed some newly degenerated faces. Some faces could become degenerate after some mesh transformation.
|
||||
stl_generate_shared_vertices(&mesh.stl, mesh.its);
|
||||
} else
|
||||
mesh.its.clear();
|
||||
return std::move(mesh.its);
|
||||
}
|
||||
|
||||
// Slice single triangle mesh.
|
||||
static std::vector<ExPolygons> slice_volume(
|
||||
const ModelVolume &volume,
|
||||
@ -65,7 +48,7 @@ static std::vector<ExPolygons> slice_volume(
|
||||
{
|
||||
std::vector<ExPolygons> layers;
|
||||
if (! zs.empty()) {
|
||||
indexed_triangle_set its = get_mesh_its_fix_mesh_connectivity(volume.mesh());
|
||||
indexed_triangle_set its = volume.mesh().its;
|
||||
if (its.indices.size() > 0) {
|
||||
MeshSlicingParamsEx params2 { params };
|
||||
params2.trafo = params2.trafo * volume.get_matrix();
|
||||
|
@ -35,13 +35,6 @@ legend("tan(a) as cura - topographic lines distance limit", "sqrt(tan(a)) as Pru
|
||||
namespace Slic3r
|
||||
{
|
||||
|
||||
static inline std::pair<float, float> face_z_span(const stl_facet &f)
|
||||
{
|
||||
return std::pair<float, float>(
|
||||
std::min(std::min(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)),
|
||||
std::max(std::max(f.vertex[0](2), f.vertex[1](2)), f.vertex[2](2)));
|
||||
}
|
||||
|
||||
// By Florens Waserfall aka @platch:
|
||||
// This constant essentially describes the volumetric error at the surface which is induced
|
||||
// by stacking "elliptic" extrusion threads. It is empirically determined by
|
||||
@ -88,10 +81,15 @@ void SlicingAdaptive::prepare(const ModelObject &object)
|
||||
mesh.transform(first_instance.get_matrix(), first_instance.is_left_handed());
|
||||
|
||||
// 1) Collect faces from mesh.
|
||||
m_faces.reserve(mesh.stl.stats.number_of_facets);
|
||||
for (const stl_facet &face : mesh.stl.facet_start) {
|
||||
Vec3f n = face.normal.normalized();
|
||||
m_faces.emplace_back(FaceZ({ face_z_span(face), std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
|
||||
m_faces.reserve(mesh.facets_count());
|
||||
for (stl_triangle_vertex_indices face : mesh.its.indices) {
|
||||
stl_vertex vertex[3] = { mesh.its.vertices[face[0]], mesh.its.vertices[face[1]], mesh.its.vertices[face[2]] };
|
||||
stl_vertex n = (vertex[2] - vertex[1]).cross(vertex[3] - vertex[2]).normalized();
|
||||
std::pair<float, float> face_z_span {
|
||||
std::min(std::min(vertex[0].z(), vertex[1].z()), vertex[2].z()),
|
||||
std::max(std::max(vertex[0].z(), vertex[1].z()), vertex[2].z())
|
||||
};
|
||||
m_faces.emplace_back(FaceZ({ face_z_span, std::abs(n.z()), std::sqrt(n.x() * n.x() + n.y() * n.y()) }));
|
||||
}
|
||||
|
||||
// 2) Sort faces lexicographically by their Z span.
|
||||
|
@ -187,6 +187,10 @@ void TriangleMesh::repair(bool update_shared_vertices)
|
||||
|
||||
this->repaired = true;
|
||||
|
||||
//FIXME The admesh repair function may break the face connectivity, rather refresh it here as the slicing code relies on it.
|
||||
if (auto nr_degenerated = this->stl.stats.degenerate_facets; this->facets_count() > 0 && nr_degenerated > 0)
|
||||
stl_check_facets_exact(&this->stl);
|
||||
|
||||
BOOST_LOG_TRIVIAL(debug) << "TriangleMesh::repair() finished";
|
||||
|
||||
// This call should be quite cheap, a lot of code requires the indexed_triangle_set data structure,
|
||||
@ -1335,4 +1339,15 @@ std::vector<Vec3i> its_face_neighbors_par(const indexed_triangle_set &its)
|
||||
return create_face_neighbors_index(ex_tbb, its);
|
||||
}
|
||||
|
||||
std::vector<Vec3f> its_face_normals(const indexed_triangle_set &its)
|
||||
{
|
||||
std::vector<Vec3f> normals;
|
||||
normals.reserve(its.indices.size());
|
||||
for (stl_triangle_vertex_indices face : its.indices) {
|
||||
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
||||
normals.push_back((vertex[2] - vertex[1]).cross(vertex[3] - vertex[2]).normalized());
|
||||
}
|
||||
return normals;
|
||||
}
|
||||
|
||||
} // namespace Slic3r
|
||||
|
@ -52,7 +52,6 @@ public:
|
||||
TriangleMeshPtrs split() const;
|
||||
void merge(const TriangleMesh &mesh);
|
||||
ExPolygons horizontal_projection() const;
|
||||
const float* first_vertex() const { return this->stl.facet_start.empty() ? nullptr : &this->stl.facet_start.front().vertex[0](0); }
|
||||
// 2D convex hull of a 3D mesh projected into the Z=0 plane.
|
||||
Polygon convex_hull();
|
||||
BoundingBoxf3 bounding_box() const;
|
||||
@ -80,10 +79,14 @@ public:
|
||||
// Restore optional data possibly released by release_optional().
|
||||
void restore_optional();
|
||||
|
||||
stl_file stl;
|
||||
const stl_stats& stats() const { return this->stl.stats; }
|
||||
|
||||
indexed_triangle_set its;
|
||||
bool repaired;
|
||||
|
||||
//private:
|
||||
stl_file stl;
|
||||
|
||||
private:
|
||||
std::deque<uint32_t> find_unvisited_neighbors(std::vector<unsigned char> &facet_visited) const;
|
||||
};
|
||||
@ -205,6 +208,8 @@ void its_merge(indexed_triangle_set &A, const indexed_triangle_set &B);
|
||||
void its_merge(indexed_triangle_set &A, const std::vector<Vec3f> &triangles);
|
||||
void its_merge(indexed_triangle_set &A, const Pointf3s &triangles);
|
||||
|
||||
std::vector<Vec3f> its_face_normals(const indexed_triangle_set &its);
|
||||
|
||||
indexed_triangle_set its_make_cube(double x, double y, double z);
|
||||
TriangleMesh make_cube(double x, double y, double z);
|
||||
|
||||
|
@ -9,16 +9,6 @@
|
||||
|
||||
namespace Slic3r {
|
||||
|
||||
static inline Vec3i root_neighbors(const TriangleMesh &mesh, int triangle_id)
|
||||
{
|
||||
Vec3i neighbors;
|
||||
const stl_neighbors& neighbors_src = mesh.stl.neighbors_start[triangle_id];
|
||||
for (int i = 0; i < 3; ++i)
|
||||
// Refuse a neighbor with a flipped normal.
|
||||
neighbors(i) = neighbors_src.neighbor[i];
|
||||
return neighbors;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
bool TriangleSelector::verify_triangle_midpoints(const Triangle &tr) const
|
||||
{
|
||||
@ -129,7 +119,7 @@ int TriangleSelector::select_unsplit_triangle(const Vec3f &hit, int facet_idx) c
|
||||
if (!m_triangles[facet_idx].valid())
|
||||
return -1;
|
||||
|
||||
Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
|
||||
Vec3i neighbors = m_neighbors[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
|
||||
return this->select_unsplit_triangle(hit, facet_idx, neighbors);
|
||||
}
|
||||
@ -167,7 +157,7 @@ void TriangleSelector::select_patch(const Vec3f& hit, int facet_start,
|
||||
if (! visited[facet]) {
|
||||
if (select_triangle(facet, new_state, triangle_splitting)) {
|
||||
// add neighboring facets to list to be proccessed later
|
||||
for (int neighbor_idx : m_mesh->stl.neighbors_start[facet].neighbor) {
|
||||
for (int neighbor_idx : m_neighbors[facet]) {
|
||||
if (neighbor_idx >=0 && (m_cursor.type == SPHERE || faces_camera(neighbor_idx)))
|
||||
facets_to_check.push_back(neighbor_idx);
|
||||
}
|
||||
@ -213,12 +203,12 @@ void TriangleSelector::seed_fill_select_triangles(const Vec3f &hit, int facet_st
|
||||
|
||||
if (current_facet < m_orig_size_indices)
|
||||
// Propagate over the original triangles.
|
||||
for (int neighbor_idx : m_mesh->stl.neighbors_start[current_facet].neighbor) {
|
||||
for (int neighbor_idx : m_neighbors[current_facet]) {
|
||||
assert(neighbor_idx >= -1);
|
||||
if (neighbor_idx >= 0 && !visited[neighbor_idx]) {
|
||||
// Check if neighbour_facet_idx is satisfies angle in seed_fill_angle and append it to facet_queue if it do.
|
||||
const Vec3f &n1 = m_mesh->stl.facet_start[m_triangles[neighbor_idx].source_triangle].normal;
|
||||
const Vec3f &n2 = m_mesh->stl.facet_start[m_triangles[current_facet].source_triangle].normal;
|
||||
const Vec3f &n1 = m_face_normals[m_triangles[neighbor_idx].source_triangle];
|
||||
const Vec3f &n2 = m_face_normals[m_triangles[current_facet].source_triangle];
|
||||
if (std::clamp(n1.dot(n2), 0.f, 1.f) >= facet_angle_limit)
|
||||
facet_queue.push(neighbor_idx);
|
||||
}
|
||||
@ -261,7 +251,7 @@ std::pair<std::vector<Vec3i>, std::vector<Vec3i>> TriangleSelector::precompute_a
|
||||
std::vector<Vec3i> neighbors(m_triangles.size(), Vec3i(-1, -1, -1));
|
||||
std::vector<Vec3i> neighbors_propagated(m_triangles.size(), Vec3i(-1, -1, -1));
|
||||
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) {
|
||||
neighbors[facet_idx] = root_neighbors(*m_mesh, facet_idx);
|
||||
neighbors[facet_idx] = m_neighbors[facet_idx];
|
||||
neighbors_propagated[facet_idx] = neighbors[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors[facet_idx]));
|
||||
if (m_triangles[facet_idx].is_split())
|
||||
@ -403,7 +393,7 @@ bool TriangleSelector::select_triangle(int facet_idx, EnforcerBlockerType type,
|
||||
if (! m_triangles[facet_idx].valid())
|
||||
return false;
|
||||
|
||||
Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
|
||||
Vec3i neighbors = m_neighbors[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
|
||||
|
||||
if (! select_triangle_recursive(facet_idx, neighbors, type, triangle_splitting))
|
||||
@ -906,14 +896,7 @@ bool TriangleSelector::is_pointer_in_triangle(int facet_idx) const
|
||||
bool TriangleSelector::faces_camera(int facet) const
|
||||
{
|
||||
assert(facet < m_orig_size_indices);
|
||||
// The normal is cached in mesh->stl, use it.
|
||||
Vec3f normal = m_mesh->stl.facet_start[facet].normal;
|
||||
|
||||
if (! m_cursor.uniform_scaling) {
|
||||
// Transform the normal into world coords.
|
||||
normal = m_cursor.trafo_normal * normal;
|
||||
}
|
||||
return (normal.dot(m_cursor.dir) < 0.);
|
||||
return (m_cursor.uniform_scaling ? m_face_normals[facet] : m_cursor.trafo_normal * m_face_normals[facet]).dot(m_cursor.dir) < 0.;
|
||||
}
|
||||
|
||||
|
||||
@ -1094,7 +1077,7 @@ void TriangleSelector::garbage_collect()
|
||||
}
|
||||
|
||||
TriangleSelector::TriangleSelector(const TriangleMesh& mesh)
|
||||
: m_mesh{&mesh}
|
||||
: m_mesh{mesh}, m_neighbors(its_face_neighbors(mesh.its)), m_face_normals(its_face_normals(mesh.its))
|
||||
{
|
||||
reset();
|
||||
}
|
||||
@ -1107,16 +1090,17 @@ void TriangleSelector::reset()
|
||||
m_invalid_triangles = 0;
|
||||
m_free_triangles_head = -1;
|
||||
m_free_vertices_head = -1;
|
||||
m_vertices.reserve(m_mesh->its.vertices.size());
|
||||
for (const stl_vertex& vert : m_mesh->its.vertices)
|
||||
m_vertices.reserve(m_mesh.its.vertices.size());
|
||||
for (const stl_vertex& vert : m_mesh.its.vertices)
|
||||
m_vertices.emplace_back(vert);
|
||||
m_triangles.reserve(m_mesh->its.indices.size());
|
||||
for (size_t i = 0; i < m_mesh->its.indices.size(); ++i) {
|
||||
const stl_triangle_vertex_indices &ind = m_mesh->its.indices[i];
|
||||
m_triangles.reserve(m_mesh.its.indices.size());
|
||||
for (size_t i = 0; i < m_mesh.its.indices.size(); ++i) {
|
||||
const stl_triangle_vertex_indices &ind = m_mesh.its.indices[i];
|
||||
push_triangle(ind[0], ind[1], ind[2], int(i));
|
||||
}
|
||||
m_orig_size_vertices = int(m_vertices.size());
|
||||
m_orig_size_indices = int(m_triangles.size());
|
||||
|
||||
}
|
||||
|
||||
|
||||
@ -1286,7 +1270,7 @@ indexed_triangle_set TriangleSelector::get_facets_strict(EnforcerBlockerType sta
|
||||
}
|
||||
|
||||
for (int itriangle = 0; itriangle < m_orig_size_indices; ++ itriangle)
|
||||
this->get_facets_strict_recursive(m_triangles[itriangle], root_neighbors(*m_mesh, itriangle), state, out.indices);
|
||||
this->get_facets_strict_recursive(m_triangles[itriangle], m_neighbors[itriangle], state, out.indices);
|
||||
|
||||
for (auto &triangle : out.indices)
|
||||
for (int i = 0; i < 3; ++ i)
|
||||
@ -1398,7 +1382,7 @@ void TriangleSelector::get_facets_split_by_tjoints(const Vec3i &vertices, const
|
||||
std::vector<Vec2i> TriangleSelector::get_seed_fill_contour() const {
|
||||
std::vector<Vec2i> edges_out;
|
||||
for (int facet_idx = 0; facet_idx < this->m_orig_size_indices; ++facet_idx) {
|
||||
const Vec3i neighbors = root_neighbors(*m_mesh, facet_idx);
|
||||
const Vec3i neighbors = m_neighbors[facet_idx];
|
||||
assert(this->verify_triangle_neighbors(m_triangles[facet_idx], neighbors));
|
||||
this->get_seed_fill_contour_recursive(facet_idx, neighbors, neighbors, edges_out);
|
||||
}
|
||||
@ -1522,10 +1506,10 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
||||
|
||||
// Reserve number of triangles as if each triangle was saved with 4 bits.
|
||||
// With MMU painting this estimate may be somehow low, but better than nothing.
|
||||
m_triangles.reserve(std::max(m_mesh->its.indices.size(), data.second.size() / 4));
|
||||
m_triangles.reserve(std::max(m_mesh.its.indices.size(), data.second.size() / 4));
|
||||
// Number of triangles is twice the number of vertices on a large manifold mesh of genus zero.
|
||||
// Here the triangles count account for both the nodes and leaves, thus the following line may overestimate.
|
||||
m_vertices.reserve(std::max(m_mesh->its.vertices.size(), m_triangles.size() / 2));
|
||||
m_vertices.reserve(std::max(m_mesh.its.vertices.size(), m_triangles.size() / 2));
|
||||
|
||||
// Vector to store all parents that have offsprings.
|
||||
struct ProcessingInfo {
|
||||
@ -1565,7 +1549,7 @@ void TriangleSelector::deserialize(const std::pair<std::vector<std::pair<int, in
|
||||
if (is_split) {
|
||||
// root is split, add it into list of parents and split it.
|
||||
// then go to the next.
|
||||
Vec3i neighbors = root_neighbors(*m_mesh, triangle_id);
|
||||
Vec3i neighbors = m_neighbors[triangle_id];
|
||||
parents.push_back({triangle_id, neighbors, 0, num_of_children});
|
||||
m_triangles[triangle_id].set_division(num_of_split_sides, special_side);
|
||||
perform_split(triangle_id, neighbors, EnforcerBlockerType::NONE);
|
||||
|
@ -161,7 +161,9 @@ protected:
|
||||
// Lists of vertices and triangles, both original and new
|
||||
std::vector<Vertex> m_vertices;
|
||||
std::vector<Triangle> m_triangles;
|
||||
const TriangleMesh* m_mesh;
|
||||
const TriangleMesh &m_mesh;
|
||||
const std::vector<Vec3i> m_neighbors;
|
||||
const std::vector<Vec3f> m_face_normals;
|
||||
|
||||
// Number of invalid triangles (to trigger garbage collection).
|
||||
int m_invalid_triangles;
|
||||
|
@ -158,22 +158,27 @@ void GLIndexedVertexArray::load_mesh_full_shading(const TriangleMesh& mesh)
|
||||
}
|
||||
else {
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * mesh.facets_count());
|
||||
|
||||
unsigned int vertices_count = 0;
|
||||
for (int i = 0; i < (int)mesh.stl.stats.number_of_facets; ++i) {
|
||||
const stl_facet& facet = mesh.stl.facet_start[i];
|
||||
for (int j = 0; j < 3; ++j)
|
||||
this->push_geometry(facet.vertex[j](0), facet.vertex[j](1), facet.vertex[j](2), facet.normal(0), facet.normal(1), facet.normal(2));
|
||||
|
||||
this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2);
|
||||
vertices_count += 3;
|
||||
}
|
||||
this->load_its_flat_shading(mesh.its);
|
||||
#if ENABLE_SMOOTH_NORMALS
|
||||
}
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
}
|
||||
|
||||
void GLIndexedVertexArray::load_its_flat_shading(const indexed_triangle_set &its)
|
||||
{
|
||||
this->vertices_and_normals_interleaved.reserve(this->vertices_and_normals_interleaved.size() + 3 * 3 * 2 * its.indices.size());
|
||||
unsigned int vertices_count = 0;
|
||||
for (int i = 0; i < int(its.indices.size()); ++ i) {
|
||||
stl_triangle_vertex_indices face = its.indices[i];
|
||||
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
||||
stl_vertex n = (vertex[2] - vertex[1]).cross(vertex[3] - vertex[2]).normalized();
|
||||
for (int j = 0; j < 3; ++j)
|
||||
this->push_geometry(vertex[j](0), vertex[j](1), vertex[j](2), n(0), n(1), n(2));
|
||||
this->push_triangle(vertices_count, vertices_count + 1, vertices_count + 2);
|
||||
vertices_count += 3;
|
||||
}
|
||||
}
|
||||
|
||||
void GLIndexedVertexArray::finalize_geometry(bool opengl_initialized)
|
||||
{
|
||||
assert(this->vertices_and_normals_interleaved_VBO_id == 0);
|
||||
@ -531,7 +536,7 @@ const BoundingBoxf3& GLVolume::transformed_convex_hull_bounding_box() const
|
||||
|
||||
BoundingBoxf3 GLVolume::transformed_convex_hull_bounding_box(const Transform3d &trafo) const
|
||||
{
|
||||
return (m_convex_hull && m_convex_hull->stl.stats.number_of_facets > 0) ?
|
||||
return (m_convex_hull && m_convex_hull->facets_count() > 0) ?
|
||||
m_convex_hull->transformed_bounding_box(trafo) :
|
||||
bounding_box().transformed(trafo);
|
||||
}
|
||||
|
@ -128,6 +128,8 @@ public:
|
||||
void load_mesh(const TriangleMesh& mesh) { this->load_mesh_full_shading(mesh); }
|
||||
#endif // ENABLE_SMOOTH_NORMALS
|
||||
|
||||
void load_its_flat_shading(const indexed_triangle_set &its);
|
||||
|
||||
inline bool has_VBOs() const { return vertices_and_normals_interleaved_VBO_id != 0; }
|
||||
|
||||
inline void reserve(size_t sz) {
|
||||
|
@ -78,7 +78,7 @@ void GLModel::init_from(const InitializationData& data)
|
||||
}
|
||||
}
|
||||
|
||||
void GLModel::init_from(const TriangleMesh& mesh)
|
||||
void GLModel::init_from(const indexed_triangle_set& its, const BoundingBoxf3 &bbox)
|
||||
{
|
||||
if (!m_render_data.empty()) // call reset() if you want to reuse this model
|
||||
return;
|
||||
@ -86,25 +86,26 @@ void GLModel::init_from(const TriangleMesh& mesh)
|
||||
RenderData data;
|
||||
data.type = PrimitiveType::Triangles;
|
||||
|
||||
std::vector<float> vertices = std::vector<float>(18 * mesh.stl.stats.number_of_facets);
|
||||
std::vector<unsigned int> indices = std::vector<unsigned int>(3 * mesh.stl.stats.number_of_facets);
|
||||
std::vector<float> vertices = std::vector<float>(18 * its.indices.size());
|
||||
std::vector<unsigned int> indices = std::vector<unsigned int>(3 * its.indices.size());
|
||||
|
||||
unsigned int vertices_count = 0;
|
||||
for (uint32_t i = 0; i < mesh.stl.stats.number_of_facets; ++i) {
|
||||
const stl_facet& facet = mesh.stl.facet_start[i];
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
for (uint32_t i = 0; i < its.indices.size(); ++i) {
|
||||
stl_triangle_vertex_indices face = its.indices[i];
|
||||
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
||||
stl_vertex n = (vertex[2] - vertex[1]).cross(vertex[3] - vertex[2]).normalized();
|
||||
for (size_t j = 0; j < 3; ++ j) {
|
||||
size_t offset = i * 18 + j * 6;
|
||||
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(facet.vertex[j].data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(facet.normal.data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[offset]), static_cast<const void*>(vertex[j].data()), 3 * sizeof(float));
|
||||
::memcpy(static_cast<void*>(&vertices[3 + offset]), static_cast<const void*>(n.data()), 3 * sizeof(float));
|
||||
}
|
||||
for (size_t j = 0; j < 3; ++j) {
|
||||
for (size_t j = 0; j < 3; ++j)
|
||||
indices[i * 3 + j] = vertices_count + j;
|
||||
}
|
||||
vertices_count += 3;
|
||||
}
|
||||
|
||||
data.indices_count = static_cast<unsigned int>(indices.size());
|
||||
m_bounding_box = mesh.bounding_box();
|
||||
m_bounding_box = bbox;
|
||||
|
||||
send_to_gpu(data, vertices, indices);
|
||||
m_render_data.emplace_back(data);
|
||||
|
@ -70,7 +70,8 @@ namespace GUI {
|
||||
virtual ~GLModel() { reset(); }
|
||||
|
||||
void init_from(const InitializationData& data);
|
||||
void init_from(const TriangleMesh& mesh);
|
||||
void init_from(const TriangleMesh& mesh) { this->init_from(mesh.its, mesh.bounding_box()); }
|
||||
void init_from(const indexed_triangle_set& its, const BoundingBoxf3& bbox);
|
||||
#if ENABLE_SINKING_CONTOURS
|
||||
void init_from(const Polygons& polygons, float z);
|
||||
#endif // ENABLE_SINKING_CONTOURS
|
||||
|
@ -429,9 +429,8 @@ wxString file_wildcards(FileType file_type, const std::string &custom_extension)
|
||||
/* FT_OBJ */ "OBJ files (*.obj)|*.obj;*.OBJ",
|
||||
/* FT_AMF */ "AMF files (*.amf)|*.zip.amf;*.amf;*.AMF;*.xml;*.XML",
|
||||
/* FT_3MF */ "3MF files (*.3mf)|*.3mf;*.3MF;",
|
||||
/* FT_PRUSA */ "Prusa Control files (*.prusa)|*.prusa;*.PRUSA",
|
||||
/* FT_GCODE */ "G-code files (*.gcode, *.gco, *.g, *.ngc)|*.gcode;*.GCODE;*.gco;*.GCO;*.g;*.G;*.ngc;*.NGC",
|
||||
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF;*.prusa;*.PRUSA",
|
||||
/* FT_MODEL */ "Known files (*.stl, *.obj, *.amf, *.xml, *.3mf, *.prusa)|*.stl;*.STL;*.obj;*.OBJ;*.amf;*.AMF;*.xml;*.XML;*.3mf;*.3MF",
|
||||
/* FT_PROJECT */ "Project files (*.3mf, *.amf)|*.3mf;*.3MF;*.amf;*.AMF",
|
||||
/* FT_GALLERY */ "Known files (*.stl, *.obj)|*.stl;*.STL;*.obj;*.OBJ",
|
||||
|
||||
|
@ -393,7 +393,7 @@ wxString ObjectList::get_mesh_errors_list(const int obj_idx, const int vol_idx /
|
||||
|
||||
const stl_stats& stats = vol_idx == -1 ?
|
||||
(*m_objects)[obj_idx]->get_object_stl_stats() :
|
||||
(*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stl.stats;
|
||||
(*m_objects)[obj_idx]->volumes[vol_idx]->mesh().stats();
|
||||
|
||||
if (stats.degenerate_facets > 0)
|
||||
tooltip += "\t" + format_wxstr(_L_PLURAL("%1$d degenerate facet", "%1$d degenerate facets", stats.degenerate_facets), stats.degenerate_facets) + "\n";
|
||||
|
@ -288,9 +288,12 @@ void GLGizmoFdmSupports::select_facets_by_angle(float threshold_deg, bool block)
|
||||
|
||||
// Now calculate dot product of vert_direction and facets' normals.
|
||||
int idx = -1;
|
||||
for (const stl_facet &facet : mv->mesh().stl.facet_start) {
|
||||
++idx;
|
||||
if (facet.normal.dot(down) > dot_limit) {
|
||||
const indexed_triangle_set &its = mv->mesh().its;
|
||||
for (stl_triangle_vertex_indices face : its.indices) {
|
||||
stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
|
||||
stl_vertex n = (vertex[2] - vertex[1]).cross(vertex[3] - vertex[2]).normalized();
|
||||
++ idx;
|
||||
if (n.dot(down) > dot_limit) {
|
||||
m_triangle_selectors[mesh_id]->set_facet(idx, block ? EnforcerBlockerType::BLOCKER : EnforcerBlockerType::ENFORCER);
|
||||
m_triangle_selectors.back()->request_update_render_data();
|
||||
}
|
||||
|
@ -142,7 +142,9 @@ void GLGizmoFlatten::update_planes()
|
||||
|
||||
// Now we'll go through all the facets and append Points of facets sharing the same normal.
|
||||
// This part is still performed in mesh coordinate system.
|
||||
const int num_of_facets = ch.stl.stats.number_of_facets;
|
||||
const int num_of_facets = ch.facets_count();
|
||||
const std::vector<Vec3f> face_normals = its_face_normals(ch.its);
|
||||
const std::vector<Vec3i> face_neighbors = its_face_neighbors(ch.its);
|
||||
std::vector<int> facet_queue(num_of_facets, 0);
|
||||
std::vector<bool> facet_visited(num_of_facets, false);
|
||||
int facet_queue_cnt = 0;
|
||||
@ -154,7 +156,7 @@ void GLGizmoFlatten::update_planes()
|
||||
if (!facet_visited[facet_idx]) {
|
||||
facet_queue[facet_queue_cnt ++] = facet_idx;
|
||||
facet_visited[facet_idx] = true;
|
||||
normal_ptr = &ch.stl.facet_start[facet_idx].normal;
|
||||
normal_ptr = &face_normals[facet_idx];
|
||||
m_planes.emplace_back();
|
||||
break;
|
||||
}
|
||||
@ -163,20 +165,18 @@ void GLGizmoFlatten::update_planes()
|
||||
|
||||
while (facet_queue_cnt > 0) {
|
||||
int facet_idx = facet_queue[-- facet_queue_cnt];
|
||||
const stl_normal& this_normal = ch.stl.facet_start[facet_idx].normal;
|
||||
const stl_normal& this_normal = face_normals[facet_idx];
|
||||
if (std::abs(this_normal(0) - (*normal_ptr)(0)) < 0.001 && std::abs(this_normal(1) - (*normal_ptr)(1)) < 0.001 && std::abs(this_normal(2) - (*normal_ptr)(2)) < 0.001) {
|
||||
stl_vertex* first_vertex = ch.stl.facet_start[facet_idx].vertex;
|
||||
const Vec3i face = ch.its.indices[facet_idx];
|
||||
for (int j=0; j<3; ++j)
|
||||
m_planes.back().vertices.emplace_back(first_vertex[j].cast<double>());
|
||||
m_planes.back().vertices.emplace_back(ch.its.vertices[face[j]].cast<double>());
|
||||
|
||||
facet_visited[facet_idx] = true;
|
||||
for (int j = 0; j < 3; ++ j) {
|
||||
int neighbor_idx = ch.stl.neighbors_start[facet_idx].neighbor[j];
|
||||
if (! facet_visited[neighbor_idx])
|
||||
for (int j = 0; j < 3; ++ j)
|
||||
if (int neighbor_idx = face_neighbors[facet_idx][j]; neighbor_idx >= 0 && ! facet_visited[neighbor_idx])
|
||||
facet_queue[facet_queue_cnt ++] = neighbor_idx;
|
||||
}
|
||||
}
|
||||
}
|
||||
m_planes.back().normal = normal_ptr->cast<double>();
|
||||
|
||||
Pointf3s& verts = m_planes.back().vertices;
|
||||
|
@ -8,8 +8,9 @@
|
||||
#include "slic3r/GUI/GUI_App.hpp"
|
||||
#include "slic3r/GUI/Camera.hpp"
|
||||
#include "slic3r/GUI/Plater.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/Model.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
#include "libslic3r/TriangleMesh.hpp"
|
||||
|
||||
|
||||
|
||||
@ -20,17 +21,10 @@ GLGizmoPainterBase::GLGizmoPainterBase(GLCanvas3D& parent, const std::string& ic
|
||||
: GLGizmoBase(parent, icon_filename, sprite_id)
|
||||
{
|
||||
// Make sphere and save it into a vertex buffer.
|
||||
const TriangleMesh sphere_mesh = make_sphere(1., (2*M_PI)/24.);
|
||||
for (size_t i=0; i<sphere_mesh.its.vertices.size(); ++i)
|
||||
m_vbo_sphere.push_geometry(sphere_mesh.its.vertices[i].cast<double>(),
|
||||
sphere_mesh.stl.facet_start[i].normal.cast<double>());
|
||||
for (const stl_triangle_vertex_indices& indices : sphere_mesh.its.indices)
|
||||
m_vbo_sphere.push_triangle(indices(0), indices(1), indices(2));
|
||||
m_vbo_sphere.load_its_flat_shading(its_make_sphere(1., (2*M_PI)/24.));
|
||||
m_vbo_sphere.finalize_geometry(true);
|
||||
}
|
||||
|
||||
|
||||
|
||||
// port of 948bc382655993721d93d3b9fce9b0186fcfb211
|
||||
void GLGizmoPainterBase::activate_internal_undo_redo_stack(bool activate)
|
||||
{
|
||||
@ -632,9 +626,15 @@ void TriangleSelectorGUI::update_render_data()
|
||||
|
||||
GLIndexedVertexArray &iva = tr.get_state() == EnforcerBlockerType::ENFORCER ? m_iva_enforcers : m_iva_blockers;
|
||||
int & cnt = tr.get_state() == EnforcerBlockerType::ENFORCER ? enf_cnt : blc_cnt;
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
iva.push_geometry(m_vertices[tr.verts_idxs[i]].v, m_mesh->stl.facet_start[tr.source_triangle].normal);
|
||||
const Vec3f &v0 = m_vertices[tr.verts_idxs[0]].v;
|
||||
const Vec3f &v1 = m_vertices[tr.verts_idxs[1]].v;
|
||||
const Vec3f &v2 = m_vertices[tr.verts_idxs[2]].v;
|
||||
//FIXME the normal may likely be pulled from m_triangle_selectors, but it may not be worth the effort
|
||||
// or the current implementation may be more cache friendly.
|
||||
const Vec3f n = (v1 - v0).cross(v2 - v1).normalized();
|
||||
iva.push_geometry(v0, n);
|
||||
iva.push_geometry(v1, n);
|
||||
iva.push_geometry(v2, n);
|
||||
iva.push_triangle(cnt, cnt + 1, cnt + 2);
|
||||
cnt += 3;
|
||||
}
|
||||
|
@ -113,10 +113,8 @@ public:
|
||||
// during MeshRaycaster existence.
|
||||
MeshRaycaster(const TriangleMesh& mesh)
|
||||
: m_emesh(mesh, true) // calculate epsilon for triangle-ray intersection from an average edge length
|
||||
, m_normals(its_face_normals(mesh.its))
|
||||
{
|
||||
m_normals.reserve(mesh.stl.facet_start.size());
|
||||
for (const stl_facet& facet : mesh.stl.facet_start)
|
||||
m_normals.push_back(facet.normal);
|
||||
}
|
||||
|
||||
void line_from_mouse_pos(const Vec2d& mouse_pos, const Transform3d& trafo, const Camera& camera,
|
||||
|
@ -342,7 +342,7 @@ SCENARIO( "TriangleMesh: Mesh merge functions") {
|
||||
cube.merge(cube2);
|
||||
cube.repair();
|
||||
THEN( "There are twice as many facets in the merged mesh as the original.") {
|
||||
REQUIRE(cube.stl.stats.number_of_facets == 2 * cube2.stl.stats.number_of_facets);
|
||||
REQUIRE(cube.facets_count() == 2 * cube2.facets_count());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -10,7 +10,6 @@
|
||||
#include "libslic3r/Format/AMF.hpp"
|
||||
#include "libslic3r/Format/3mf.hpp"
|
||||
#include "libslic3r/Format/OBJ.hpp"
|
||||
#include "libslic3r/Format/PRUS.hpp"
|
||||
#include "libslic3r/Format/STL.hpp"
|
||||
#include "libslic3r/PresetBundle.hpp"
|
||||
%}
|
||||
|
Loading…
Reference in New Issue
Block a user