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