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
10
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{
27 if (_pRenderMonitor && _pRenderMonitor->testBreak()) {
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]);
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.
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a vector
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
SIMD_FORCE_INLINE btVector3 transform(const btVector3 &point) const
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
Vec3f & GetVertexNormal(int index)
Definition WEdge.h:826
void setFrsMaterials(const vector< FrsMaterial > &iMaterials)
Definition WEdge.h:1142
vector< WVertex * > & getVertexList()
Definition WEdge.h:1053
real ComputeMeanEdgeSize() const
Definition WEdge.cpp:714
void setFrsMaterial(const FrsMaterial &frs_material, uint i)
Definition WEdge.h:1137
virtual WFace * MakeFace(vector< WVertex * > &iVertexList, vector< bool > &iFaceEdgeMarksList, uint iMaterialIndex)
Definition WEdge.cpp:590
void AddVertex(WVertex *iVertex)
Definition WEdge.h:1203
vector< WFace * > & GetFaceList()
Definition WEdge.h:1058
void setId(int id)
Definition WEdge.h:111
virtual void visitNodeTransformAfter(NodeTransform &)
virtual bool buildWShape(WShape &shape, IndexedFaceSet &ifs)
virtual void buildWVertices(WShape &shape, const float *vertices, uint vsize)
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