Skip to content

Commit e8947ac

Browse files
committed
add generic functions for update normal algorithms
1 parent 0ab734d commit e8947ac

File tree

1 file changed

+184
-133
lines changed

1 file changed

+184
-133
lines changed

include/vclib/algorithms/update/normal.h

Lines changed: 184 additions & 133 deletions
Original file line numberDiff line numberDiff line change
@@ -24,12 +24,149 @@
2424
#define VCL_ALGORITHMS_UPDATE_NORMAL_H
2525

2626
#include <vclib/mesh/requirements.h>
27+
#include <vclib/misc/logger.h>
2728
#include <vclib/space/matrix.h>
2829

2930
#include "../polygon.h"
3031

3132
namespace vcl {
3233

34+
template<uint ELEM_ID, MeshConcept MeshType, LoggerConcept LogType = NullLogger>
35+
void normalizePerElementNormals(
36+
MeshType& mesh,
37+
bool noThrow = true,
38+
LogType& log = nullLogger)
39+
{
40+
vcl::requirePerElementComponent<ELEM_ID, NORMAL>(mesh);
41+
42+
if constexpr (isLoggerValid<LogType>()) {
43+
log.log(
44+
0, "Normalizing per-" + elementEnumString<ELEM_ID>() + " normals");
45+
}
46+
47+
for (auto& elem : mesh.template elements<ELEM_ID>()) {
48+
try {
49+
elem.normal().normalize();
50+
}
51+
catch (const std::exception& e) {
52+
if (noThrow) {
53+
if constexpr (isLoggerValid<LogType>()) {
54+
log.log(LogType::WARNING, e.what());
55+
}
56+
}
57+
else {
58+
throw e;
59+
}
60+
}
61+
}
62+
63+
if constexpr (isLoggerValid<LogType>()) {
64+
log.log(
65+
100, "Per-" + elementEnumString<ELEM_ID>() + " normals normalized.");
66+
}
67+
}
68+
69+
template<uint ELEM_ID, MeshConcept MeshType>
70+
void clearPerElementNormals(MeshType& mesh)
71+
{
72+
vcl::requirePerElementComponent<ELEM_ID, NORMAL>(mesh);
73+
74+
for (auto& elem : mesh.template elements<ELEM_ID>()) {
75+
elem.normal().setZero();
76+
}
77+
}
78+
79+
template<uint ELEM_ID, MeshConcept MeshType, typename MScalar>
80+
void multiplyPerElementNormalsByMatrix(
81+
MeshType& mesh,
82+
vcl::Matrix33<MScalar> mat,
83+
bool removeScalingFromMatrix = true)
84+
{
85+
vcl::requirePerElementComponent<ELEM_ID, NORMAL>(mesh);
86+
87+
if (removeScalingFromMatrix) {
88+
MScalar scaleX = std::sqrt(
89+
mat(0, 0) * mat(0, 0) + mat(0, 1) * mat(0, 1) +
90+
mat(0, 2) * mat(0, 2));
91+
MScalar scaleY = std::sqrt(
92+
mat(1, 0) * mat(1, 0) + mat(1, 1) * mat(1, 1) +
93+
mat(1, 2) * mat(1, 2));
94+
MScalar scaleZ = std::sqrt(
95+
mat(2, 0) * mat(2, 0) + mat(2, 1) * mat(2, 1) +
96+
mat(2, 2) * mat(2, 2));
97+
for (int i = 0; i < 3; ++i) {
98+
mat(0, i) /= scaleX;
99+
mat(1, i) /= scaleY;
100+
mat(2, i) /= scaleZ;
101+
}
102+
}
103+
for (auto& elem : mesh.template elements<ELEM_ID>()) {
104+
elem.normal() *= mat;
105+
}
106+
}
107+
108+
template<uint ELEM_ID, MeshConcept MeshType, typename MScalar>
109+
void multiplyPerElementNormalsByMatrix(
110+
MeshType& mesh,
111+
const vcl::Matrix44<MScalar>& mat,
112+
bool removeScalingFromMatrix = true)
113+
{
114+
vcl::requirePerElementComponent<ELEM_ID, NORMAL>(mesh);
115+
116+
Matrix33<MScalar> m33 = mat.block(0, 0, 3, 3);
117+
multiplyPerElementNormalsByMatrix<ELEM_ID>(
118+
mesh, m33, removeScalingFromMatrix);
119+
}
120+
121+
/**
122+
* @brief Sets to zero the normals of all the vertices of the mesh, including
123+
* the unreferenced ones.
124+
*
125+
* Requirements:
126+
* - Mesh:
127+
* - Vertices:
128+
* - Normal
129+
*
130+
* @param[in,out] m: The mesh on which clear the vertex normals.
131+
*/
132+
template<MeshConcept MeshType>
133+
void clearPerVertexNormals(MeshType& m)
134+
{
135+
clearPerElementNormals<VERTEX>(m);
136+
}
137+
138+
/**
139+
* @brief Sets to zero the normals of all the faces of the mesh.
140+
*
141+
* Requirements:
142+
* - Mesh:
143+
* - Faces:
144+
* - Normal
145+
*
146+
* @param[in,out] m: The mesh on which clear the face normals.
147+
*/
148+
template<FaceMeshConcept MeshType>
149+
void clearPerFaceNormals(MeshType& m)
150+
{
151+
clearPerElementNormals<FACE>(m);
152+
}
153+
154+
/**
155+
* @brief Normalizes the length of the vertex normals.
156+
*
157+
* Requirements:
158+
* - Mesh:
159+
* - Vertices:
160+
* - Normal
161+
*
162+
* @param[in,out] m: the mesh on which normalize the vertex normals.
163+
*/
164+
template<MeshConcept MeshType>
165+
void normalizePerVertexNormals(MeshType& m)
166+
{
167+
normalizePerElementNormals<VERTEX>(m);
168+
}
169+
33170
/**
34171
* @brief Normalizes the length of the face normals.
35172
*
@@ -43,11 +180,54 @@ namespace vcl {
43180
template<FaceMeshConcept MeshType>
44181
void normalizePerFaceNormals(MeshType& m)
45182
{
46-
vcl::requirePerFaceNormal(m);
183+
normalizePerElementNormals<FACE>(m);
184+
}
47185

48-
for (auto& n : m.faces() | views::normals) {
49-
n.normalize();
50-
}
186+
/**
187+
* @brief Multiplies the Vertex Normals by the given TRS 4x4 Matrix.
188+
* By default, the scale component is removed from the matrix.
189+
*
190+
* Requirements:
191+
* - Mesh:
192+
* - Vertices:
193+
* - Normal
194+
*
195+
* @param[in,out] mesh: the mesh on which multiply the vertex normals.
196+
* @param[in] mat: the 4x4 TRS matrix that is multiplied to the normals.
197+
* @param[in] removeScalingFromMatrix: if true (default), the scale component is
198+
* removed from the matrix.
199+
*/
200+
template<MeshConcept MeshType, typename MScalar>
201+
void multiplyPerVertexNormalsByMatrix(
202+
MeshType& mesh,
203+
const vcl::Matrix44<MScalar>& mat,
204+
bool removeScalingFromMatrix = true)
205+
{
206+
multiplyPerElementNormalsByMatrix<VERTEX>(
207+
mesh, mat, removeScalingFromMatrix);
208+
}
209+
210+
/**
211+
* @brief Multiplies the Face Normals by the given TRS 4x4 Matrix.
212+
* By default, the scale component is removed from the matrix.
213+
*
214+
* Requirements:
215+
* - Mesh:
216+
* - Faces
217+
* - Normal
218+
*
219+
* @param[in,out] mesh: the mesh on which multiply the face normals.
220+
* @param[in] mat: the 4x4 TRS matrix that is multiplied to the normals.
221+
* @param[in] removeScalingFromMatrix: if true (default), the scale component is
222+
* removed from the matrix.
223+
*/
224+
template<FaceMeshConcept MeshType, typename MScalar>
225+
void multiplyPerFaceNormalsByMatrix(
226+
MeshType& mesh,
227+
const vcl::Matrix44<MScalar>& mat,
228+
bool removeScalingFromMatrix = true)
229+
{
230+
multiplyPerElementNormalsByMatrix<FACE>(mesh, mat, removeScalingFromMatrix);
51231
}
52232

53233
/**
@@ -72,26 +252,7 @@ void updatePerFaceNormals(MeshType& m, bool normalize = true)
72252
normalizePerFaceNormals(m);
73253
}
74254

75-
/**
76-
* @brief Sets to zero the normals of all the vertices of the mesh, including
77-
* the unreferenced ones.
78-
*
79-
* Requirements:
80-
* - Mesh:
81-
* - Vertices:
82-
* - Normal
83-
*
84-
* @param[in,out] m: The mesh on which clear the vertex normals.
85-
*/
86-
template<MeshConcept MeshType>
87-
void clearPerVertexNormals(MeshType& m)
88-
{
89-
vcl::requirePerVertexNormal(m);
90255

91-
for (auto& n : m.vertices() | views::normals) {
92-
n.setZero();
93-
}
94-
}
95256

96257
/**
97258
* @brief Sets to zero all the normals of vertices that are referenced by at
@@ -121,25 +282,7 @@ void clearPerReferencedVertexNormals(MeshType& m)
121282
}
122283
}
123284

124-
/**
125-
* @brief Normalizes the length of the vertex normals.
126-
*
127-
* Requirements:
128-
* - Mesh:
129-
* - Vertices:
130-
* - Normal
131-
*
132-
* @param[in,out] m: the mesh on which normalize the vertex normals.
133-
*/
134-
template<MeshConcept MeshType>
135-
void normalizePerVertexNormals(MeshType& m)
136-
{
137-
vcl::requirePerVertexNormal(m);
138285

139-
for (auto& n : m.vertices() | views::normals) {
140-
n.normalize();
141-
}
142-
}
143286

144287
/**
145288
* @brief Computes the vertex normal as the classic area weighted average.
@@ -325,98 +468,6 @@ void updatePerVertexNormalsNelsonMaxWeighted(MeshType& m, bool normalize = true)
325468
normalizePerVertexNormals(m);
326469
}
327470

328-
/**
329-
* @brief Multiplies the Face Normals by the given TRS 4x4 Matrix.
330-
* By default, the scale component is removed from the matrix.
331-
*
332-
* Requirements:
333-
* - Mesh:
334-
* - Faces
335-
* - Normal
336-
*
337-
* @param[in,out] mesh: the mesh on which multiply the face normals.
338-
* @param[in] mat: the 4x4 TRS matrix that is multiplied to the normals.
339-
* @param[in] removeScalingFromMatrix: if true (default), the scale component is
340-
* removed from the matrix.
341-
*/
342-
template<FaceMeshConcept MeshType, typename MScalar>
343-
void multiplyPerFaceNormalsByMatrix(
344-
MeshType& mesh,
345-
const vcl::Matrix44<MScalar>& mat,
346-
bool removeScalingFromMatrix = true)
347-
{
348-
requirePerFaceNormal(mesh);
349-
350-
using FaceType = MeshType::FaceType;
351-
352-
Matrix33<MScalar> m33 = mat.block(0, 0, 3, 3);
353-
if (removeScalingFromMatrix) {
354-
MScalar scaleX = std::sqrt(
355-
m33(0, 0) * m33(0, 0) + m33(0, 1) * m33(0, 1) +
356-
m33(0, 2) * m33(0, 2));
357-
MScalar scaleY = std::sqrt(
358-
m33(1, 0) * m33(1, 0) + m33(1, 1) * m33(1, 1) +
359-
m33(1, 2) * m33(1, 2));
360-
MScalar scaleZ = std::sqrt(
361-
m33(2, 0) * m33(2, 0) + m33(2, 1) * m33(2, 1) +
362-
m33(2, 2) * m33(2, 2));
363-
for (int i = 0; i < 3; ++i) {
364-
m33(0, i) /= scaleX;
365-
m33(1, i) /= scaleY;
366-
m33(2, i) /= scaleZ;
367-
}
368-
}
369-
for (FaceType& f : mesh.faces()) {
370-
f.normal() *= m33;
371-
}
372-
}
373-
374-
/**
375-
* @brief Multiplies the Vertex Normals by the given TRS 4x4 Matrix.
376-
* By default, the scale component is removed from the matrix.
377-
*
378-
* Requirements:
379-
* - Mesh:
380-
* - Vertices:
381-
* - Normal
382-
*
383-
* @param[in,out] mesh: the mesh on which multiply the vertex normals.
384-
* @param[in] mat: the 4x4 TRS matrix that is multiplied to the normals.
385-
* @param[in] removeScalingFromMatrix: if true (default), the scale component is
386-
* removed from the matrix.
387-
*/
388-
template<MeshConcept MeshType, typename MScalar>
389-
void multiplyPerVertexNormalsByMatrix(
390-
MeshType& mesh,
391-
const vcl::Matrix44<MScalar>& mat,
392-
bool removeScalingFromMatrix = true)
393-
{
394-
requirePerVertexNormal(mesh);
395-
396-
using VertexType = MeshType::VertexType;
397-
398-
Matrix33<MScalar> m33 = mat.block(0, 0, 3, 3);
399-
if (removeScalingFromMatrix) {
400-
MScalar scaleX = std::sqrt(
401-
m33(0, 0) * m33(0, 0) + m33(0, 1) * m33(0, 1) +
402-
m33(0, 2) * m33(0, 2));
403-
MScalar scaleY = std::sqrt(
404-
m33(1, 0) * m33(1, 0) + m33(1, 1) * m33(1, 1) +
405-
m33(1, 2) * m33(1, 2));
406-
MScalar scaleZ = std::sqrt(
407-
m33(2, 0) * m33(2, 0) + m33(2, 1) * m33(2, 1) +
408-
m33(2, 2) * m33(2, 2));
409-
for (int i = 0; i < 3; ++i) {
410-
m33(0, i) /= scaleX;
411-
m33(1, i) /= scaleY;
412-
m33(2, i) /= scaleZ;
413-
}
414-
}
415-
for (VertexType& v : mesh.vertices()) {
416-
v.normal() *= m33;
417-
}
418-
}
419-
420471
} // namespace vcl
421472

422473
#endif // VCL_ALGORITHMS_UPDATE_NORMAL_H

0 commit comments

Comments
 (0)