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