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