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
17 /** \file
18 * \ingroup freestyle
19 * \brief Classes to define an Extended Winged Edge data structure.
20 */
21
22 #include "WXEdge.h"
23 #include "BKE_global.h"
24
25 namespace Freestyle {
26
27 /**********************************
28 * *
29 * *
30 * WXFace *
31 * *
32 * *
33 **********************************/
34
Get0VertexIndex() const35 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 }
GetSmoothEdgeIndex() const46 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
RetrieveCuspEdgesIndices(vector<int> & oCuspEdges)58 void WXFaceLayer::RetrieveCuspEdgesIndices(vector<int> &oCuspEdges)
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
BuildSmoothEdge()70 WXSmoothEdge *WXFaceLayer::BuildSmoothEdge()
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(0), *woeb(0);
78 bool ok = false;
79 vector<int> cuspEdgesIndices;
80 int indexStart, indexEnd;
81 unsigned nedges = _pWXFace->numberOfEdges();
82 if (_nNullDotP == nedges) {
83 _pSmoothEdge = NULL;
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 0;
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 ((_nPosDotP == 2) || (_nPosDotP == 0)) {
123 _pSmoothEdge = NULL;
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 = NULL;
133 return NULL;
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) {
177 _pSmoothEdge = new WXSmoothEdge;
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
ComputeCenter()250 void WXFace::ComputeCenter()
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
MakeFace(vector<WVertex * > & iVertexList,vector<bool> & iFaceEdgeMarksList,unsigned iMaterialIndex)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 NULL;
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
MakeFace(vector<WVertex * > & iVertexList,vector<Vec3f> & iNormalsList,vector<Vec2f> & iTexCoordsList,vector<bool> & iFaceEdgeMarksList,unsigned iMaterialIndex)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 */
317