17#include <lagrange/Mesh.h>
18#include <lagrange/MeshTrait.h>
19#include <lagrange/NormalWeightingType.h>
20#include <lagrange/common.h>
21#include <lagrange/compute_triangle_normal.h>
22#include <lagrange/internal/doublearea.h>
23#include <lagrange/internal/internal_angles.h>
24#include <lagrange/legacy/inline.h>
34enum PerVertexNormalsWeightingType :
char {
36 PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM = 0,
39 PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA = 1,
42 PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE = 2,
45 PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT = 3,
48 NUM_PER_VERTEX_NORMALS_WEIGHTING_TYPE = 4
52template <
typename MeshType>
55 const PerVertexNormalsWeightingType weighting = PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE,
56 bool recompute_facet_normals =
false)
58 static_assert(MeshTrait<MeshType>::is_mesh(),
"Input type is not Mesh");
59 using Index = IndexOf<MeshType>;
60 using Scalar = ScalarOf<MeshType>;
62 if (mesh.get_vertex_per_facet() != 3) {
63 throw std::runtime_error(
"Input mesh is not triangle mesh.");
66 if (!mesh.has_facet_attribute(
"normal") || recompute_facet_normals) {
67 compute_triangle_normal(mesh);
71 using AttributeArray =
typename MeshType::AttributeArray;
72 const auto& vertices = mesh.get_vertices();
73 const auto& facets = mesh.get_facets();
74 const auto& facet_normals = mesh.get_facet_attribute(
"normal");
75 AttributeArray vertex_normals(vertices.rows(), 3);
76 vertex_normals.setZero();
81 AttributeArray weights(facets.rows(), 3);
84 case PER_VERTEX_NORMALS_WEIGHTING_TYPE_UNIFORM: weights.setConstant(Scalar(1));
break;
85 case PER_VERTEX_NORMALS_WEIGHTING_TYPE_DEFAULT:
86 case PER_VERTEX_NORMALS_WEIGHTING_TYPE_AREA: {
87 Eigen::Matrix<Scalar, Eigen::Dynamic, 1> areas;
88 lagrange::internal::doublearea(vertices, facets, areas);
89 weights = areas.replicate(1, 3);
92 case PER_VERTEX_NORMALS_WEIGHTING_TYPE_ANGLE:
95 default: assert(
false &&
"Unknown weighting type");
99 weights = weights.array().isFinite().select(weights, Scalar(0));
101 if (mesh.is_edge_data_initialized()) {
103 tbb::parallel_for(Index(0), mesh.get_num_vertices(), [&](Index v) {
104 mesh.foreach_corners_around_vertex(v, [&](const Index c) {
105 const Index f = c / 3;
106 const Index lv = c % 3;
107 vertex_normals.row(v) += weights(f, lv) * facet_normals.row(f);
112 for (Index f = 0; f < static_cast<Index>(facets.rows()); ++f) {
114 for (Index lv = 0; lv < 3; ++lv) {
115 const Index v = facets(f, lv);
116 vertex_normals.row(v) += weights(f, lv) * facet_normals.row(f);
124 tbb::parallel_for(Index(0), mesh.get_num_vertices(), [&](Index v) {
125 vertex_normals.row(v).stableNormalize();
129 mesh.add_vertex_attribute(
"normal");
130 mesh.import_vertex_attribute(
"normal", vertex_normals);
AttributeId compute_vertex_normal(SurfaceMesh< Scalar, Index > &mesh, VertexNormalOptions options={})
Compute per-vertex normals based on specified weighting type.
Definition: compute_vertex_normal.cpp:34
#define la_runtime_assert(...)
Runtime assertion check.
Definition: assert.h:169
void internal_angles(const Eigen::MatrixBase< DerivedV > &vertices, const Eigen::MatrixBase< DerivedF > &facets, Eigen::PlainObjectBase< DerivedK > &angles)
Compute internal angles for a triangle mesh.
Definition: internal_angles.h:39
Main namespace for Lagrange.
Definition: AABBIGL.h:30