Blender  V2.93
FEdgeXDetector.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 <cfloat>
23 
24 #include "FEdgeXDetector.h"
25 
26 #include "../geometry/GeomUtils.h"
27 #include "../geometry/normal_cycle.h"
28 
29 #include "BKE_global.h"
30 
31 namespace Freestyle {
32 
34 {
35  bool progressBarDisplay = false;
36 #if 0
37  Vec3r Min, Max;
38 #endif
39  vector<WShape *> wshapes = we.getWShapes();
40  WXShape *wxs;
41 
42  if (_pProgressBar != nullptr) {
44  _pProgressBar->setLabelText("Detecting feature lines");
45  _pProgressBar->setTotalSteps(wshapes.size() * 3);
47  progressBarDisplay = true;
48  }
49 
50  for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
52  break;
53  }
54  wxs = dynamic_cast<WXShape *>(*it);
55 #if 0
56  wxs->bbox(Min, Max);
57  _bbox_diagonal = (Max - Min).norm();
58 #endif
59  if (_changes) {
60  vector<WFace *> &wfaces = wxs->GetFaceList();
61  for (vector<WFace *>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend;
62  ++wf) {
63  WXFace *wxf = dynamic_cast<WXFace *>(*wf);
64  wxf->Clear();
65  }
67  }
68  else if (!(wxs)->getComputeViewIndependentFlag()) {
69  wxs->Reset();
71  }
72  else {
74  }
75  preProcessShape(wxs);
76  if (progressBarDisplay) {
78  }
79  processBorderShape(wxs);
82  }
83  processCreaseShape(wxs);
86  }
89  }
92  if (progressBarDisplay) {
94  }
95 
96  // build smooth edges:
97  buildSmoothEdges(wxs);
98 
99  // Post processing for suggestive contours
102  }
103  if (progressBarDisplay) {
105  }
106 
107  wxs->setComputeViewIndependentFlag(false);
108  _computeViewIndependent = false;
109  _changes = false;
110 
111  // reset user data
112  (*it)->ResetUserData();
113  }
114 }
115 
116 // GENERAL STUFF
119 {
120  _meanK1 = 0;
121  _meanKr = 0;
122  _minK1 = FLT_MAX;
123  _maxK1 = -FLT_MAX;
124  _minKr = FLT_MAX;
125  _maxKr = -FLT_MAX;
126  _nPoints = 0;
127 #if 0
128  _meanEdgeSize = iWShape->getMeanEdgeSize();
129 #else
130  _meanEdgeSize = iWShape->ComputeMeanEdgeSize();
131 #endif
132 
133  vector<WFace *> &wfaces = iWShape->GetFaceList();
134  vector<WFace *>::iterator f, fend;
135  // view dependent stuff
136  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
137  preProcessFace((WXFace *)(*f));
138  }
139 
141  vector<WVertex *> &wvertices = iWShape->getVertexList();
142  for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
143  ++wv) {
144  // Compute curvatures
145  WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
146  computeCurvatures(wxv);
147  }
148  _meanK1 /= (real)(_nPoints);
149  _meanKr /= (real)(_nPoints);
150  }
151 }
152 
154 {
155  Vec3f firstPoint = iFace->GetVertex(0)->GetVertex();
156  Vec3f N = iFace->GetNormal();
157 
158  // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
159  Vec3f V;
161  V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z());
162  }
163  else {
164  V = Vec3f(_Viewpoint - firstPoint);
165  }
166  N.normalize();
167  V.normalize();
168  iFace->setDotP(N * V);
169 
170  // compute the distance between the face center and the viewpoint:
172  iFace->setZ(iFace->center().z() - _Viewpoint.z());
173  }
174  else {
175  Vec3f dist_vec(iFace->center() - _Viewpoint);
176  iFace->setZ(dist_vec.norm());
177  }
178 }
179 
181 {
182  // TODO: for some reason, the 'vertex' may have no associated edges
183  // (i.e., WVertex::_EdgeList is empty), which causes a crash due to
184  // a subsequent call of WVertex::_EdgeList.front().
185  if (vertex->GetEdges().empty()) {
186  if (G.debug & G_DEBUG_FREESTYLE) {
187  printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId());
188  }
189  return;
190  }
191 
192  // CURVATURE LAYER
193  // store all the curvature datas for each vertex
194 
195  // soc unused - real K1, K2
196  real cos2theta, sin2theta;
197  Vec3r e1, n, v;
198  // one vertex curvature info :
199  CurvatureInfo *C;
200  float radius = _sphereRadius * _meanEdgeSize;
201 
202  // view independent stuff
204  C = new CurvatureInfo();
205  vertex->setCurvatures(C);
206  OGF::NormalCycle ncycle;
207  ncycle.begin();
208  if (radius > 0) {
209  OGF::compute_curvature_tensor(vertex, radius, ncycle);
210  }
211  else {
213  }
214  ncycle.end();
215  C->K1 = ncycle.kmin();
216  C->K2 = ncycle.kmax();
217  C->e1 = ncycle.Kmax(); // ncycle.kmin() * ncycle.Kmax();
218  C->e2 = ncycle.Kmin(); // ncycle.kmax() * ncycle.Kmin();
219 
220  real absK1 = fabs(C->K1);
221  _meanK1 += absK1;
222  if (absK1 > _maxK1) {
223  _maxK1 = absK1;
224  }
225  if (absK1 < _minK1) {
226  _minK1 = absK1;
227  }
228  }
229  // view dependent
230  C = vertex->curvatures();
231  if (C == nullptr) {
232  return;
233  }
234 
235  // compute radial curvature :
236  n = C->e1 ^ C->e2;
238  v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
239  }
240  else {
241  v = Vec3r(_Viewpoint - vertex->GetVertex());
242  }
243  C->er = v - (v * n) * n;
244  C->er.normalize();
245  e1 = C->e1;
246  e1.normalize();
247  cos2theta = C->er * e1;
248  cos2theta *= cos2theta;
249  sin2theta = 1 - cos2theta;
250  C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
251  real absKr = fabs(C->Kr);
252  _meanKr += absKr;
253  if (absKr > _maxKr) {
254  _maxKr = absKr;
255  }
256  if (absKr < _minKr) {
257  _minKr = absKr;
258  }
259 
260  ++_nPoints;
261 }
262 
263 // SILHOUETTE
266 {
267  // Make a first pass on every polygons in order to compute all their silhouette relative values:
268  vector<WFace *> &wfaces = iWShape->GetFaceList();
269  vector<WFace *>::iterator f, fend;
270  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
271  ProcessSilhouetteFace((WXFace *)(*f));
272  }
273 
274  // Make a pass on the edges to detect the silhouette edges that are not smooth
275  vector<WEdge *>::iterator we, weend;
276  vector<WEdge *> &wedges = iWShape->getEdgeList();
277  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
278  ProcessSilhouetteEdge((WXEdge *)(*we));
279  }
280 }
281 
283 {
284  // SILHOUETTE LAYER
285  Vec3f normal;
286  // Compute the dot products between View direction and N at each vertex of the face:
287  Vec3f point;
288  int closestPointId = 0;
289  float dist, minDist = FLT_MAX;
290  int numVertices = iFace->numberOfVertices();
291  WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
292  for (int i = 0; i < numVertices; i++) {
293  point = iFace->GetVertex(i)->GetVertex();
294  normal = iFace->GetVertexNormal(i);
295  normal.normalize();
296  Vec3f V;
298  V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z());
299  }
300  else {
301  V = Vec3f(_Viewpoint - point);
302  }
303  V.normalize();
304  float d = normal * V;
305  faceLayer->PushDotP(d);
306  // Find the point the closest to the viewpoint
308  dist = point.z() - _Viewpoint.z();
309  }
310  else {
311  Vec3f dist_vec(point - _Viewpoint);
312  dist = dist_vec.norm();
313  }
314  if (dist < minDist) {
315  minDist = dist;
316  closestPointId = i;
317  }
318  }
319  // Set the closest point id:
320  faceLayer->setClosestPointIndex(closestPointId);
321  // Add this layer to the face:
322  iFace->AddSmoothLayer(faceLayer);
323 }
324 
326 {
327  if (iEdge->nature() & Nature::BORDER) {
328  return;
329  }
330  // SILHOUETTE ?
331  //-------------
332  WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
333  WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
334 
335  if ((fA->front()) ^
336  (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
337  // The only edges we want to set as silhouette edges in this way are the ones with 2 different
338  // normals for 1 vertex for these two faces
339  //--------------------
340  // In reality we only test the normals for 1 of the 2 vertices.
341  if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) {
342  return;
343  }
345  if (fB->front()) {
346  iEdge->setOrder(1);
347  }
348  else {
349  iEdge->setOrder(-1);
350  }
351  }
352 }
353 
354 // BORDER
357 {
359  return;
360  }
361  // Make a pass on the edges to detect the BORDER
362  vector<WEdge *>::iterator we, weend;
363  vector<WEdge *> &wedges = iWShape->getEdgeList();
364  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
365  ProcessBorderEdge((WXEdge *)(*we));
366  }
367 }
368 
370 {
371  // first check whether it is a border edge: BORDER ?
372  //---------
373  if (iEdge->GetaFace() == nullptr) {
374  // it is a border edge
375  iEdge->AddNature(Nature::BORDER);
376  }
377 }
378 
379 // CREASE
382 {
384  return;
385  }
386 
387  // Make a pass on the edges to detect the CREASE
388  vector<WEdge *>::iterator we, weend;
389  vector<WEdge *> &wedges = iWShape->getEdgeList();
390  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
391  ProcessCreaseEdge((WXEdge *)(*we));
392  }
393 }
394 
396 {
397  // CREASE ?
398  //---------
399  if (iEdge->nature() & Nature::BORDER) {
400  return;
401  }
402  WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
403  WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
404 
405  WVertex *aVertex = iEdge->GetaVertex();
406  if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) {
407  iEdge->AddNature(Nature::CREASE);
408  }
409 }
410 
411 // RIDGES AND VALLEYS
414 {
415  // Don't forget to add the built layer to the face at the end of the ProcessFace:
416  // iFace->AddSmoothLayer(faceLayer);
417 
419  return;
420  }
421 
422  // Here the curvatures must already have been computed
423  vector<WFace *> &wfaces = iWShape->GetFaceList();
424  vector<WFace *>::iterator f, fend;
425  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
426  ProcessRidgeFace((WXFace *)(*f));
427  }
428 }
429 
430 // RIDGES
433 {
434  WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false);
435  iFace->AddSmoothLayer(flayer);
436 
437  unsigned int numVertices = iFace->numberOfVertices();
438  for (unsigned int i = 0; i < numVertices; ++i) {
439  WVertex *wv = iFace->GetVertex(i);
440  WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
441  flayer->PushDotP(wxv->curvatures()->K1);
442  }
443 
444 #if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true
445  real threshold = 0;
446  //real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;
447 
448  if (flayer->nPosDotP() != numVertices) {
449  if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) &&
450  (fabs(flayer->dotP(2)) < threshold)) {
451  flayer->ReplaceDotP(0, 0);
452  flayer->ReplaceDotP(1, 0);
453  flayer->ReplaceDotP(2, 0);
454  }
455  }
456 #endif
457 }
458 
459 #if 0
461 {
462  // RIDGE LAYER
463  // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face
464  WVertex *v;
465  Vec3r v1v2;
466  real t;
467  vector<WXFaceLayer *> SmoothLayers;
468  WXFaceLayer *faceLayer;
469  Face_Curvature_Info *layer_info;
470  real K1_a(0), K1_b(0);
471  Vec3r Inter_a, Inter_b;
472 
473  // find the ridge layer of the face
474  iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
475  if (SmoothLayers.size() != 1) {
476  return;
477  }
478  faceLayer = SmoothLayers[0];
479  // retrieve the curvature info of this layer
480  layer_info = (Face_Curvature_Info *)faceLayer->userdata;
481 
482  int numVertices = iFace->numberOfVertices();
483  for (int i = 0; i < numVertices; i++) {
484  v = iFace->GetVertex(i);
485  // vec_curvature_info[i] contains the curvature info of this vertex
486  Vec3r e2 = layer_info->vec_curvature_info[i]->K2 * layer_info->vec_curvature_info[i]->e2;
487  Vec3r e1 = layer_info->vec_curvature_info[i]->K1 * layer_info->vec_curvature_info[i]->e1;
488  e2.normalize();
489 
490  WVertex::face_iterator fit = v->faces_begin();
491  WVertex::face_iterator fitend = v->faces_end();
492  for (; fit != fitend; ++fit) {
493  WXFace *wxf = dynamic_cast<WXFace *>(*fit);
494  WOEdge *oppositeEdge;
495  if (!(wxf->getOppositeEdge(v, oppositeEdge))) {
496  continue;
497  }
498  v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
501  oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex() * e2), t, 1.0e-06);
502  if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
503  vector<WXFaceLayer *> second_ridge_layer;
504  wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
505  if (second_ridge_layer.size() != 1) {
506  continue;
507  }
508  Face_Curvature_Info *second_layer_info =
509  (Face_Curvature_Info *)second_ridge_layer[0]->userdata;
510 
511  unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
512  unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
513  real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
514  real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
515  real K1 = (1.0 - t) * K1_1 + t * K1_2;
516  Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
517  t * oppositeEdge->GetbVertex()->GetVertex());
518  Vec3r vtmp(inter - v->GetVertex());
519  // is it K1_a or K1_b ?
520  if (vtmp * e1 > 0) {
521  K1_b = K1;
522  Inter_b = inter;
523  }
524  else {
525  K1_a = K1;
526  Inter_a = inter;
527  }
528  }
529  }
530  // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
531  //real d = fabs(K1_b) - fabs(K1_a);
532  real d = 0;
533  real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
534  //real threshold = _meanK1;
535  //if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
536  d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
537  faceLayer->PushDotP(d);
538  //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
539  }
540 
541  // Make the values relevant by checking whether all principal directions have the "same" direction:
542  Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
543  e0.normalize();
544  Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
545  e1.normalize();
546  Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
547  e2.normalize();
548  if (e0 * e1 < 0) {
549  // invert dotP[1]
550  faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
551  }
552  if (e0 * e2 < 0) {
553  // invert dotP[2]
554  faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
555  }
556 
557 # if 0 // remove the weakest values;
558  real minDiff = (_maxK1 - _minK1) / 10.0;
559  real minDiff = _meanK1;
560  if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) {
561  faceLayer->ReplaceDotP(0, 0);
562  faceLayer->ReplaceDotP(1, 0);
563  faceLayer->ReplaceDotP(2, 0);
564  }
565 # endif
566 }
567 #endif
568 
569 // SUGGESTIVE CONTOURS
571 
573 {
574  // Here the curvatures must already have been computed
575  vector<WFace *> &wfaces = iWShape->GetFaceList();
576  vector<WFace *>::iterator f, fend;
577  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
579  }
580 }
581 
583 {
584  WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
585  iFace->AddSmoothLayer(faceLayer);
586 
587  unsigned int numVertices = iFace->numberOfVertices();
588  for (unsigned int i = 0; i < numVertices; ++i) {
589  WVertex *wv = iFace->GetVertex(i);
590  WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
591  faceLayer->PushDotP(wxv->curvatures()->Kr);
592  }
593 
594 #if 0 // FIXME: find a more clever way to compute the threshold
595  real threshold = _meanKr;
596  if (faceLayer->nPosDotP() != numVertices) {
597  if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) &&
598  (fabs(faceLayer->dotP(2)) < threshold)) {
599  faceLayer->ReplaceDotP(0, 0);
600  faceLayer->ReplaceDotP(1, 0);
601  faceLayer->ReplaceDotP(2, 0);
602  }
603  }
604 #endif
605 }
606 
608 {
609  vector<WFace *> &wfaces = iShape->GetFaceList();
610  vector<WFace *>::iterator f, fend;
611  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
613  }
614 }
615 
617 {
618  // Compute the derivative of the radial curvature in the radial direction, at the two extremities
619  // of the smooth edge.
620  // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge.
621 
622  // Find the suggestive contour layer of the face (zero or one edge).
623  vector<WXFaceLayer *> sc_layers;
625  if (sc_layers.empty()) {
626  return;
627  }
628 
629  WXFaceLayer *sc_layer;
630  sc_layer = sc_layers[0];
631 
632  // Compute the derivative value at each vertex of the face, and add it in a vector.
633  vector<real> kr_derivatives;
634 
635  unsigned vertices_nb = iFace->numberOfVertices();
636  WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
637  WXFace *wxf;
638  WOEdge *opposite_edge;
639  Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
641  real kr(0), kr1(0), kr2(0), t;
642 
643  for (unsigned int i = 0; i < vertices_nb; ++i) {
644  v = (WXVertex *)(iFace->GetVertex(i));
645 
646  // v is a singular vertex, skip it.
647  if (v->isBoundary()) {
648  kr_derivatives.push_back(0);
649  continue;
650  }
651 
652  v_vec = v->GetVertex();
653  er_vec = v->curvatures()->er;
654 
655  // For each vertex, iterate on its adjacent faces.
656  for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend;
657  ++fit) {
658  wxf = dynamic_cast<WXFace *>(*fit);
659  if (!wxf->getOppositeEdge(v, opposite_edge)) {
660  continue;
661  }
662 
663  opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex();
664  opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex();
665  normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
666  radial_normal_vec = er_vec ^ normal_vec;
667 
668  // Test whether the radial plan intersects with the edge at the opposite of v.
669  res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(),
670  opposite_edge->GetVec(),
671  radial_normal_vec,
672  -(v_vec * radial_normal_vec),
673  t,
674  1.0e-06);
675 
676  // If there is an intersection, compute the value of the derivative ath that point.
677  if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
678  kr = t * opposite_vertex_a->curvatures()->Kr +
679  (1 - t) * opposite_vertex_b->curvatures()->Kr;
680  inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec();
681  tmp_vec = inter - v->GetVertex();
682  // Is it kr1 or kr2?
683  if (tmp_vec * er_vec > 0) {
684  kr2 = kr;
685  inter2 = inter;
686  }
687  else {
688  kr1 = kr;
689  inter1 = inter;
690  }
691  }
692  }
693 
694  // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
695  // We have to compute the derivative of kr for that vertex, equal to:
696  // (kr2 - kr1) / dist(inter1, inter2).
697  // Then we add it to the vector of derivatives.
698  v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
699  kr_derivatives.push_back(v->curvatures()->dKr);
700  }
701 
702  // At that point, we have the derivatives for each vertex of iFace.
703  // All we have to do now is to use linear interpolation to compute the values at the extremities
704  // of the smooth edge.
705  WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
706  WOEdge *sc_oedge = sc_edge->woea();
707  t = sc_edge->ta();
708  if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
709  (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
711  sc_layer->removeSmoothEdge();
712  return;
713  }
714  sc_oedge = sc_edge->woeb();
715  t = sc_edge->tb();
716  if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
717  (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
719  sc_layer->removeSmoothEdge();
720  }
721 }
722 
723 // MATERIAL_BOUNDARY
726 {
728  return;
729  }
730  // Make a pass on the edges to detect material boundaries
731  vector<WEdge *>::iterator we, weend;
732  vector<WEdge *> &wedges = iWShape->getEdgeList();
733  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
735  }
736 }
737 
739 {
740  // check whether the edge is a material boundary?
741  WFace *aFace = iEdge->GetaFace();
742  WFace *bFace = iEdge->GetbFace();
743  if (aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()) {
745  }
746 }
747 
748 // EDGE MARKS
751 {
752  // Make a pass on the edges to detect material boundaries
753  vector<WEdge *>::iterator we, weend;
754  vector<WEdge *> &wedges = iShape->getEdgeList();
755  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
756  ProcessEdgeMarks((WXEdge *)(*we));
757  }
758 }
759 
761 {
762  if (iEdge->GetMark()) {
764  }
765 }
766 
767 // Build Smooth edges
770 {
771  bool hasSmoothEdges = false;
772 
773  // Make a last pass to build smooth edges from the previous stored values:
774  //--------------------------------------------------------------------------
775  vector<WFace *> &wfaces = iShape->GetFaceList();
776  for (vector<WFace *>::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
777  vector<WXFaceLayer *> &faceLayers = ((WXFace *)(*f))->getSmoothLayers();
778  for (vector<WXFaceLayer *>::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end();
779  wxfl != wxflend;
780  ++wxfl) {
781  if ((*wxfl)->BuildSmoothEdge()) {
782  hasSmoothEdges = true;
783  }
784  }
785  }
786 
787  if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) {
788  vector<WVertex *> &wvertices = iShape->getVertexList();
789  for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
790  ++wv) {
791  // Compute curvatures
792  WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
793  computeCurvatures(wxv);
794  }
795  _meanK1 /= (real)(_nPoints);
796  _meanKr /= (real)(_nPoints);
797  }
798 }
799 
800 } /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:140
Detects/flags/builds extended features edges on the WXEdge structure.
_GL_VOID GLfloat value _GL_VOID_RET _GL_VOID const GLuint GLboolean *residences _GL_BOOL_RET _GL_VOID GLsizei GLfloat GLfloat GLfloat GLfloat const GLubyte *bitmap _GL_VOID_RET _GL_VOID GLenum const void *lists _GL_VOID_RET _GL_VOID const GLdouble *equation _GL_VOID_RET _GL_VOID GLdouble GLdouble blue _GL_VOID_RET _GL_VOID GLfloat GLfloat blue _GL_VOID_RET _GL_VOID GLint GLint blue _GL_VOID_RET _GL_VOID GLshort GLshort blue _GL_VOID_RET _GL_VOID GLubyte GLubyte blue _GL_VOID_RET _GL_VOID GLuint GLuint blue _GL_VOID_RET _GL_VOID GLushort GLushort blue _GL_VOID_RET _GL_VOID GLbyte GLbyte GLbyte alpha _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble alpha _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat alpha _GL_VOID_RET _GL_VOID GLint GLint GLint alpha _GL_VOID_RET _GL_VOID GLshort GLshort GLshort alpha _GL_VOID_RET _GL_VOID GLubyte GLubyte GLubyte alpha _GL_VOID_RET _GL_VOID GLuint GLuint GLuint alpha _GL_VOID_RET _GL_VOID GLushort GLushort GLushort alpha _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLint GLsizei GLsizei GLenum type _GL_VOID_RET _GL_VOID GLsizei GLenum GLenum const void *pixels _GL_VOID_RET _GL_VOID const void *pointer _GL_VOID_RET _GL_VOID GLdouble v _GL_VOID_RET _GL_VOID GLfloat v _GL_VOID_RET _GL_VOID GLint GLint i2 _GL_VOID_RET _GL_VOID GLint j _GL_VOID_RET _GL_VOID GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble GLdouble GLdouble zFar _GL_VOID_RET _GL_UINT GLdouble *equation _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLenum GLfloat *v _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLfloat *values _GL_VOID_RET _GL_VOID GLushort *values _GL_VOID_RET _GL_VOID GLenum GLfloat *params _GL_VOID_RET _GL_VOID GLenum GLdouble *params _GL_VOID_RET _GL_VOID GLenum GLint *params _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_BOOL GLfloat param _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLushort pattern _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLint GLdouble GLdouble GLint GLint const GLdouble *points _GL_VOID_RET _GL_VOID GLdouble GLdouble u2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLint GLdouble GLdouble v2 _GL_VOID_RET _GL_VOID GLenum GLfloat param _GL_VOID_RET _GL_VOID GLenum GLint param _GL_VOID_RET _GL_VOID GLenum mode _GL_VOID_RET _GL_VOID GLdouble GLdouble nz _GL_VOID_RET _GL_VOID GLfloat GLfloat nz _GL_VOID_RET _GL_VOID GLint GLint nz _GL_VOID_RET _GL_VOID GLshort GLshort nz _GL_VOID_RET _GL_VOID GLsizei const void *pointer _GL_VOID_RET _GL_VOID GLsizei const GLfloat *values _GL_VOID_RET _GL_VOID GLsizei const GLushort *values _GL_VOID_RET _GL_VOID GLint param _GL_VOID_RET _GL_VOID const GLuint const GLclampf *priorities _GL_VOID_RET _GL_VOID GLdouble y _GL_VOID_RET _GL_VOID GLfloat y _GL_VOID_RET _GL_VOID GLint y _GL_VOID_RET _GL_VOID GLshort y _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLfloat GLfloat z _GL_VOID_RET _GL_VOID GLint GLint z _GL_VOID_RET _GL_VOID GLshort GLshort z _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble w _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat w _GL_VOID_RET _GL_VOID GLint GLint GLint w _GL_VOID_RET _GL_VOID GLshort GLshort GLshort w _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble y2 _GL_VOID_RET _GL_VOID GLfloat GLfloat GLfloat y2 _GL_VOID_RET _GL_VOID GLint GLint GLint y2 _GL_VOID_RET _GL_VOID GLshort GLshort GLshort y2 _GL_VOID_RET _GL_VOID GLdouble GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLdouble GLdouble z _GL_VOID_RET _GL_VOID GLuint *buffer _GL_VOID_RET _GL_VOID GLdouble t _GL_VOID_RET _GL_VOID GLfloat t _GL_VOID_RET _GL_VOID GLint t _GL_VOID_RET _GL_VOID GLshort t _GL_VOID_RET _GL_VOID GLdouble t
#define C
Definition: RandGen.cpp:39
ATTR_WARN_UNUSED_RESULT const BMVert * v
int numVertices() const
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition: btVector3.h:263
virtual void processRidgesAndValleysShape(WXShape *iWShape)
virtual void ProcessBorderEdge(WXEdge *iEdge)
virtual void processShapes(WingedEdge &)
virtual void ProcessMaterialBoundaryEdge(WXEdge *iEdge)
virtual void processEdgeMarksShape(WXShape *iShape)
virtual void processCreaseShape(WXShape *iWShape)
virtual void ProcessEdgeMarks(WXEdge *iEdge)
virtual void ProcessRidgeFace(WXFace *iFace)
virtual void processMaterialBoundaryShape(WXShape *iWShape)
virtual void preProcessFace(WXFace *iFace)
virtual void ProcessSilhouetteFace(WXFace *iFace)
virtual void buildSmoothEdges(WXShape *iShape)
virtual void preProcessShape(WXShape *iWShape)
RenderMonitor * _pRenderMonitor
virtual void computeCurvatures(WXVertex *iVertex)
virtual void processSuggestiveContourShape(WXShape *iWShape)
virtual void processSilhouetteShape(WXShape *iWShape)
virtual void ProcessSilhouetteEdge(WXEdge *iEdge)
virtual void postProcessSuggestiveContourShape(WXShape *iShape)
virtual void ProcessCreaseEdge(WXEdge *iEdge)
virtual void ProcessSuggestiveContourFace(WXFace *iFace)
virtual void postProcessSuggestiveContourFace(WXFace *iFace)
virtual void processBorderShape(WXShape *iWShape)
vector< CurvatureInfo * > vec_curvature_info
Definition: Curvature.h:118
const Vec3r & Kmin() const
Definition: normal_cycle.h:94
const Vec3r & Kmax() const
Definition: normal_cycle.h:89
virtual void setLabelText(const string &s)
Definition: ProgressBar.h:62
virtual void setProgress(unsigned i)
Definition: ProgressBar.h:57
virtual void reset()
Definition: ProgressBar.h:46
unsigned int getProgress() const
Definition: ProgressBar.h:73
virtual void setTotalSteps(unsigned n)
Definition: ProgressBar.h:52
value_type z() const
Definition: VecMat.h:552
value_type norm() const
Definition: VecMat.h:109
Vec< T, N > & normalize()
Definition: VecMat.h:119
WFace * GetaFace()
Definition: WEdge.h:658
WFace * GetbFace()
Definition: WEdge.h:663
bool GetMark()
Definition: WEdge.h:638
WOEdge * GetaOEdge()
Definition: WEdge.h:623
WVertex * GetaVertex()
Definition: WEdge.h:648
unsigned frs_materialIndex() const
Definition: WEdge.h:785
Vec3f & GetVertexNormal(int index)
Definition: WEdge.h:872
Vec3f & GetNormal()
Definition: WEdge.h:775
int numberOfVertices() const
Definition: WEdge.h:931
bool getOppositeEdge(const WVertex *v, WOEdge *&e)
Definition: WEdge.cpp:390
WVertex * GetVertex(unsigned int index)
Definition: WEdge.h:798
int GetIndex(WVertex *iVertex)
Definition: WEdge.h:811
WFace * GetbFace()
Definition: WEdge.h:449
const Vec3f & GetVec()
Definition: WEdge.h:459
WVertex * GetaVertex()
Definition: WEdge.h:434
WFace * GetaFace()
Definition: WEdge.h:444
WVertex * GetbVertex()
Definition: WEdge.h:439
vector< WEdge * > & getEdgeList()
Definition: WEdge.h:1092
real ComputeMeanEdgeSize() const
Definition: WEdge.cpp:723
vector< WVertex * > & getVertexList()
Definition: WEdge.h:1097
vector< WFace * > & GetFaceList()
Definition: WEdge.h:1102
Vec3f & GetVertex()
Definition: WEdge.h:87
vector< WEdge * > & GetEdges()
Definition: WEdge.h:92
WXNature nature()
Definition: WXEdge.h:163
void setOrder(int i)
Definition: WXEdge.h:194
void AddNature(WXNature iNature)
Definition: WXEdge.h:189
const float dotP(int i) const
Definition: WXEdge.h:378
void setClosestPointIndex(int iIndex)
Definition: WXEdge.h:426
void PushDotP(float iDotP)
Definition: WXEdge.h:462
void ReplaceDotP(unsigned int index, float newDotP)
Definition: WXEdge.h:473
unsigned nPosDotP() const
Definition: WXEdge.h:383
WXSmoothEdge * getSmoothEdge()
Definition: WXEdge.h:416
void removeSmoothEdge()
Definition: WXEdge.h:431
void setDotP(float iDotP)
Definition: WXEdge.h:645
void Clear()
Definition: WXEdge.h:678
void retrieveSmoothLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothLayers)
Definition: WXEdge.h:616
bool front()
Definition: WXEdge.h:565
void retrieveSmoothEdgesLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothEdgesLayers)
Definition: WXEdge.h:605
void AddSmoothLayer(WXFaceLayer *iLayer)
Definition: WXEdge.h:656
void setZ(float z)
Definition: WXEdge.h:635
Vec3f & center()
Definition: WXEdge.h:555
virtual void Reset()
Definition: WXEdge.h:796
void setComputeViewIndependentFlag(bool iFlag)
Definition: WXEdge.h:748
float ta() const
Definition: WXEdge.h:261
float tb() const
Definition: WXEdge.h:266
void setCurvatures(CurvatureInfo *ci)
Definition: WXEdge.h:81
CurvatureInfo * curvatures()
Definition: WXEdge.h:88
vector< WShape * > & getWShapes()
Definition: WEdge.h:1369
struct Vec3f Vec3f
IconTextureDrawCall normal
intersection_test intersectRayPlane(const Vec3r &orig, const Vec3r &dir, const Vec3r &norm, const real d, real &t, const real epsilon)
Definition: GeomUtils.cpp:512
VecMat::Vec3< real > Vec3r
Definition: Geom.h:42
static const EdgeNature BORDER
Definition: Nature.h:52
static const EdgeNature MATERIAL_BOUNDARY
Definition: Nature.h:62
static const EdgeNature EDGE_MARK
Definition: Nature.h:64
static const EdgeNature VALLEY
Definition: Nature.h:58
static const EdgeNature CREASE
Definition: Nature.h:54
static const EdgeNature RIDGE
Definition: Nature.h:56
static const EdgeNature SILHOUETTE
Definition: Nature.h:50
static const EdgeNature SUGGESTIVE_CONTOUR
Definition: Nature.h:60
void compute_curvature_tensor(WVertex *start, real radius, NormalCycle &nc)
Definition: Curvature.cpp:605
void compute_curvature_tensor_one_ring(WVertex *start, NormalCycle &nc)
Definition: Curvature.cpp:647
inherits from class Rep
Definition: AppCanvas.cpp:32
double real
Definition: Precision.h:26
params N
ccl_device_inline float2 fabs(const float2 &a)
#define G(x, y, z)
CCL_NAMESPACE_BEGIN struct View V