Blender  V3.3
ViewEdgeXBuilder.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 #include <list>
9 
10 #include "SilhouetteGeomEngine.h"
11 #include "ViewEdgeXBuilder.h"
12 #include "ViewMap.h"
13 
14 #include "../winged_edge/WXEdge.h"
15 
16 using namespace std;
17 
18 namespace Freestyle {
19 
20 void ViewEdgeXBuilder::Init(ViewShape *oVShape)
21 {
22  if (nullptr == oVShape) {
23  return;
24  }
25 
26  // for design convenience, we store the current SShape.
27  _pCurrentSShape = oVShape->sshape();
28  if (nullptr == _pCurrentSShape) {
29  return;
30  }
31 
32  _pCurrentVShape = oVShape;
33 
34  // Reset previous data
35  //--------------------
36  if (!_SVertexMap.empty()) {
37  _SVertexMap.clear();
38  }
39 }
40 
41 void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape,
42  ViewShape *oVShape,
43  vector<ViewEdge *> &ioVEdges,
44  vector<ViewVertex *> &ioVVertices,
45  vector<FEdge *> &ioFEdges,
46  vector<SVertex *> &ioSVertices)
47 {
48  // Reinit structures
49  Init(oVShape);
50 
51  /* ViewEdge *vedge; */ /* UNUSED */
52  // Let us build the smooth stuff
53  //----------------------------------------
54  // We parse all faces to find the ones that contain smooth edges
55  vector<WFace *> &wfaces = iWShape->GetFaceList();
56  vector<WFace *>::iterator wf, wfend;
57  WXFace *wxf;
58  for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) {
59  wxf = dynamic_cast<WXFace *>(*wf);
60  if (false == ((wxf))->hasSmoothEdges()) { // does it contain at least one smooth edge ?
61  continue;
62  }
63  // parse all smooth layers:
64  vector<WXFaceLayer *> &smoothLayers = wxf->getSmoothLayers();
65  for (vector<WXFaceLayer *>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end();
66  sl != slend;
67  ++sl) {
68  if (!(*sl)->hasSmoothEdge()) {
69  continue;
70  }
71  if (stopSmoothViewEdge((*sl))) { // has it been parsed already ?
72  continue;
73  }
74  // here we know that we're dealing with a face layer that has not been processed yet and that
75  // contains a smooth edge.
76  /* vedge =*//* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
77  }
78  }
79 
80  // Now let's build sharp view edges:
81  //----------------------------------
82  // Reset all userdata for WXEdge structure
83  //----------------------------------------
84  // iWShape->ResetUserData();
85 
86  WXEdge *wxe;
87  vector<WEdge *> &wedges = iWShape->getEdgeList();
88  //------------------------------
89  for (vector<WEdge *>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) {
90  wxe = dynamic_cast<WXEdge *>(*we);
91  if (Nature::NO_FEATURE == wxe->nature()) {
92  continue;
93  }
94 
95  if (!stopSharpViewEdge(wxe)) {
96  bool b = true;
97  if (wxe->order() == -1) {
98  b = false;
99  }
100  BuildSharpViewEdge(OWXEdge(wxe, b));
101  }
102  }
103 
104  // Reset all userdata for WXEdge structure
105  //----------------------------------------
106  iWShape->ResetUserData();
107 
108  // Add all these new edges to the scene's feature edges list:
109  //-----------------------------------------------------------
110  vector<FEdge *> &newedges = _pCurrentSShape->getEdgeList();
111  vector<SVertex *> &newVertices = _pCurrentSShape->getVertexList();
112  vector<ViewVertex *> &newVVertices = _pCurrentVShape->vertices();
113  vector<ViewEdge *> &newVEdges = _pCurrentVShape->edges();
114 
115  // inserts in ioFEdges, at its end, all the edges of newedges
116  ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
117  ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
118  ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
119  ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
120 }
121 
122 ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer &iFaceLayer)
123 {
124  // Find first edge:
125  OWXFaceLayer first = iFaceLayer;
126  OWXFaceLayer currentFace = first;
127 
128  // bidirectional chaining.
129  // first direction
130  list<OWXFaceLayer> facesChain;
131  unsigned size = 0;
132  while (!stopSmoothViewEdge(currentFace.fl)) {
133  facesChain.push_back(currentFace);
134  ++size;
135  currentFace.fl->userdata = (void *)1; // processed
136  // Find the next edge!
137  currentFace = FindNextFaceLayer(currentFace);
138  }
139  OWXFaceLayer end = facesChain.back();
140  // second direction
141  currentFace = FindPreviousFaceLayer(first);
142  while (!stopSmoothViewEdge(currentFace.fl)) {
143  facesChain.push_front(currentFace);
144  ++size;
145  currentFace.fl->userdata = (void *)1; // processed
146  // Find the previous edge!
147  currentFace = FindPreviousFaceLayer(currentFace);
148  }
149  first = facesChain.front();
150 
151  if (iFaceLayer.fl->nature() & Nature::RIDGE) {
152  if (size < 4) {
153  return nullptr;
154  }
155  }
156 
157  // Start a new chain edges
158  ViewEdge *newVEdge = new ViewEdge;
159  newVEdge->setId(_currentViewId);
160  ++_currentViewId;
161 
162  _pCurrentVShape->AddEdge(newVEdge);
163 
164  // build FEdges
165  FEdge *feprevious = nullptr;
166  FEdge *fefirst = nullptr;
167  FEdge *fe = nullptr;
168  for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend;
169  ++fl) {
170  fe = BuildSmoothFEdge(feprevious, (*fl));
171  if (feprevious && fe == feprevious) {
172  continue;
173  }
174  fe->setViewEdge(newVEdge);
175  if (!fefirst) {
176  fefirst = fe;
177  }
178  feprevious = fe;
179  }
180  // Store the chain starting edge:
181  _pCurrentSShape->AddChain(fefirst);
182  newVEdge->setNature(iFaceLayer.fl->nature());
183  newVEdge->setFEdgeA(fefirst);
184  newVEdge->setFEdgeB(fe);
185 
186  // is it a closed loop ?
187  if ((first == end) && (size != 1)) {
188  fefirst->setPreviousEdge(fe);
189  fe->setNextEdge(fefirst);
190  newVEdge->setA(nullptr);
191  newVEdge->setB(nullptr);
192  }
193  else {
194  ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
195  ViewVertex *vvb = MakeViewVertex(fe->vertexB());
196 
197  ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
198  ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
199 
200  newVEdge->setA(vva);
201  newVEdge->setB(vvb);
202  }
203 
204  return newVEdge;
205 }
206 
207 ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge &iWEdge)
208 {
209  // Start a new sharp chain edges
210  ViewEdge *newVEdge = new ViewEdge;
211  newVEdge->setId(_currentViewId);
212  ++_currentViewId;
213  unsigned size = 0;
214 
215  _pCurrentVShape->AddEdge(newVEdge);
216 
217  // Find first edge:
218  OWXEdge firstWEdge = iWEdge;
219  /* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */
220  OWXEdge currentWEdge = firstWEdge;
221  list<OWXEdge> edgesChain;
222 #if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */
223  // bidirectional chaining
224  // first direction:
225  while (!stopSharpViewEdge(currentWEdge.e)) {
226  edgesChain.push_back(currentWEdge);
227  ++size;
228  currentWEdge.e->userdata = (void *)1; // processed
229  // Find the next edge!
230  currentWEdge = FindNextWEdge(currentWEdge);
231  }
232  OWXEdge endWEdge = edgesChain.back();
233  // second direction
234  currentWEdge = FindPreviousWEdge(firstWEdge);
235  while (!stopSharpViewEdge(currentWEdge.e)) {
236  edgesChain.push_front(currentWEdge);
237  ++size;
238  currentWEdge.e->userdata = (void *)1; // processed
239  // Find the previous edge!
240  currentWEdge = FindPreviousWEdge(currentWEdge);
241  }
242 #else
243  edgesChain.push_back(currentWEdge);
244  ++size;
245  currentWEdge.e->userdata = (void *)1; // processed
246  OWXEdge endWEdge = edgesChain.back();
247 #endif
248  firstWEdge = edgesChain.front();
249 
250  // build FEdges
251  FEdge *feprevious = nullptr;
252  FEdge *fefirst = nullptr;
253  FEdge *fe = nullptr;
254  for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend;
255  ++we) {
256  fe = BuildSharpFEdge(feprevious, (*we));
257  fe->setViewEdge(newVEdge);
258  if (!fefirst) {
259  fefirst = fe;
260  }
261  feprevious = fe;
262  }
263  // Store the chain starting edge:
264  _pCurrentSShape->AddChain(fefirst);
265  newVEdge->setNature(iWEdge.e->nature());
266  newVEdge->setFEdgeA(fefirst);
267  newVEdge->setFEdgeB(fe);
268 
269  // is it a closed loop ?
270  if ((firstWEdge == endWEdge) && (size != 1)) {
271  fefirst->setPreviousEdge(fe);
272  fe->setNextEdge(fefirst);
273  newVEdge->setA(nullptr);
274  newVEdge->setB(nullptr);
275  }
276  else {
277  ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
278  ViewVertex *vvb = MakeViewVertex(fe->vertexB());
279 
280  ((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
281  ((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
282 
283  newVEdge->setA(vva);
284  newVEdge->setB(vvb);
285  }
286 
287  return newVEdge;
288 }
289 
290 OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer &iFaceLayer)
291 {
292  WXFace *nextFace = nullptr;
293  WOEdge *woeend;
294  real tend;
295  if (iFaceLayer.order) {
296  woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
297  tend = iFaceLayer.fl->getSmoothEdge()->tb();
298  }
299  else {
300  woeend = iFaceLayer.fl->getSmoothEdge()->woea();
301  tend = iFaceLayer.fl->getSmoothEdge()->ta();
302  }
303  // special case of EDGE_VERTEX config:
304  if (ELEM(tend, 0.0, 1.0)) {
305  WVertex *nextVertex;
306  if (tend == 0.0) {
307  nextVertex = woeend->GetaVertex();
308  }
309  else {
310  nextVertex = woeend->GetbVertex();
311  }
312  if (nextVertex->isBoundary()) { // if it's a non-manifold vertex -> ignore
313  return OWXFaceLayer(nullptr, true);
314  }
315  bool found = false;
316  WVertex::face_iterator f = nextVertex->faces_begin();
317  WVertex::face_iterator fend = nextVertex->faces_end();
318  while ((!found) && (f != fend)) {
319  nextFace = dynamic_cast<WXFace *>(*f);
320  if ((nullptr != nextFace) && (nextFace != iFaceLayer.fl->getFace())) {
321  vector<WXFaceLayer *> sameNatureLayers;
322  nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
323  // don't know... Maybe should test whether this face has also a vertex_edge configuration.
324  if (sameNatureLayers.size() == 1) {
325  WXFaceLayer *winner = sameNatureLayers[0];
326  // check face mark continuity
327  if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
328  return OWXFaceLayer(nullptr, true);
329  }
330  if (woeend == winner->getSmoothEdge()->woea()->twin()) {
331  return OWXFaceLayer(winner, true);
332  }
333 
334  return OWXFaceLayer(winner, false);
335  }
336  }
337  ++f;
338  }
339  }
340  else {
341  nextFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
342  if (!nextFace) {
343  return OWXFaceLayer(nullptr, true);
344  }
345  // if the next face layer has either no smooth edge or no smooth edge of same nature, no next
346  // face
347  if (!nextFace->hasSmoothEdges()) {
348  return OWXFaceLayer(nullptr, true);
349  }
350  vector<WXFaceLayer *> sameNatureLayers;
351  nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
352  // don't know how to deal with several edges of same nature on a single face
353  if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
354  return OWXFaceLayer(nullptr, true);
355  }
356 
357  WXFaceLayer *winner = sameNatureLayers[0];
358  // check face mark continuity
359  if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
360  return OWXFaceLayer(nullptr, true);
361  }
362  if (woeend == winner->getSmoothEdge()->woea()->twin()) {
363  return OWXFaceLayer(winner, true);
364  }
365 
366  return OWXFaceLayer(winner, false);
367  }
368  return OWXFaceLayer(nullptr, true);
369 }
370 
371 OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer &iFaceLayer)
372 {
373  WXFace *previousFace = nullptr;
374  WOEdge *woebegin;
375  real tend;
376  if (iFaceLayer.order) {
377  woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
378  tend = iFaceLayer.fl->getSmoothEdge()->ta();
379  }
380  else {
381  woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
382  tend = iFaceLayer.fl->getSmoothEdge()->tb();
383  }
384 
385  // special case of EDGE_VERTEX config:
386  if (ELEM(tend, 0.0, 1.0)) {
387  WVertex *previousVertex;
388  if (tend == 0.0) {
389  previousVertex = woebegin->GetaVertex();
390  }
391  else {
392  previousVertex = woebegin->GetbVertex();
393  }
394  if (previousVertex->isBoundary()) { // if it's a non-manifold vertex -> ignore
395  return OWXFaceLayer(nullptr, true);
396  }
397  bool found = false;
398  WVertex::face_iterator f = previousVertex->faces_begin();
399  WVertex::face_iterator fend = previousVertex->faces_end();
400  for (; (!found) && (f != fend); ++f) {
401  previousFace = dynamic_cast<WXFace *>(*f);
402  if ((nullptr != previousFace) && (previousFace != iFaceLayer.fl->getFace())) {
403  vector<WXFaceLayer *> sameNatureLayers;
404  previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
405  // don't know... Maybe should test whether this face has also a vertex_edge configuration
406  if (sameNatureLayers.size() == 1) {
407  WXFaceLayer *winner = sameNatureLayers[0];
408  // check face mark continuity
409  if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
410  return OWXFaceLayer(nullptr, true);
411  }
412  if (woebegin == winner->getSmoothEdge()->woeb()->twin()) {
413  return OWXFaceLayer(winner, true);
414  }
415 
416  return OWXFaceLayer(winner, false);
417  }
418  }
419  }
420  }
421  else {
422  previousFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
423  if (nullptr == previousFace) {
424  return OWXFaceLayer(nullptr, true);
425  }
426  // if the next face layer has either no smooth edge or no smooth edge of same nature, no next
427  // face
428  if (!previousFace->hasSmoothEdges()) {
429  return OWXFaceLayer(nullptr, true);
430  }
431  vector<WXFaceLayer *> sameNatureLayers;
432  previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
433  // don't know how to deal with several edges of same nature on a single face
434  if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
435  return OWXFaceLayer(nullptr, true);
436  }
437 
438  WXFaceLayer *winner = sameNatureLayers[0];
439  // check face mark continuity
440  if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
441  return OWXFaceLayer(nullptr, true);
442  }
443  if (woebegin == winner->getSmoothEdge()->woeb()->twin()) {
444  return OWXFaceLayer(winner, true);
445  }
446 
447  return OWXFaceLayer(winner, false);
448  }
449  return OWXFaceLayer(nullptr, true);
450 }
451 
452 FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer &ifl)
453 {
454  WOEdge *woea, *woeb;
455  real ta, tb;
456  SVertex *va, *vb;
457  FEdgeSmooth *fe;
458  // retrieve exact silhouette data
459  WXSmoothEdge *se = ifl.fl->getSmoothEdge();
460 
461  if (ifl.order) {
462  woea = se->woea();
463  woeb = se->woeb();
464  ta = se->ta();
465  tb = se->tb();
466  }
467  else {
468  woea = se->woeb();
469  woeb = se->woea();
470  ta = se->tb();
471  tb = se->ta();
472  }
473 
474  Vec3r normal;
475  // Make the 2 Svertices
476  if (feprevious ==
477  nullptr) { // that means that we don't have any vertex already built for that face
478  Vec3r A1(woea->GetaVertex()->GetVertex());
479  Vec3r A2(woea->GetbVertex()->GetVertex());
480  Vec3r A(A1 + ta * (A2 - A1));
481 
482  va = MakeSVertex(A, false);
483  // Set normal:
484  Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
485  Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
486  Vec3r na((1 - ta) * NA1 + ta * NA2);
487  na.normalize();
488  va->AddNormal(na);
489  normal = na;
490 
491  // Set CurvatureInfo
492  CurvatureInfo *curvature_info_a = new CurvatureInfo(
493  *(dynamic_cast<WXVertex *>(woea->GetaVertex())->curvatures()),
494  *(dynamic_cast<WXVertex *>(woea->GetbVertex())->curvatures()),
495  ta);
496  va->setCurvatureInfo(curvature_info_a);
497  }
498  else {
499  va = feprevious->vertexB();
500  }
501 
502  Vec3r B1(woeb->GetaVertex()->GetVertex());
503  Vec3r B2(woeb->GetbVertex()->GetVertex());
504  Vec3r B(B1 + tb * (B2 - B1));
505 
506  if (feprevious && (B - va->point3D()).norm() < 1.0e-6) {
507  return feprevious;
508  }
509 
510  vb = MakeSVertex(B, false);
511  // Set normal:
512  Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
513  Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
514  Vec3r nb((1 - tb) * NB1 + tb * NB2);
515  nb.normalize();
516  normal += nb;
517  vb->AddNormal(nb);
518 
519  // Set CurvatureInfo
520  CurvatureInfo *curvature_info_b = new CurvatureInfo(
521  *(dynamic_cast<WXVertex *>(woeb->GetaVertex())->curvatures()),
522  *(dynamic_cast<WXVertex *>(woeb->GetbVertex())->curvatures()),
523  tb);
524  vb->setCurvatureInfo(curvature_info_b);
525 
526  // Creates the corresponding feature edge
527  fe = new FEdgeSmooth(va, vb);
528  fe->setNature(ifl.fl->nature());
529  fe->setId(_currentFId);
531  fe->setFace(ifl.fl->getFace());
532  fe->setFaceMark(ifl.fl->getFace()->GetMark());
533  if (feprevious == nullptr) {
534  normal.normalize();
535  }
536  fe->setNormal(normal);
537  fe->setPreviousEdge(feprevious);
538  if (feprevious) {
539  feprevious->setNextEdge(fe);
540  }
541  _pCurrentSShape->AddEdge(fe);
542  va->AddFEdge(fe);
543  vb->AddFEdge(fe);
544 
545  ++_currentFId;
546  ifl.fl->userdata = fe;
547  return fe;
548 }
549 
550 bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer)
551 {
552  if (nullptr == iFaceLayer) {
553  return true;
554  }
555  if (iFaceLayer->userdata == nullptr) {
556  return false;
557  }
558  return true;
559 }
560 
561 int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge)
562 {
563  WFace *aFace = iEdge->GetaFace();
564  WFace *bFace = iEdge->GetbFace();
565  int result = 0;
566  if (aFace && aFace->GetMark()) {
567  result += 1;
568  }
569  if (bFace && bFace->GetMark()) {
570  result += 2;
571  }
572  return result;
573 }
574 
575 OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge &iEdge)
576 {
577  if (Nature::NO_FEATURE == iEdge.e->nature()) {
578  return OWXEdge(nullptr, true);
579  }
580 
581  WVertex *v;
582  if (true == iEdge.order) {
583  v = iEdge.e->GetbVertex();
584  }
585  else {
586  v = iEdge.e->GetaVertex();
587  }
588 
589  if (((WXVertex *)v)->isFeature()) {
590  return nullptr; /* XXX eeek? NULL? OWXEdge(NULL, true/false)? */
591  }
592 
593  int faceMarks = retrieveFaceMarks(iEdge.e);
594  vector<WEdge *> &vEdges = (v)->GetEdges();
595  for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
596  WXEdge *wxe = dynamic_cast<WXEdge *>(*ve);
597  if (wxe == iEdge.e) {
598  continue; // same edge as the one processed
599  }
600 
601  if (wxe->nature() != iEdge.e->nature()) {
602  continue;
603  }
604 
605  // check face mark continuity
606  if (retrieveFaceMarks(wxe) != faceMarks) {
607  continue;
608  }
609 
610  if (wxe->GetaVertex() == v) {
611  // That means that the face necessarily lies on the edge left.
612  // So the vertex order is OK.
613  return OWXEdge(wxe, true);
614  }
615 
616  // That means that the face necessarily lies on the edge left.
617  // So the vertex order is OK.
618  return OWXEdge(wxe, false);
619  }
620  // we did not find:
621  return OWXEdge(nullptr, true);
622 }
623 
624 OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge &iEdge)
625 {
626  if (Nature::NO_FEATURE == iEdge.e->nature()) {
627  return OWXEdge(nullptr, true);
628  }
629 
630  WVertex *v;
631  if (true == iEdge.order) {
632  v = iEdge.e->GetaVertex();
633  }
634  else {
635  v = iEdge.e->GetbVertex();
636  }
637 
638  if (((WXVertex *)v)->isFeature()) {
639  return nullptr;
640  }
641 
642  int faceMarks = retrieveFaceMarks(iEdge.e);
643  vector<WEdge *> &vEdges = (v)->GetEdges();
644  for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
645  WXEdge *wxe = dynamic_cast<WXEdge *>(*ve);
646  if (wxe == iEdge.e) {
647  continue; // same edge as the one processed
648  }
649 
650  if (wxe->nature() != iEdge.e->nature()) {
651  continue;
652  }
653 
654  // check face mark continuity
655  if (retrieveFaceMarks(wxe) != faceMarks) {
656  continue;
657  }
658 
659  if (wxe->GetbVertex() == v) {
660  return OWXEdge(wxe, true);
661  }
662 
663  return OWXEdge(wxe, false);
664  }
665  // we did not find:
666  return OWXEdge(nullptr, true);
667 }
668 
669 FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge &iwe)
670 {
671  SVertex *va, *vb;
672  FEdgeSharp *fe;
673  Vec3r vA, vB;
674  if (iwe.order) {
675  vA = iwe.e->GetaVertex()->GetVertex();
676  vB = iwe.e->GetbVertex()->GetVertex();
677  }
678  else {
679  vA = iwe.e->GetbVertex()->GetVertex();
680  vB = iwe.e->GetaVertex()->GetVertex();
681  }
682  // Make the 2 SVertex
683  va = MakeSVertex(vA, true);
684  vb = MakeSVertex(vB, true);
685 
686  // get the faces normals and the material indices
687  Vec3r normalA, normalB;
688  unsigned matA(0), matB(0);
689  bool faceMarkA = false, faceMarkB = false;
690  if (iwe.order) {
691  normalB = (iwe.e->GetbFace()->GetNormal());
692  matB = (iwe.e->GetbFace()->frs_materialIndex());
693  faceMarkB = (iwe.e->GetbFace()->GetMark());
694  if (!(iwe.e->nature() & Nature::BORDER)) {
695  normalA = (iwe.e->GetaFace()->GetNormal());
696  matA = (iwe.e->GetaFace()->frs_materialIndex());
697  faceMarkA = (iwe.e->GetaFace()->GetMark());
698  }
699  }
700  else {
701  normalA = (iwe.e->GetbFace()->GetNormal());
702  matA = (iwe.e->GetbFace()->frs_materialIndex());
703  faceMarkA = (iwe.e->GetbFace()->GetMark());
704  if (!(iwe.e->nature() & Nature::BORDER)) {
705  normalB = (iwe.e->GetaFace()->GetNormal());
706  matB = (iwe.e->GetaFace()->frs_materialIndex());
707  faceMarkB = (iwe.e->GetaFace()->GetMark());
708  }
709  }
710  // Creates the corresponding feature edge
711  fe = new FEdgeSharp(va, vb);
712  fe->setNature(iwe.e->nature());
713  fe->setId(_currentFId);
714  fe->setaFrsMaterialIndex(matA);
715  fe->setbFrsMaterialIndex(matB);
716  fe->setaFaceMark(faceMarkA);
717  fe->setbFaceMark(faceMarkB);
718  fe->setNormalA(normalA);
719  fe->setNormalB(normalB);
720  fe->setPreviousEdge(feprevious);
721  if (feprevious) {
722  feprevious->setNextEdge(fe);
723  }
724  _pCurrentSShape->AddEdge(fe);
725  va->AddFEdge(fe);
726  vb->AddFEdge(fe);
727  // Add normals:
728  va->AddNormal(normalA);
729  va->AddNormal(normalB);
730  vb->AddNormal(normalA);
731  vb->AddNormal(normalB);
732 
733  ++_currentFId;
734  iwe.e->userdata = fe;
735  return fe;
736 }
737 
738 bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge)
739 {
740  if (nullptr == iEdge) {
741  return true;
742  }
743  if (iEdge->userdata == nullptr) {
744  return false;
745  }
746  return true;
747 }
748 
749 SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint)
750 {
751  SVertex *va = new SVertex(iPoint, _currentSVertexId);
752  SilhouetteGeomEngine::ProjectSilhouette(va);
753  ++_currentSVertexId;
754  // Add the svertex to the SShape svertex list:
755  _pCurrentSShape->AddNewVertex(va);
756  return va;
757 }
758 
759 SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint, bool shared)
760 {
761  SVertex *va;
762  if (!shared) {
763  va = MakeSVertex(iPoint);
764  }
765  else {
766  // Check whether the iPoint is already in the table
767  SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
768  if (shared && found != _SVertexMap.end()) {
769  va = (*found).second;
770  }
771  else {
772  va = MakeSVertex(iPoint);
773  // Add the svertex into the table using iPoint as the key
774  _SVertexMap[iPoint] = va;
775  }
776  }
777  return va;
778 }
779 
780 ViewVertex *ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex)
781 {
782  ViewVertex *vva = iSVertex->viewvertex();
783  if (vva) {
784  return vva;
785  }
786  vva = new NonTVertex(iSVertex);
787  // Add the view vertex to the ViewShape svertex list:
788  _pCurrentVShape->AddVertex(vva);
789  return vva;
790 }
791 
792 } /* namespace Freestyle */
#define ELEM(...)
#define A2
Definition: RandGen.cpp:24
#define A1
Definition: RandGen.cpp:23
Class to perform all geometric operations dedicated to silhouette. That, for example,...
Class to build view edges and the underlying chains of feature edges...
Classes to define a View Map (ViewVertex, ViewEdge, etc.)
ATTR_WARN_UNUSED_RESULT const BMVert * v
#define A
static DBVT_INLINE btScalar size(const btDbvtVolume &a)
Definition: btDbvt.cpp:52
void setbFrsMaterialIndex(unsigned i)
Definition: Silhouette.h:1255
void setaFaceMark(bool iFaceMark)
Definition: Silhouette.h:1261
void setNormalB(const Vec3r &iNormal)
Definition: Silhouette.h:1243
void setaFrsMaterialIndex(unsigned i)
Definition: Silhouette.h:1249
void setbFaceMark(bool iFaceMark)
Definition: Silhouette.h:1267
void setNormalA(const Vec3r &iNormal)
Definition: Silhouette.h:1237
void setNormal(const Vec3r &iNormal)
Definition: Silhouette.h:1378
void setFaceMark(bool iFaceMark)
Definition: Silhouette.h:1372
void setFrsMaterialIndex(unsigned i)
Definition: Silhouette.h:1384
void setFace(void *iFace)
Definition: Silhouette.h:1366
void setId(const Id &id)
Definition: Silhouette.h:735
SVertex * vertexA()
Definition: Silhouette.h:597
void setViewEdge(ViewEdge *iViewEdge)
Definition: Silhouette.h:766
void setNextEdge(FEdge *iEdge)
Definition: Silhouette.h:741
SVertex * vertexB()
Definition: Silhouette.h:603
void setNature(Nature::EdgeNature iNature)
Definition: Silhouette.h:753
void setPreviousEdge(FEdge *iEdge)
Definition: Silhouette.h:747
ViewVertex * viewvertex()
Definition: Silhouette.h:276
void setCurvatureInfo(CurvatureInfo *ci)
Definition: Silhouette.h:301
void AddNormal(const Vec3r &iNormal)
Definition: Silhouette.h:296
const Vec3r & point3D() const
Definition: Silhouette.h:223
void AddFEdge(FEdge *iFEdge)
Definition: Silhouette.h:359
Vec< T, N > & normalize()
Definition: VecMat.h:105
void setId(const Id &id)
Definition: ViewMap.h:1182
void setFEdgeB(FEdge *iFEdge)
Definition: ViewMap.h:1170
void setA(ViewVertex *iA)
Definition: ViewMap.h:1146
void setFEdgeA(FEdge *iFEdge)
Definition: ViewMap.h:1164
void setNature(Nature::EdgeNature iNature)
Definition: ViewMap.h:1158
void setB(ViewVertex *iB)
Definition: ViewMap.h:1152
SShape * sshape()
Definition: ViewMap.h:1539
WFace * GetaFace()
Definition: WEdge.h:611
WVertex * GetbVertex()
Definition: WEdge.h:606
void * userdata
Definition: WEdge.h:509
WFace * GetbFace()
Definition: WEdge.h:616
WVertex * GetaVertex()
Definition: WEdge.h:601
unsigned frs_materialIndex() const
Definition: WEdge.h:738
Vec3f & GetVertexNormal(int index)
Definition: WEdge.h:825
bool GetMark() const
Definition: WEdge.h:743
Vec3f & GetNormal()
Definition: WEdge.h:728
WFace * GetBordingFace(int index)
Definition: WEdge.h:799
WVertex * GetaVertex()
Definition: WEdge.h:387
WOEdge * twin()
Definition: WEdge.cpp:197
WVertex * GetbVertex()
Definition: WEdge.h:392
vector< WEdge * > & getEdgeList()
Definition: WEdge.h:1045
vector< WFace * > & GetFaceList()
Definition: WEdge.h:1055
void ResetUserData()
Definition: WEdge.h:1206
bool isBoundary()
Definition: WEdge.cpp:98
Vec3f & GetVertex()
Definition: WEdge.h:73
virtual face_iterator faces_end()
Definition: WEdge.h:301
virtual face_iterator faces_begin()
Definition: WEdge.h:296
short order() const
Definition: WXEdge.h:159
WXNature nature()
Definition: WXEdge.h:149
WXNature nature() const
Definition: WXEdge.h:384
WXFace * getFace()
Definition: WXEdge.h:397
WXSmoothEdge * getSmoothEdge()
Definition: WXEdge.h:402
vector< WXFaceLayer * > & getSmoothLayers()
Definition: WXEdge.h:574
void retrieveSmoothEdgesLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothEdgesLayers)
Definition: WXEdge.h:591
bool hasSmoothEdges() const
Definition: WXEdge.h:561
float ta() const
Definition: WXEdge.h:247
float tb() const
Definition: WXEdge.h:252
CurvatureInfo * curvatures()
Definition: WXEdge.h:74
IconTextureDrawCall normal
#define B
static const EdgeNature NO_FEATURE
Definition: Nature.h:34
static const EdgeNature BORDER
Definition: Nature.h:38
static const EdgeNature RIDGE
Definition: Nature.h:42
inherits from class Rep
Definition: AppCanvas.cpp:18
static double B1(double u)
Definition: FitCurve.cpp:304
static double B2(double u)
Definition: FitCurve.cpp:310
double real
Definition: Precision.h:12
static const pxr::TfToken b("b", pxr::TfToken::Immortal)