24
24
#define VCL_ALGORITHMS_UPDATE_NORMAL_H
25
25
26
26
#include < vclib/mesh/requirements.h>
27
+ #include < vclib/misc/logger.h>
27
28
#include < vclib/space/matrix.h>
28
29
29
30
#include " ../polygon.h"
30
31
31
32
namespace vcl {
32
33
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
+
33
170
/* *
34
171
* @brief Normalizes the length of the face normals.
35
172
*
@@ -43,11 +180,54 @@ namespace vcl {
43
180
template <FaceMeshConcept MeshType>
44
181
void normalizePerFaceNormals (MeshType& m)
45
182
{
46
- vcl::requirePerFaceNormal (m);
183
+ normalizePerElementNormals<FACE>(m);
184
+ }
47
185
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);
51
231
}
52
232
53
233
/* *
@@ -72,26 +252,7 @@ void updatePerFaceNormals(MeshType& m, bool normalize = true)
72
252
normalizePerFaceNormals (m);
73
253
}
74
254
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);
90
255
91
- for (auto & n : m.vertices () | views::normals) {
92
- n.setZero ();
93
- }
94
- }
95
256
96
257
/* *
97
258
* @brief Sets to zero all the normals of vertices that are referenced by at
@@ -121,25 +282,7 @@ void clearPerReferencedVertexNormals(MeshType& m)
121
282
}
122
283
}
123
284
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);
138
285
139
- for (auto & n : m.vertices () | views::normals) {
140
- n.normalize ();
141
- }
142
- }
143
286
144
287
/* *
145
288
* @brief Computes the vertex normal as the classic area weighted average.
@@ -325,98 +468,6 @@ void updatePerVertexNormalsNelsonMaxWeighted(MeshType& m, bool normalize = true)
325
468
normalizePerVertexNormals (m);
326
469
}
327
470
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
-
420
471
} // namespace vcl
421
472
422
473
#endif // VCL_ALGORITHMS_UPDATE_NORMAL_H
0 commit comments