Tech ENABLE_SHOW_NON_MANIFOLD_EDGES - 1st installment - Calculate and show in 3D view non-manifold edges as lines

This commit is contained in:
enricoturri1966 2022-01-20 13:32:24 +01:00
parent 81edc7d752
commit 18e2cc2298
12 changed files with 166 additions and 22 deletions

View file

@ -302,10 +302,10 @@ void GLVolume::SinkingContours::render()
void GLVolume::SinkingContours::update()
{
int object_idx = m_parent.object_idx();
Model& model = GUI::wxGetApp().plater()->model();
const int object_idx = m_parent.object_idx();
const Model& model = GUI::wxGetApp().plater()->model();
if (0 <= object_idx && object_idx < (int)model.objects.size() && m_parent.is_sinking() && !m_parent.is_below_printbed()) {
if (0 <= object_idx && object_idx < int(model.objects.size()) && m_parent.is_sinking() && !m_parent.is_below_printbed()) {
const BoundingBoxf3& box = m_parent.transformed_convex_hull_bounding_box();
if (!m_old_box.size().isApprox(box.size()) || m_old_box.min.z() != box.min.z()) {
m_old_box = box;
@ -317,13 +317,16 @@ void GLVolume::SinkingContours::update()
GUI::GLModel::InitializationData init_data;
MeshSlicingParams slicing_params;
slicing_params.trafo = m_parent.world_matrix();
Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params));
for (ExPolygon &expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) {
const Polygons polygons = union_(slice_mesh(mesh.its, 0.0f, slicing_params));
for (const ExPolygon &expoly : diff_ex(expand(polygons, float(scale_(HalfWidth))), shrink(polygons, float(scale_(HalfWidth))))) {
GUI::GLModel::InitializationData::Entity entity;
entity.type = GUI::GLModel::PrimitiveType::Triangles;
const std::vector<Vec3d> triangulation = triangulate_expolygon_3d(expoly);
entity.positions.reserve(entity.positions.size() + triangulation.size());
entity.normals.reserve(entity.normals.size() + triangulation.size());
entity.indices.reserve(entity.indices.size() + triangulation.size() / 3);
for (const Vec3d& v : triangulation) {
entity.positions.emplace_back(v.cast<float>() + Vec3f(0.0f, 0.0f, 0.015f)); // add a small positive z to avoid z-fighting
entity.positions.emplace_back(v.cast<float>() + 0.015f * Vec3f::UnitZ()); // add a small positive z to avoid z-fighting
entity.normals.emplace_back(Vec3f::UnitZ());
const size_t positions_count = entity.positions.size();
if (positions_count % 3 == 0) {
@ -344,6 +347,61 @@ void GLVolume::SinkingContours::update()
m_model.reset();
}
#if ENABLE_SHOW_NON_MANIFOLD_EDGES
void GLVolume::NonManifoldEdges::render()
{
update();
glsafe(::glLineWidth(2.0f));
glsafe(::glPushMatrix());
glsafe(::glMultMatrixd(m_parent.world_matrix().data()));
m_model.set_color(-1, complementary(m_parent.render_color));
m_model.render();
glsafe(::glPopMatrix());
}
void GLVolume::NonManifoldEdges::update()
{
if (!m_update_needed)
return;
m_model.reset();
const int object_idx = m_parent.object_idx();
const Model& model = GUI::wxGetApp().plater()->model();
if (0 <= object_idx && object_idx < int(model.objects.size())) {
const ModelObject* model_object = model.objects[object_idx];
const int volume_idx = m_parent.volume_idx();
if (0 <= volume_idx && volume_idx < int(model_object->volumes.size())) {
const ModelVolume* model_volume = model_object->volumes[volume_idx];
const TriangleMesh& mesh = model_volume->mesh();
const std::vector<std::pair<int, int>> edges = its_get_open_edges(mesh.its);
if (!edges.empty()) {
GUI::GLModel::InitializationData init_data;
GUI::GLModel::InitializationData::Entity entity;
entity.type = GUI::GLModel::PrimitiveType::Lines;
entity.positions.reserve(2 * edges.size());
entity.normals.reserve(2 * edges.size());
entity.indices.reserve(2 * edges.size());
for (const std::pair<int, int>& edge : edges) {
entity.positions.emplace_back(mesh.its.vertices[edge.first].cast<float>());
entity.positions.emplace_back(mesh.its.vertices[edge.second].cast<float>());
entity.normals.emplace_back(Vec3f::UnitZ());
entity.normals.emplace_back(Vec3f::UnitZ());
entity.indices.emplace_back(entity.positions.size() - 2);
entity.indices.emplace_back(entity.positions.size() - 1);
}
init_data.entities.emplace_back(entity);
m_model.init_from(init_data);
}
}
}
m_update_needed = false;
}
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
const ColorRGBA GLVolume::SELECTED_COLOR = ColorRGBA::GREEN();
const ColorRGBA GLVolume::HOVER_SELECT_COLOR = { 0.4f, 0.9f, 0.1f, 1.0f };
const ColorRGBA GLVolume::HOVER_DESELECT_COLOR = { 1.0f, 0.75f, 0.75f, 1.0f };
@ -363,6 +421,9 @@ const std::array<ColorRGBA, 4> GLVolume::MODEL_COLOR = { {
GLVolume::GLVolume(float r, float g, float b, float a)
: m_sla_shift_z(0.0)
, m_sinking_contours(*this)
#if ENABLE_SHOW_NON_MANIFOLD_EDGES
, m_non_manifold_edges(*this)
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
// geometry_id == 0 -> invalid
, geometry_id(std::pair<size_t, size_t>(0, 0))
, extruder_id(0)
@ -571,6 +632,13 @@ void GLVolume::render_sinking_contours()
m_sinking_contours.render();
}
#if ENABLE_SHOW_NON_MANIFOLD_EDGES
void GLVolume::render_non_manifold_edges()
{
m_non_manifold_edges.render();
}
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
std::vector<int> GLVolumeCollection::load_object(
const ModelObject *model_object,
int obj_idx,
@ -883,6 +951,14 @@ void GLVolumeCollection::render(GLVolumeCollection::ERenderType type, bool disab
}
}
#if ENABLE_SHOW_NON_MANIFOLD_EDGES
if (m_show_non_manifold_edges && GUI::wxGetApp().app_config->get("non_manifold_edges") == "1") {
for (GLVolumeWithIdAndZ& volume : to_render) {
volume.first->render_non_manifold_edges();
}
}
#endif // ENABLE_SHOW_NON_MANIFOLD_EDGES
if (disable_cullface)
glsafe(::glEnable(GL_CULL_FACE));