Blender  V3.3
WXEdge.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 #include "WXEdge.h"
9 #include "BKE_global.h"
10 
11 namespace Freestyle {
12 
13 /**********************************
14  * *
15  * *
16  * WXFace *
17  * *
18  * *
19  **********************************/
20 
21 unsigned int WXFaceLayer::Get0VertexIndex() const
22 {
23  int i = 0;
24  int nEdges = _pWXFace->numberOfEdges();
25  for (i = 0; i < nEdges; ++i) {
26  if (_DotP[i] == 0.0f) { // TODO: this comparison is weak, check if it actually works
27  return i;
28  }
29  }
30  return -1;
31 }
32 unsigned int WXFaceLayer::GetSmoothEdgeIndex() const
33 {
34  int i = 0;
35  int nEdges = _pWXFace->numberOfEdges();
36  for (i = 0; i < nEdges; ++i) {
37  if ((_DotP[i] == 0.0f) && (_DotP[(i + 1) % nEdges] == 0.0f)) { // TODO: ditto
38  return i;
39  }
40  }
41  return -1;
42 }
43 
45 {
46  int i = 0;
47  int nEdges = _pWXFace->numberOfEdges();
48  for (i = 0; i < nEdges; ++i) {
49  if (_DotP[i] * _DotP[(i + 1) % nEdges] < 0.0f) {
50  // we got one
51  oCuspEdges.push_back(i);
52  }
53  }
54 }
55 
57 {
58  // if the smooth edge has already been built: exit
59  if (_pSmoothEdge) {
60  return _pSmoothEdge;
61  }
62  float ta, tb;
63  WOEdge *woea(nullptr), *woeb(nullptr);
64  bool ok = false;
65  vector<int> cuspEdgesIndices;
66  int indexStart, indexEnd;
67  unsigned nedges = _pWXFace->numberOfEdges();
68  if (_nNullDotP == nedges) {
69  _pSmoothEdge = nullptr;
70  return _pSmoothEdge;
71  }
72  if ((_nPosDotP != 0) && (_nPosDotP != _DotP.size()) && (_nNullDotP == 0)) {
73  // that means that we have a smooth edge that starts from an edge and ends at an edge
74  //-----------------------------
75  // We retrieve the 2 edges for which we have opposite signs for each extremity
76  RetrieveCuspEdgesIndices(cuspEdgesIndices);
77  if (cuspEdgesIndices.size() != 2) { // we necessarily have 2 cusp edges
78  return nullptr;
79  }
80 
81  // let us determine which cusp edge corresponds to the starting:
82  // We can do that because we defined that a silhouette edge had the back facing part on its
83  // right. So if the WOEdge woea is such that woea[0].dotp > 0 and woea[1].dotp < 0, it is the
84  // starting edge.
85  //-------------------------------------------
86 
87  if (_DotP[cuspEdgesIndices[0]] > 0.0f) {
88  woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
89  woeb = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
90  indexStart = cuspEdgesIndices[0];
91  indexEnd = cuspEdgesIndices[1];
92  }
93  else {
94  woea = _pWXFace->GetOEdge(cuspEdgesIndices[1]);
95  woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
96  indexStart = cuspEdgesIndices[1];
97  indexEnd = cuspEdgesIndices[0];
98  }
99 
100  // Compute the interpolation:
101  ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]);
102  tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]);
103  ok = true;
104  }
105  else if (_nNullDotP == 1) {
106  // that means that we have exactly one of the 2 extremities of our silhouette edge is a vertex
107  // of the mesh
108  if (ELEM(_nPosDotP, 2, 0)) {
109  _pSmoothEdge = nullptr;
110  return _pSmoothEdge;
111  }
112  RetrieveCuspEdgesIndices(cuspEdgesIndices);
113  // We should have only one EdgeCusp:
114  if (cuspEdgesIndices.size() != 1) {
115  if (G.debug & G_DEBUG_FREESTYLE) {
116  cout << "Warning in BuildSmoothEdge: weird WXFace configuration" << endl;
117  }
118  _pSmoothEdge = nullptr;
119  return nullptr;
120  }
121  unsigned index0 = Get0VertexIndex(); // retrieve the 0 vertex index
122  unsigned nedges = _pWXFace->numberOfEdges();
123  if (_DotP[cuspEdgesIndices[0]] > 0.0f) {
124  woea = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
125  woeb = _pWXFace->GetOEdge(index0);
126  indexStart = cuspEdgesIndices[0];
127  ta = _DotP[indexStart] / (_DotP[indexStart] - _DotP[(indexStart + 1) % nedges]);
128  tb = 0.0f;
129  }
130  else {
131  woea = _pWXFace->GetOEdge(index0);
132  woeb = _pWXFace->GetOEdge(cuspEdgesIndices[0]);
133  indexEnd = cuspEdgesIndices[0];
134  ta = 0.0f;
135  tb = _DotP[indexEnd] / (_DotP[indexEnd] - _DotP[(indexEnd + 1) % nedges]);
136  }
137  ok = true;
138  }
139  else if (_nNullDotP == 2) {
140  // that means that the silhouette edge is an edge of the mesh
141  int index = GetSmoothEdgeIndex();
142  if (!_pWXFace->front()) { // is it in the right order ?
143  // the order of the WOEdge index is wrong
144  woea = _pWXFace->GetOEdge((index + 1) % nedges);
145  woeb = _pWXFace->GetOEdge((index - 1) % nedges);
146  ta = 0.0f;
147  tb = 1.0f;
148  ok = true;
149  }
150  else {
151  // here it's not good, our edge is a single point -> skip that face
152  ok = false;
153 #if 0
154  // the order of the WOEdge index is good
155  woea = _pWXFace->GetOEdge((index - 1) % nedges);
156  woeb = _pWXFace->GetOEdge((index + 1) % nedges);
157  ta = 1.0f;
158  tb = 0.0f;
159 #endif
160  }
161  }
162  if (ok) {
164  _pSmoothEdge->setWOeA(woea);
165  _pSmoothEdge->setWOeB(woeb);
166  _pSmoothEdge->setTa(ta);
167  _pSmoothEdge->setTb(tb);
168  if (_Nature & Nature::SILHOUETTE) {
169  if (_nNullDotP != 2) {
170  if (_DotP[_ClosestPointIndex] + 0.01f > 0.0f) {
171  _pSmoothEdge->setFront(true);
172  }
173  else {
174  _pSmoothEdge->setFront(false);
175  }
176  }
177  }
178  }
179 
180 #if 0
181  // check bording edges to see if they have different dotp values in bording faces.
182  for (int i = 0; i < numberOfEdges(); i++) {
183  WSFace *bface = (WSFace *)GetBordingFace(i);
184  if (bface) {
185  if ((front()) ^
186  (bface->front())) { // fA->front XOR fB->front (true if one is 0 and the other is 1)
187  // that means that the edge i of the face is a silhouette edge
188  // CHECK FIRST WHETHER THE EXACTSILHOUETTEEDGE HAS
189  // NOT YET BEEN BUILT ON THE OTHER FACE (1 is enough).
190  if (((WSExactFace *)bface)->exactSilhouetteEdge()) {
191  // that means that this silhouette edge has already been built
192  return ((WSExactFace *)bface)->exactSilhouetteEdge();
193  }
194  // Else we must build it
195  WOEdge *woea, *woeb;
196  float ta, tb;
197  if (!front()) { // is it in the right order ?
198  // the order of the WOEdge index is wrong
199  woea = _OEdgeList[(i + 1) % numberOfEdges()];
200  if (0 == i) {
201  woeb = _OEdgeList[numberOfEdges() - 1];
202  }
203  else {
204  woeb = _OEdgeList[(i - 1)];
205  }
206  ta = 0.0f;
207  tb = 1.0f;
208  }
209  else {
210  // the order of the WOEdge index is good
211  if (0 == i) {
212  woea = _OEdgeList[numberOfEdges() - 1];
213  }
214  else {
215  woea = _OEdgeList[(i - 1)];
216  }
217  woeb = _OEdgeList[(i + 1) % numberOfEdges()];
218  ta = 1.0f;
219  tb = 0.0f;
220  }
221 
222  _pSmoothEdge = new ExactSilhouetteEdge(ExactSilhouetteEdge::VERTEX_VERTEX);
223  _pSmoothEdge->setWOeA(woea);
224  _pSmoothEdge->setWOeA(woeb);
225  _pSmoothEdge->setTa(ta);
226  _pSmoothEdge->setTb(tb);
227 
228  return _pSmoothEdge;
229  }
230  }
231  }
232 #endif
233  return _pSmoothEdge;
234 }
235 
237 {
238  vector<WVertex *> iVertexList;
239  RetrieveVertexList(iVertexList);
240  Vec3f center;
241  for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end();
242  wv != wvend;
243  ++wv) {
244  center += (*wv)->GetVertex();
245  }
246  center /= (float)iVertexList.size();
247  setCenter(center);
248 }
249 
250 /**********************************
251  * *
252  * *
253  * WXShape *
254  * *
255  * *
256  **********************************/
257 
258 WFace *WXShape::MakeFace(vector<WVertex *> &iVertexList,
259  vector<bool> &iFaceEdgeMarksList,
260  unsigned iMaterialIndex)
261 {
262  WFace *face = WShape::MakeFace(iVertexList, iFaceEdgeMarksList, iMaterialIndex);
263  if (!face) {
264  return nullptr;
265  }
266 
267  Vec3f center;
268  for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end();
269  wv != wvend;
270  ++wv) {
271  center += (*wv)->GetVertex();
272  }
273  center /= (float)iVertexList.size();
274  ((WXFace *)face)->setCenter(center);
275 
276  return face;
277 }
278 
279 WFace *WXShape::MakeFace(vector<WVertex *> &iVertexList,
280  vector<Vec3f> &iNormalsList,
281  vector<Vec2f> &iTexCoordsList,
282  vector<bool> &iFaceEdgeMarksList,
283  unsigned iMaterialIndex)
284 {
285  WFace *face = WShape::MakeFace(
286  iVertexList, iNormalsList, iTexCoordsList, iFaceEdgeMarksList, iMaterialIndex);
287 
288 #if 0
289  Vec3f center;
290  for (vector<WVertex *>::iterator wv = iVertexList.begin(), wvend = iVertexList.end();
291  wv != wvend;
292  ++wv) {
293  center += (*wv)->GetVertex();
294  }
295  center /= (float)iVertexList.size();
296  ((WXFace *)face)->setCenter(center);
297 #endif
298 
299  return face;
300 }
301 
302 } /* namespace Freestyle */
typedef float(TangentPoint)[2]
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:181
#define ELEM(...)
NSNotificationCenter * center
Classes to define an Extended Winged Edge data structure.
int numberOfEdges() const
Definition: WEdge.h:879
WOEdge * GetOEdge(int i)
Definition: WEdge.h:723
void RetrieveVertexList(vector< WVertex * > &oVertices)
Definition: WEdge.h:778
virtual WFace * MakeFace(vector< WVertex * > &iVertexList, vector< bool > &iFaceEdgeMarksList, unsigned iMaterialIndex)
Definition: WEdge.cpp:586
unsigned int Get0VertexIndex() const
Definition: WXEdge.cpp:21
unsigned _nPosDotP
Definition: WXEdge.h:321
unsigned _ClosestPointIndex
Definition: WXEdge.h:324
void RetrieveCuspEdgesIndices(vector< int > &oCuspEdges)
Definition: WXEdge.cpp:44
unsigned int GetSmoothEdgeIndex() const
Definition: WXEdge.cpp:32
vector< float > _DotP
Definition: WXEdge.h:314
unsigned _nNullDotP
Definition: WXEdge.h:323
WXSmoothEdge * BuildSmoothEdge()
Definition: WXEdge.cpp:56
WXSmoothEdge * _pSmoothEdge
Definition: WXEdge.h:315
bool front()
Definition: WXEdge.h:551
void setCenter(const Vec3f &iCenter)
Definition: WXEdge.h:614
void ComputeCenter()
Definition: WXEdge.cpp:236
Vec3f & center()
Definition: WXEdge.h:541
virtual WFace * MakeFace(vector< WVertex * > &iVertexList, vector< bool > &iFaceEdgeMarksList, unsigned iMaterialIndex)
Definition: WXEdge.cpp:258
void setWOeA(WOEdge *iwoea)
Definition: WXEdge.h:268
void setWOeB(WOEdge *iwoeb)
Definition: WXEdge.h:273
void setTb(float tb)
Definition: WXEdge.h:283
void setFront(bool iFront)
Definition: WXEdge.h:288
void setTa(float ta)
Definition: WXEdge.h:278
#define G(x, y, z)
static const EdgeNature SILHOUETTE
Definition: Nature.h:36
inherits from class Rep
Definition: AppCanvas.cpp:18