ENABLE_SMOOTH_NORMALS (#14080)

* ENABLE_SMOOTH_NORMALS

* Remove definition of macro L if defined

* Update GLModel.cpp

* suavizado ajustado en 5 grados

5 grados

3,5 grados

* Ajuste de brillo menos intenso

* opcion smooth normals

Update GLModel.cpp

test

test 3

* cleaning macros

* tooltip

* Apply suggestion from @RF47

* Apply suggestion from @RF47

* Apply suggestions from code review

Co-authored-by: Rodrigo Faselli <162915171+RF47@users.noreply.github.com>
This commit is contained in:
Rodrigo Faselli
2026-06-18 22:42:12 -03:00
committed by SoftFever
parent 70fd764e7d
commit da7e0540a9
9 changed files with 79 additions and 61 deletions

View File

@@ -276,6 +276,9 @@ void AppConfig::set_defaults()
if (get(SETTING_OPENGL_PHONG_BASIC_PLATE_SHADOWS).empty())
set_bool(SETTING_OPENGL_PHONG_BASIC_PLATE_SHADOWS, false);
if (get(SETTING_OPENGL_PHONG_SMOOTH_NORMALS).empty())
set_bool(SETTING_OPENGL_PHONG_SMOOTH_NORMALS, false);
if (get(SETTING_OPENGL_PHONG_SSAO).empty())
set_bool(SETTING_OPENGL_PHONG_SSAO, false);

View File

@@ -39,6 +39,7 @@ using namespace nlohmann;
#define SETTING_OPENGL_SHADING_MODEL "opengl_shading_model"
#define SETTING_OPENGL_PHONG_BASIC_PLATE_SHADOWS "opengl_phong_basic_plate_shadows"
#define SETTING_OPENGL_PHONG_SSAO "opengl_phong_ssao"
#define SETTING_OPENGL_PHONG_SMOOTH_NORMALS "opengl_phong_smooth_normals"
#if defined(_WIN32) || defined(_WIN64)
#define BAMBU_NETWORK_AGENT_VERSION_LEGACY "01.10.01.09"

View File

@@ -24,8 +24,7 @@
// Enable rendering of objects using environment map
#define ENABLE_ENVIRONMENT_MAP 0
// Enable smoothing of objects normals
#define ENABLE_SMOOTH_NORMALS 0
// Enable rendering markers for options in preview as fixed screen size points
#define ENABLE_FIXED_SCREEN_SIZE_POINT_MARKERS 1

View File

@@ -758,13 +758,9 @@ int GLVolumeCollection::load_object_volume(
GLVolume& v = *this->volumes.back();
v.set_color(color_from_model_volume(*model_volume));
v.name = model_volume->name;
#if ENABLE_SMOOTH_NORMALS
v.model.init_from(mesh, true);
#else
v.model.init_from(*mesh);
if (need_raycaster) { v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(mesh); }
#endif // ENABLE_SMOOTH_NORMALS
v.composite_id = GLVolume::CompositeID(obj_idx, volume_idx, instance_idx);
if (model_volume->is_model_part())
@@ -815,13 +811,9 @@ void GLVolumeCollection::load_object_auxiliary(
const ModelInstance& model_instance = *print_object->model_object()->instances[instance_idx.first];
this->volumes.emplace_back(new GLVolume((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR));
GLVolume& v = *this->volumes.back();
#if ENABLE_SMOOTH_NORMALS
v.model.init_from(mesh, true);
#else
v.model.init_from(mesh);
v.model.set_color((milestone == slaposPad) ? GLVolume::SLA_PAD_COLOR : GLVolume::SLA_SUPPORT_COLOR);
v.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<const TriangleMesh>(mesh));
#endif // ENABLE_SMOOTH_NORMALS
v.composite_id = GLVolume::CompositeID(obj_idx, -int(milestone), (int)instance_idx.first);
v.geometry_id = std::pair<size_t, size_t>(timestamp, model_instance.id().id);
// Create a copy of the convex hull mesh for each instance. Use a move operator on the last instance.

View File

@@ -2793,22 +2793,14 @@ void GLCanvas3D::reload_scene(bool refresh_immediately, bool force_full_scene_re
TriangleMesh mesh = print_object->get_mesh(slaposDrillHoles);
assert(! mesh.empty());
mesh.transform(sla_print->sla_trafo(*m_model->objects[volume.object_idx()]).inverse());
#if ENABLE_SMOOTH_NORMALS
volume.model.init_from(mesh, true);
#else
volume.model.init_from(mesh);
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(mesh));
#endif // ENABLE_SMOOTH_NORMALS
}
else {
// Reload the original volume.
#if ENABLE_SMOOTH_NORMALS
volume.model.init_from(m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh(), true);
#else
const TriangleMesh& new_mesh = m_model->objects[volume.object_idx()]->volumes[volume.volume_idx()]->mesh();
volume.model.init_from(new_mesh);
volume.mesh_raycaster = std::make_unique<GUI::MeshRaycaster>(std::make_shared<TriangleMesh>(new_mesh));
#endif // ENABLE_SMOOTH_NORMALS
}
}
//FIXME it is an ugly hack to write the timestamp into the "offsets" field to not have to add another member variable
@@ -10001,11 +9993,7 @@ void GLCanvas3D::_load_sla_shells()
const TriangleMesh& mesh, const ColorRGBA& color, bool outside_printer_detection_enabled) {
m_volumes.volumes.emplace_back(new GLVolume(color));
GLVolume& v = *m_volumes.volumes.back();
#if ENABLE_SMOOTH_NORMALS
v.model.init_from(mesh, true);
#else
v.model.init_from(mesh);
#endif // ENABLE_SMOOTH_NORMALS
v.shader_outside_printer_detection_enabled = outside_printer_detection_enabled;
v.composite_id.volume_id = volume_id;
v.set_instance_offset(unscale(instance.shift.x(), instance.shift.y(), 0.0));

View File

@@ -14,18 +14,20 @@
#include <boost/filesystem/operations.hpp>
#include <boost/algorithm/string/predicate.hpp>
#if ENABLE_SMOOTH_NORMALS
#if defined(L)
#undef L
#endif
#include <igl/per_face_normals.h>
#include <igl/per_corner_normals.h>
#include <igl/per_vertex_normals.h>
#endif // ENABLE_SMOOTH_NORMALS
#include <glad/gl.h>
namespace Slic3r {
namespace GUI {
#if ENABLE_SMOOTH_NORMALS
static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_normal>& normals)
{
using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
@@ -41,7 +43,7 @@ static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_norm
Eigen::Index(face_normals.size()), 3).cast<double>();
Eigen::MatrixXd out_normals;
igl::per_corner_normals(vertices, indices, in_normals, 1.0, out_normals);
igl::per_corner_normals(vertices, indices, 1.0, out_normals);
normals = std::vector<stl_normal>(mesh.its.vertices.size());
for (size_t i = 0; i < mesh.its.indices.size(); ++i) {
@@ -50,7 +52,6 @@ static void smooth_normals_corner(const TriangleMesh& mesh, std::vector<stl_norm
}
}
}
#endif // ENABLE_SMOOTH_NORMALS
void GLModel::Geometry::add_vertex(const Vec2f& position)
{
@@ -455,17 +456,41 @@ void GLModel::init_from(const indexed_triangle_set& its)
data.reserve_vertices(3 * its.indices.size());
data.reserve_indices(3 * its.indices.size());
// vertices + indices
unsigned int vertices_counter = 0;
for (uint32_t i = 0; i < its.indices.size(); ++i) {
const stl_triangle_vertex_indices face = its.indices[i];
const stl_vertex vertex[3] = { its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]] };
const stl_vertex n = face_normal_normalized(vertex);
for (size_t j = 0; j < 3; ++j) {
data.add_vertex(vertex[j], n);
// Read user preference: smooth normals enabled
const bool realistic_mode = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_REALISTIC_MODE);
const bool smooth_normals_enabled = wxGetApp().app_config != nullptr && wxGetApp().app_config->get_bool(SETTING_OPENGL_PHONG_SMOOTH_NORMALS);
if (realistic_mode && smooth_normals_enabled) {
// Use per-corner smooth normals (via IGL)
using MapMatrixXfUnaligned = Eigen::Map<const Eigen::Matrix<float, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
using MapMatrixXiUnaligned = Eigen::Map<const Eigen::Matrix<int, Eigen::Dynamic, Eigen::Dynamic, Eigen::RowMajor | Eigen::DontAlign>>;
Eigen::MatrixXd vertices = MapMatrixXfUnaligned(its.vertices.front().data(), Eigen::Index(its.vertices.size()), 3).cast<double>();
Eigen::MatrixXi indices = MapMatrixXiUnaligned(its.indices.front().data(), Eigen::Index(its.indices.size()), 3);
Eigen::MatrixXd corner_normals;
igl::per_corner_normals(vertices, indices, 5.0, corner_normals);
unsigned int vertices_counter = 0;
for (uint32_t i = 0; i < its.indices.size(); ++i) {
const stl_triangle_vertex_indices face = its.indices[i];
for (size_t j = 0; j < 3; ++j) {
const Vec3f normal = corner_normals.row(Eigen::Index(i * 3 + j)).cast<float>();
data.add_vertex(its.vertices[face[j]], normal);
}
data.add_triangle(vertices_counter, vertices_counter + 1, vertices_counter + 2);
vertices_counter += 3;
}
} else {
//Original flat (per-face) normals
unsigned int vertices_counter = 0;
for (uint32_t i = 0; i < its.indices.size(); ++i) {
const stl_triangle_vertex_indices face = its.indices[i];
const stl_vertex vertex[3] = {its.vertices[face[0]], its.vertices[face[1]], its.vertices[face[2]]};
const stl_vertex n = face_normal_normalized(vertex);
for (size_t j = 0; j < 3; ++j)
data.add_vertex(vertex[j], n);
data.add_triangle(vertices_counter, vertices_counter + 1, vertices_counter + 2);
vertices_counter += 3;
}
vertices_counter += 3;
data.add_triangle(vertices_counter - 3, vertices_counter - 2, vertices_counter - 1);
}
// update bounding box

View File

@@ -1578,6 +1578,15 @@ void PreferencesDialog::create_items()
);
g_sizer->Add(item_realistic_shadows);
auto item_realistic_smooth_normals = create_item_checkbox(
_L("Smooth normals"),
_L("Applies smooth normals to the realistic view.\n\nRequires manual scene reload to take effect "
"(right-click on 3D view → \"Reload All\")."),
SETTING_OPENGL_PHONG_SMOOTH_NORMALS
);
g_sizer->Add(item_realistic_smooth_normals);
//// GRAPHICS > Anti-aliasing
g_sizer->Add(create_item_title(_L("Anti-aliasing")), 1, wxEXPAND);