Blender V4.3
WingedEdgeBuilder.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008-2023 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include <set>
12
13#include "WingedEdgeBuilder.h"
14
16
18
19#include "BLI_sys_types.h"
20
21using namespace std;
22
23namespace Freestyle {
24
25void WingedEdgeBuilder::visitIndexedFaceSet(IndexedFaceSet &ifs)
26{
28 return;
29 }
30 WShape *shape = new WShape;
31 if (!buildWShape(*shape, ifs)) {
32 delete shape;
33 return;
34 }
35 shape->setId(ifs.getId().getFirst());
36 // ifs.setId(shape->GetId());
37}
38
39void WingedEdgeBuilder::visitNodeShape(NodeShape &ns)
40{
41 // Sets the current material to iShapeode->material:
42 _current_frs_material = &ns.frs_material();
43}
44
45void WingedEdgeBuilder::visitNodeTransform(NodeTransform &tn)
46{
47 if (!_current_matrix) {
48 _current_matrix = new Matrix44r(tn.matrix());
49 return;
50 }
51
52 _matrices_stack.push_back(_current_matrix);
53 Matrix44r *new_matrix = new Matrix44r(*_current_matrix * tn.matrix());
54 _current_matrix = new_matrix;
55}
56
58{
59 delete _current_matrix;
60
61 if (_matrices_stack.empty()) {
62 _current_matrix = nullptr;
63 return;
64 }
65
66 _current_matrix = _matrices_stack.back();
67 _matrices_stack.pop_back();
68}
69
71{
72 uint vsize = ifs.vsize();
73 uint nsize = ifs.nsize();
74 // soc unused - uint tsize = ifs.tsize();
75
76 const float *vertices = ifs.vertices();
77 const float *normals = ifs.normals();
78 const float *texCoords = ifs.texCoords();
79
80 float *new_vertices;
81 float *new_normals;
82
83 new_vertices = new float[vsize];
84 new_normals = new float[nsize];
85
86 // transform coordinates from local to world system
87 if (_current_matrix) {
88 transformVertices(vertices, vsize, *_current_matrix, new_vertices);
89 transformNormals(normals, nsize, *_current_matrix, new_normals);
90 }
91 else {
92 memcpy(new_vertices, vertices, vsize * sizeof(*new_vertices));
93 memcpy(new_normals, normals, nsize * sizeof(*new_normals));
94 }
95
96 const IndexedFaceSet::TRIANGLES_STYLE *faceStyle = ifs.trianglesStyle();
97
98 vector<FrsMaterial> frs_materials;
99 if (ifs.msize()) {
100 const FrsMaterial *const *mats = ifs.frs_materials();
101 for (uint i = 0; i < ifs.msize(); ++i) {
102 frs_materials.push_back(*(mats[i]));
103 }
104 shape.setFrsMaterials(frs_materials);
105 }
106
107#if 0
108 const FrsMaterial *mat = (ifs.frs_material());
109 if (mat) {
110 shape.setFrsMaterial(*mat);
111 }
112 else if (_current_frs_material) {
113 shape.setFrsMaterial(*_current_frs_material);
114 }
115#endif
116 const IndexedFaceSet::FaceEdgeMark *faceEdgeMarks = ifs.faceEdgeMarks();
117
118 // sets the current WShape to shape
119 _current_wshape = &shape;
120
121 // create a WVertex for each vertex
122 buildWVertices(shape, new_vertices, vsize);
123
124 const uint *vindices = ifs.vindices();
125 const uint *nindices = ifs.nindices();
126 const uint *tindices = nullptr;
127 if (ifs.tsize()) {
128 tindices = ifs.tindices();
129 }
130
131 const uint *mindices = nullptr;
132 if (ifs.msize()) {
133 mindices = ifs.mindices();
134 }
135 const uint *numVertexPerFace = ifs.numVertexPerFaces();
136 const uint numfaces = ifs.numFaces();
137
138 for (uint index = 0; index < numfaces; index++) {
139 switch (faceStyle[index]) {
141 buildTriangleStrip(new_vertices,
142 new_normals,
143 frs_materials,
144 texCoords,
145 faceEdgeMarks,
146 vindices,
147 nindices,
148 mindices,
149 tindices,
150 numVertexPerFace[index]);
151 break;
153 buildTriangleFan(new_vertices,
154 new_normals,
155 frs_materials,
156 texCoords,
157 faceEdgeMarks,
158 vindices,
159 nindices,
160 mindices,
161 tindices,
162 numVertexPerFace[index]);
163 break;
165 buildTriangles(new_vertices,
166 new_normals,
167 frs_materials,
168 texCoords,
169 faceEdgeMarks,
170 vindices,
171 nindices,
172 mindices,
173 tindices,
174 numVertexPerFace[index]);
175 break;
176 }
177 vindices += numVertexPerFace[index];
178 nindices += numVertexPerFace[index];
179 if (mindices) {
180 mindices += numVertexPerFace[index];
181 }
182 if (tindices) {
183 tindices += numVertexPerFace[index];
184 }
185 faceEdgeMarks++;
186 }
187
188 delete[] new_vertices;
189 delete[] new_normals;
190
191 if (shape.GetFaceList().empty()) { // this may happen due to degenerate triangles
192 return false;
193 }
194
195#if 0
196 // compute bbox
197 shape.ComputeBBox();
198 // compute mean edge size:
199 shape.ComputeMeanEdgeSize();
200#endif
201
202 // Parse the built winged-edge shape to update post-flags
203 set<Vec3f> normalsSet;
204 vector<WVertex *> &wvertices = shape.getVertexList();
205 for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
206 ++wv)
207 {
208 if ((*wv)->isBoundary()) {
209 continue;
210 }
211 if ((*wv)->GetEdges().empty()) {
212 // This means that the WVertex has no incoming edges... (12-Sep-2011 T.K.)
213 continue;
214 }
215 normalsSet.clear();
216 WVertex::face_iterator fit = (*wv)->faces_begin();
217 WVertex::face_iterator fitend = (*wv)->faces_end();
218 for (; fit != fitend; ++fit) {
219 WFace *face = *fit;
220 normalsSet.insert(face->GetVertexNormal(*wv));
221 if (normalsSet.size() != 1) {
222 break;
223 }
224 }
225 if (normalsSet.size() != 1) {
226 (*wv)->setSmooth(false);
227 }
228 }
229
230 // Adds the new WShape to the WingedEdge structure
231 _winged_edge->addWShape(&shape);
232
233 return true;
234}
235
236void WingedEdgeBuilder::buildWVertices(WShape &shape, const float *vertices, uint vsize)
237{
238 WVertex *vertex;
239 for (uint i = 0; i < vsize; i += 3) {
240 vertex = new WVertex(Vec3f(vertices[i], vertices[i + 1], vertices[i + 2]));
241 vertex->setId(i / 3);
242 shape.AddVertex(vertex);
243 }
244}
245
246void WingedEdgeBuilder::buildTriangleStrip(const float * /*vertices*/,
247 const float *normals,
248 vector<FrsMaterial> & /*iMaterials*/,
249 const float *texCoords,
250 const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
251 const uint *vindices,
252 const uint *nindices,
253 const uint *mindices,
254 const uint *tindices,
255 const uint nvertices)
256{
257 uint nDoneVertices = 2; /* Number of vertices already treated. */
258 uint nTriangle = 0; /* Number of the triangle currently being treated. */
259 // int nVertex = 0; /* Vertex number. */
260
261 WShape *currentShape = _current_wshape; // the current shape being built
262 vector<WVertex *> triangleVertices;
263 vector<Vec3f> triangleNormals;
264 vector<Vec2f> triangleTexCoords;
265 vector<bool> triangleFaceEdgeMarks;
266
267 while (nDoneVertices < nvertices) {
268 // clear the vertices list:
269 triangleVertices.clear();
270 // Then rebuild it:
271 if (0 == nTriangle % 2) { // if nTriangle is even
272 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]);
273 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]);
274 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]);
275
276 triangleNormals.emplace_back(normals[nindices[nTriangle]],
277 normals[nindices[nTriangle] + 1],
278 normals[nindices[nTriangle] + 2]);
279 triangleNormals.emplace_back(normals[nindices[nTriangle + 1]],
280 normals[nindices[nTriangle + 1] + 1],
281 normals[nindices[nTriangle + 1] + 2]);
282 triangleNormals.emplace_back(normals[nindices[nTriangle + 2]],
283 normals[nindices[nTriangle + 2] + 1],
284 normals[nindices[nTriangle + 2] + 2]);
285
286 if (texCoords) {
287 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle]],
288 texCoords[tindices[nTriangle] + 1]);
289 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle + 1]],
290 texCoords[tindices[nTriangle + 1] + 1]);
291 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle + 2]],
292 texCoords[tindices[nTriangle + 2] + 1]);
293 }
294 }
295 else { // if nTriangle is odd
296 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle] / 3]);
297 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 2] / 3]);
298 triangleVertices.push_back(currentShape->getVertexList()[vindices[nTriangle + 1] / 3]);
299
300 triangleNormals.emplace_back(normals[nindices[nTriangle]],
301 normals[nindices[nTriangle] + 1],
302 normals[nindices[nTriangle] + 2]);
303 triangleNormals.emplace_back(normals[nindices[nTriangle + 2]],
304 normals[nindices[nTriangle + 2] + 1],
305 normals[nindices[nTriangle + 2] + 2]);
306 triangleNormals.emplace_back(normals[nindices[nTriangle + 1]],
307 normals[nindices[nTriangle + 1] + 1],
308 normals[nindices[nTriangle + 1] + 2]);
309
310 if (texCoords) {
311 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle]],
312 texCoords[tindices[nTriangle] + 1]);
313 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle + 2]],
314 texCoords[tindices[nTriangle + 2] + 1]);
315 triangleTexCoords.emplace_back(texCoords[tindices[nTriangle + 1]],
316 texCoords[tindices[nTriangle + 1] + 1]);
317 }
318 }
319 triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::FACE_MARK) !=
320 0);
321 triangleFaceEdgeMarks.push_back(
322 (iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
323 triangleFaceEdgeMarks.push_back(
324 (iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
325 triangleFaceEdgeMarks.push_back(
326 (iFaceEdgeMarks[nTriangle / 3] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
327 if (mindices) {
328 currentShape->MakeFace(triangleVertices,
329 triangleNormals,
330 triangleTexCoords,
331 triangleFaceEdgeMarks,
332 mindices[nTriangle / 3]);
333 }
334 else {
335 currentShape->MakeFace(
336 triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
337 }
338 nDoneVertices++; // with a strip, each triangle is one vertex more
339 nTriangle++;
340 }
341}
342
343void WingedEdgeBuilder::buildTriangleFan(const float * /*vertices*/,
344 const float * /*normals*/,
345 vector<FrsMaterial> & /*iMaterials*/,
346 const float * /*texCoords*/,
347 const IndexedFaceSet::FaceEdgeMark * /*iFaceEdgeMarks*/,
348 const uint * /*vindices*/,
349 const uint * /*nindices*/,
350 const uint * /*mindices*/,
351 const uint * /*tindices*/,
352 const uint /*nvertices*/)
353{
354 // Nothing to be done
355}
356
357void WingedEdgeBuilder::buildTriangles(const float * /*vertices*/,
358 const float *normals,
359 vector<FrsMaterial> & /*iMaterials*/,
360 const float *texCoords,
361 const IndexedFaceSet::FaceEdgeMark *iFaceEdgeMarks,
362 const uint *vindices,
363 const uint *nindices,
364 const uint *mindices,
365 const uint *tindices,
366 const uint nvertices)
367{
368 WShape *currentShape = _current_wshape; // the current shape begin built
369 vector<WVertex *> triangleVertices;
370 vector<Vec3f> triangleNormals;
371 vector<Vec2f> triangleTexCoords;
372 vector<bool> triangleFaceEdgeMarks;
373
374 // Each triplet of vertices is considered as an independent triangle
375 for (uint i = 0; i < nvertices / 3; i++) {
376 triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i] / 3]);
377 triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 1] / 3]);
378 triangleVertices.push_back(currentShape->getVertexList()[vindices[3 * i + 2] / 3]);
379
380 triangleNormals.emplace_back(
381 normals[nindices[3 * i]], normals[nindices[3 * i] + 1], normals[nindices[3 * i] + 2]);
382 triangleNormals.emplace_back(normals[nindices[3 * i + 1]],
383 normals[nindices[3 * i + 1] + 1],
384 normals[nindices[3 * i + 1] + 2]);
385 triangleNormals.emplace_back(normals[nindices[3 * i + 2]],
386 normals[nindices[3 * i + 2] + 1],
387 normals[nindices[3 * i + 2] + 2]);
388
389 if (texCoords) {
390 triangleTexCoords.emplace_back(texCoords[tindices[3 * i]], texCoords[tindices[3 * i] + 1]);
391 triangleTexCoords.emplace_back(texCoords[tindices[3 * i + 1]],
392 texCoords[tindices[3 * i + 1] + 1]);
393 triangleTexCoords.emplace_back(texCoords[tindices[3 * i + 2]],
394 texCoords[tindices[3 * i + 2] + 1]);
395 }
396
397 triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::FACE_MARK) != 0);
398 triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V1V2) != 0);
399 triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V2V3) != 0);
400 triangleFaceEdgeMarks.push_back((iFaceEdgeMarks[i] & IndexedFaceSet::EDGE_MARK_V3V1) != 0);
401 }
402 if (mindices) {
403 currentShape->MakeFace(
404 triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, mindices[0]);
405 }
406 else {
407 currentShape->MakeFace(
408 triangleVertices, triangleNormals, triangleTexCoords, triangleFaceEdgeMarks, 0);
409 }
410}
411
412void WingedEdgeBuilder::transformVertices(const float *vertices,
413 uint vsize,
414 const Matrix44r &transform,
415 float *res)
416{
417 const float *v = vertices;
418 float *pv = res;
419
420 for (uint i = 0; i < vsize / 3; i++) {
421 HVec3r hv_tmp(v[0], v[1], v[2]);
422 HVec3r hv(transform * hv_tmp);
423 for (uint j = 0; j < 3; j++) {
424 pv[j] = hv[j] / hv[3];
425 }
426 v += 3;
427 pv += 3;
428 }
429}
430
431void WingedEdgeBuilder::transformNormals(const float *normals,
432 uint nsize,
433 const Matrix44r &transform,
434 float *res)
435{
436 const float *n = normals;
437 float *pn = res;
438
439 for (uint i = 0; i < nsize / 3; i++) {
440 Vec3r hn(n[0], n[1], n[2]);
441 hn = GeomUtils::rotateVector(transform, hn);
442 for (uint j = 0; j < 3; j++) {
443 pn[j] = hn[j];
444 }
445 n += 3;
446 pn += 3;
447 }
448}
449
450} /* namespace Freestyle */
unsigned int uint
Various tools for geometry.
Class to build a shape node. It contains a Rep, which is the shape geometry.
Class to render a WingedEdge data structure from a polyhedral data structure organized in nodes of a ...
ATTR_WARN_UNUSED_RESULT const BMVert * v
static const FaceEdgeMark EDGE_MARK_V2V3
virtual const uint vsize() const
virtual const FrsMaterial *const * frs_materials() const
virtual const float * vertices() const
static const FaceEdgeMark EDGE_MARK_V1V2
virtual const uint * tindices() const
virtual const uchar * faceEdgeMarks() const
virtual const TRIANGLES_STYLE * trianglesStyle() const
virtual const uint * mindices() const
virtual const uint numFaces() const
virtual const float * texCoords() const
virtual const float * normals() const
virtual const uint msize() const
virtual const uint nsize() const
virtual const uint * numVertexPerFaces() const
virtual const uint * nindices() const
virtual const uint * vindices() const
virtual const uint tsize() const
static const FaceEdgeMark FACE_MARK
static const FaceEdgeMark EDGE_MARK_V3V1
const FrsMaterial * frs_material() const
Definition Rep.h:131
vector< WVertex * > & getVertexList()
Definition WEdge.h:1053
virtual WFace * MakeFace(vector< WVertex * > &iVertexList, vector< bool > &iFaceEdgeMarksList, uint iMaterialIndex)
Definition WEdge.cpp:590
virtual void visitNodeTransformAfter(NodeTransform &)
virtual bool buildWShape(WShape &shape, IndexedFaceSet &ifs)
virtual void buildWVertices(WShape &shape, const float *vertices, uint vsize)
void addWShape(WShape *wshape)
Definition WEdge.h:1321
static float normals[][3]
Vec3r rotateVector(const Matrix44r &mat, const Vec3r &v)
VecMat::Vec3< float > Vec3f
Definition Geom.h:28
VecMat::SquareMatrix< real, 4 > Matrix44r
Definition Geom.h:54
VecMat::HVec3< real > HVec3r
Definition Geom.h:36
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
inherits from class Rep
Definition AppCanvas.cpp:20