Blender  V3.3
FEdgeXDetector.cpp
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
8 #include <cfloat>
9 
10 #include "FEdgeXDetector.h"
11 
12 #include "../geometry/GeomUtils.h"
13 #include "../geometry/normal_cycle.h"
14 
15 #include "BKE_global.h"
16 
17 namespace Freestyle {
18 
20 {
21  bool progressBarDisplay = false;
22 #if 0
23  Vec3r Min, Max;
24 #endif
25  vector<WShape *> wshapes = we.getWShapes();
26  WXShape *wxs;
27 
28  if (_pProgressBar != nullptr) {
30  _pProgressBar->setLabelText("Detecting feature lines");
31  _pProgressBar->setTotalSteps(wshapes.size() * 3);
33  progressBarDisplay = true;
34  }
35 
36  for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
38  break;
39  }
40  wxs = dynamic_cast<WXShape *>(*it);
41 #if 0
42  wxs->bbox(Min, Max);
43  _bbox_diagonal = (Max - Min).norm();
44 #endif
45  if (_changes) {
46  vector<WFace *> &wfaces = wxs->GetFaceList();
47  for (vector<WFace *>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend;
48  ++wf) {
49  WXFace *wxf = dynamic_cast<WXFace *>(*wf);
50  wxf->Clear();
51  }
53  }
54  else if (!(wxs)->getComputeViewIndependentFlag()) {
55  wxs->Reset();
57  }
58  else {
60  }
61  preProcessShape(wxs);
62  if (progressBarDisplay) {
64  }
65  processBorderShape(wxs);
68  }
69  processCreaseShape(wxs);
72  }
75  }
78  if (progressBarDisplay) {
80  }
81 
82  // build smooth edges:
83  buildSmoothEdges(wxs);
84 
85  // Post processing for suggestive contours
88  }
89  if (progressBarDisplay) {
91  }
92 
95  _changes = false;
96 
97  // reset user data
98  (*it)->ResetUserData();
99  }
100 }
101 
102 // GENERAL STUFF
105 {
106  _meanK1 = 0;
107  _meanKr = 0;
108  _minK1 = FLT_MAX;
109  _maxK1 = -FLT_MAX;
110  _minKr = FLT_MAX;
111  _maxKr = -FLT_MAX;
112  _nPoints = 0;
113 #if 0
114  _meanEdgeSize = iWShape->getMeanEdgeSize();
115 #else
116  _meanEdgeSize = iWShape->ComputeMeanEdgeSize();
117 #endif
118 
119  vector<WFace *> &wfaces = iWShape->GetFaceList();
120  vector<WFace *>::iterator f, fend;
121  // view dependent stuff
122  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
123  preProcessFace((WXFace *)(*f));
124  }
125 
127  vector<WVertex *> &wvertices = iWShape->getVertexList();
128  for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
129  ++wv) {
130  // Compute curvatures
131  WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
132  computeCurvatures(wxv);
133  }
134  _meanK1 /= (real)(_nPoints);
135  _meanKr /= (real)(_nPoints);
136  }
137 }
138 
140 {
141  Vec3f firstPoint = iFace->GetVertex(0)->GetVertex();
142  Vec3f N = iFace->GetNormal();
143 
144  // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
145  Vec3f V;
147  V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z());
148  }
149  else {
150  V = Vec3f(_Viewpoint - firstPoint);
151  }
152  N.normalize();
153  V.normalize();
154  iFace->setDotP(N * V);
155 
156  // compute the distance between the face center and the viewpoint:
158  iFace->setZ(iFace->center().z() - _Viewpoint.z());
159  }
160  else {
161  Vec3f dist_vec(iFace->center() - _Viewpoint);
162  iFace->setZ(dist_vec.norm());
163  }
164 }
165 
167 {
168  // TODO: for some reason, the 'vertex' may have no associated edges
169  // (i.e., WVertex::_EdgeList is empty), which causes a crash due to
170  // a subsequent call of WVertex::_EdgeList.front().
171  if (vertex->GetEdges().empty()) {
172  if (G.debug & G_DEBUG_FREESTYLE) {
173  printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId());
174  }
175  return;
176  }
177 
178  // CURVATURE LAYER
179  // store all the curvature data for each vertex
180 
181  // soc unused - real K1, K2
182  real cos2theta, sin2theta;
183  Vec3r e1, n, v;
184  // one vertex curvature info :
185  CurvatureInfo *C;
186  float radius = _sphereRadius * _meanEdgeSize;
187 
188  // view independent stuff
190  C = new CurvatureInfo();
191  vertex->setCurvatures(C);
192  OGF::NormalCycle ncycle;
193  ncycle.begin();
194  if (radius > 0) {
195  OGF::compute_curvature_tensor(vertex, radius, ncycle);
196  }
197  else {
199  }
200  ncycle.end();
201  C->K1 = ncycle.kmin();
202  C->K2 = ncycle.kmax();
203  C->e1 = ncycle.Kmax(); // ncycle.kmin() * ncycle.Kmax();
204  C->e2 = ncycle.Kmin(); // ncycle.kmax() * ncycle.Kmin();
205 
206  real absK1 = fabs(C->K1);
207  _meanK1 += absK1;
208  if (absK1 > _maxK1) {
209  _maxK1 = absK1;
210  }
211  if (absK1 < _minK1) {
212  _minK1 = absK1;
213  }
214  }
215  // view dependent
216  C = vertex->curvatures();
217  if (C == nullptr) {
218  return;
219  }
220 
221  // compute radial curvature :
222  n = C->e1 ^ C->e2;
224  v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
225  }
226  else {
227  v = Vec3r(_Viewpoint - vertex->GetVertex());
228  }
229  C->er = v - (v * n) * n;
230  C->er.normalize();
231  e1 = C->e1;
232  e1.normalize();
233  cos2theta = C->er * e1;
234  cos2theta *= cos2theta;
235  sin2theta = 1 - cos2theta;
236  C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
237  real absKr = fabs(C->Kr);
238  _meanKr += absKr;
239  if (absKr > _maxKr) {
240  _maxKr = absKr;
241  }
242  if (absKr < _minKr) {
243  _minKr = absKr;
244  }
245 
246  ++_nPoints;
247 }
248 
249 // SILHOUETTE
252 {
253  // Make a first pass on every polygons in order to compute all their silhouette relative values:
254  vector<WFace *> &wfaces = iWShape->GetFaceList();
255  vector<WFace *>::iterator f, fend;
256  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
257  ProcessSilhouetteFace((WXFace *)(*f));
258  }
259 
260  // Make a pass on the edges to detect the silhouette edges that are not smooth
261  vector<WEdge *>::iterator we, weend;
262  vector<WEdge *> &wedges = iWShape->getEdgeList();
263  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
264  ProcessSilhouetteEdge((WXEdge *)(*we));
265  }
266 }
267 
269 {
270  // SILHOUETTE LAYER
271  Vec3f normal;
272  // Compute the dot products between View direction and N at each vertex of the face:
273  Vec3f point;
274  int closestPointId = 0;
275  float dist, minDist = FLT_MAX;
276  int numVertices = iFace->numberOfVertices();
277  WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
278  for (int i = 0; i < numVertices; i++) {
279  point = iFace->GetVertex(i)->GetVertex();
280  normal = iFace->GetVertexNormal(i);
281  normal.normalize();
282  Vec3f V;
284  V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z());
285  }
286  else {
287  V = Vec3f(_Viewpoint - point);
288  }
289  V.normalize();
290  float d = normal * V;
291  faceLayer->PushDotP(d);
292  // Find the point the closest to the viewpoint
294  dist = point.z() - _Viewpoint.z();
295  }
296  else {
297  Vec3f dist_vec(point - _Viewpoint);
298  dist = dist_vec.norm();
299  }
300  if (dist < minDist) {
301  minDist = dist;
302  closestPointId = i;
303  }
304  }
305  // Set the closest point id:
306  faceLayer->setClosestPointIndex(closestPointId);
307  // Add this layer to the face:
308  iFace->AddSmoothLayer(faceLayer);
309 }
310 
312 {
313  if (iEdge->nature() & Nature::BORDER) {
314  return;
315  }
316  // SILHOUETTE ?
317  //-------------
318  WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
319  WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
320 
321  if ((fA->front()) ^
322  (fB->front())) { // fA->visible XOR fB->visible (true if one is 0 and the other is 1)
323  // The only edges we want to set as silhouette edges in this way are the ones with 2 different
324  // normals for 1 vertex for these two faces
325  //--------------------
326  // In reality we only test the normals for 1 of the 2 vertices.
327  if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) {
328  return;
329  }
331  if (fB->front()) {
332  iEdge->setOrder(1);
333  }
334  else {
335  iEdge->setOrder(-1);
336  }
337  }
338 }
339 
340 // BORDER
343 {
345  return;
346  }
347  // Make a pass on the edges to detect the BORDER
348  vector<WEdge *>::iterator we, weend;
349  vector<WEdge *> &wedges = iWShape->getEdgeList();
350  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
351  ProcessBorderEdge((WXEdge *)(*we));
352  }
353 }
354 
356 {
357  // first check whether it is a border edge: BORDER ?
358  //---------
359  if (iEdge->GetaFace() == nullptr) {
360  // it is a border edge
361  iEdge->AddNature(Nature::BORDER);
362  }
363 }
364 
365 // CREASE
368 {
370  return;
371  }
372 
373  // Make a pass on the edges to detect the CREASE
374  vector<WEdge *>::iterator we, weend;
375  vector<WEdge *> &wedges = iWShape->getEdgeList();
376  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
377  ProcessCreaseEdge((WXEdge *)(*we));
378  }
379 }
380 
382 {
383  // CREASE ?
384  //---------
385  if (iEdge->nature() & Nature::BORDER) {
386  return;
387  }
388  WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
389  WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
390 
391  WVertex *aVertex = iEdge->GetaVertex();
392  if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) {
393  iEdge->AddNature(Nature::CREASE);
394  }
395 }
396 
397 // RIDGES AND VALLEYS
400 {
401  // Don't forget to add the built layer to the face at the end of the ProcessFace:
402  // iFace->AddSmoothLayer(faceLayer);
403 
405  return;
406  }
407 
408  // Here the curvatures must already have been computed
409  vector<WFace *> &wfaces = iWShape->GetFaceList();
410  vector<WFace *>::iterator f, fend;
411  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
412  ProcessRidgeFace((WXFace *)(*f));
413  }
414 }
415 
416 // RIDGES
419 {
420  WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false);
421  iFace->AddSmoothLayer(flayer);
422 
423  unsigned int numVertices = iFace->numberOfVertices();
424  for (unsigned int i = 0; i < numVertices; ++i) {
425  WVertex *wv = iFace->GetVertex(i);
426  WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
427  flayer->PushDotP(wxv->curvatures()->K1);
428  }
429 
430 #if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true
431  real threshold = 0;
432  //real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;
433 
434  if (flayer->nPosDotP() != numVertices) {
435  if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) &&
436  (fabs(flayer->dotP(2)) < threshold)) {
437  flayer->ReplaceDotP(0, 0);
438  flayer->ReplaceDotP(1, 0);
439  flayer->ReplaceDotP(2, 0);
440  }
441  }
442 #endif
443 }
444 
445 #if 0
447 {
448  // RIDGE LAYER
449  // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each vertex of the face
450  WVertex *v;
451  Vec3r v1v2;
452  real t;
453  vector<WXFaceLayer *> SmoothLayers;
454  WXFaceLayer *faceLayer;
455  Face_Curvature_Info *layer_info;
456  real K1_a(0), K1_b(0);
457  Vec3r Inter_a, Inter_b;
458 
459  // find the ridge layer of the face
460  iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
461  if (SmoothLayers.size() != 1) {
462  return;
463  }
464  faceLayer = SmoothLayers[0];
465  // retrieve the curvature info of this layer
466  layer_info = (Face_Curvature_Info *)faceLayer->userdata;
467 
468  int numVertices = iFace->numberOfVertices();
469  for (int i = 0; i < numVertices; i++) {
470  v = iFace->GetVertex(i);
471  // vec_curvature_info[i] contains the curvature info of this vertex
472  Vec3r e2 = layer_info->vec_curvature_info[i]->K2 * layer_info->vec_curvature_info[i]->e2;
473  Vec3r e1 = layer_info->vec_curvature_info[i]->K1 * layer_info->vec_curvature_info[i]->e1;
474  e2.normalize();
475 
476  WVertex::face_iterator fit = v->faces_begin();
477  WVertex::face_iterator fitend = v->faces_end();
478  for (; fit != fitend; ++fit) {
479  WXFace *wxf = dynamic_cast<WXFace *>(*fit);
480  WOEdge *oppositeEdge;
481  if (!(wxf->getOppositeEdge(v, oppositeEdge))) {
482  continue;
483  }
484  v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
487  oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex() * e2), t, 1.0e-06);
488  if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
489  vector<WXFaceLayer *> second_ridge_layer;
490  wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
491  if (second_ridge_layer.size() != 1) {
492  continue;
493  }
494  Face_Curvature_Info *second_layer_info =
495  (Face_Curvature_Info *)second_ridge_layer[0]->userdata;
496 
497  unsigned index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
498  unsigned index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
499  real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
500  real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
501  real K1 = (1.0 - t) * K1_1 + t * K1_2;
502  Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
503  t * oppositeEdge->GetbVertex()->GetVertex());
504  Vec3r vtmp(inter - v->GetVertex());
505  // is it K1_a or K1_b ?
506  if (vtmp * e1 > 0) {
507  K1_b = K1;
508  Inter_b = inter;
509  }
510  else {
511  K1_a = K1;
512  Inter_a = inter;
513  }
514  }
515  }
516  // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
517  //real d = fabs(K1_b) - fabs(K1_a);
518  real d = 0;
519  real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
520  //real threshold = _meanK1;
521  //if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
522  d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
523  faceLayer->PushDotP(d);
524  //faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
525  }
526 
527  // Make the values relevant by checking whether all principal directions have the "same" direction:
528  Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
529  e0.normalize();
530  Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
531  e1.normalize();
532  Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
533  e2.normalize();
534  if (e0 * e1 < 0) {
535  // invert dotP[1]
536  faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
537  }
538  if (e0 * e2 < 0) {
539  // invert dotP[2]
540  faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
541  }
542 
543 # if 0 // remove the weakest values;
544  real minDiff = (_maxK1 - _minK1) / 10.0;
545  real minDiff = _meanK1;
546  if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) && (faceLayer->dotP(2) < minDiff)) {
547  faceLayer->ReplaceDotP(0, 0);
548  faceLayer->ReplaceDotP(1, 0);
549  faceLayer->ReplaceDotP(2, 0);
550  }
551 # endif
552 }
553 #endif
554 
555 // SUGGESTIVE CONTOURS
557 
559 {
560  // Here the curvatures must already have been computed
561  vector<WFace *> &wfaces = iWShape->GetFaceList();
562  vector<WFace *>::iterator f, fend;
563  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
565  }
566 }
567 
569 {
570  WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
571  iFace->AddSmoothLayer(faceLayer);
572 
573  unsigned int numVertices = iFace->numberOfVertices();
574  for (unsigned int i = 0; i < numVertices; ++i) {
575  WVertex *wv = iFace->GetVertex(i);
576  WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
577  faceLayer->PushDotP(wxv->curvatures()->Kr);
578  }
579 
580 #if 0 // FIXME: find a more clever way to compute the threshold
582  if (faceLayer->nPosDotP() != numVertices) {
583  if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) &&
584  (fabs(faceLayer->dotP(2)) < threshold)) {
585  faceLayer->ReplaceDotP(0, 0);
586  faceLayer->ReplaceDotP(1, 0);
587  faceLayer->ReplaceDotP(2, 0);
588  }
589  }
590 #endif
591 }
592 
594 {
595  vector<WFace *> &wfaces = iShape->GetFaceList();
596  vector<WFace *>::iterator f, fend;
597  for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
599  }
600 }
601 
603 {
604  // Compute the derivative of the radial curvature in the radial direction, at the two extremities
605  // of the smooth edge.
606  // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge.
607 
608  // Find the suggestive contour layer of the face (zero or one edge).
609  vector<WXFaceLayer *> sc_layers;
611  if (sc_layers.empty()) {
612  return;
613  }
614 
615  WXFaceLayer *sc_layer;
616  sc_layer = sc_layers[0];
617 
618  // Compute the derivative value at each vertex of the face, and add it in a vector.
619  vector<real> kr_derivatives;
620 
621  unsigned vertices_nb = iFace->numberOfVertices();
622  WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
623  WXFace *wxf;
624  WOEdge *opposite_edge;
625  Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
627  real kr(0), kr1(0), kr2(0), t;
628 
629  for (unsigned int i = 0; i < vertices_nb; ++i) {
630  v = (WXVertex *)(iFace->GetVertex(i));
631 
632  // v is a singular vertex, skip it.
633  if (v->isBoundary()) {
634  kr_derivatives.push_back(0);
635  continue;
636  }
637 
638  v_vec = v->GetVertex();
639  er_vec = v->curvatures()->er;
640 
641  // For each vertex, iterate on its adjacent faces.
642  for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend;
643  ++fit) {
644  wxf = dynamic_cast<WXFace *>(*fit);
645  if (!wxf->getOppositeEdge(v, opposite_edge)) {
646  continue;
647  }
648 
649  opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex();
650  opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex();
651  normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
652  radial_normal_vec = er_vec ^ normal_vec;
653 
654  // Test whether the radial plan intersects with the edge at the opposite of v.
655  res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(),
656  opposite_edge->GetVec(),
657  radial_normal_vec,
658  -(v_vec * radial_normal_vec),
659  t,
660  1.0e-06);
661 
662  // If there is an intersection, compute the value of the derivative ath that point.
663  if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
664  kr = t * opposite_vertex_a->curvatures()->Kr +
665  (1 - t) * opposite_vertex_b->curvatures()->Kr;
666  inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec();
667  tmp_vec = inter - v->GetVertex();
668  // Is it kr1 or kr2?
669  if (tmp_vec * er_vec > 0) {
670  kr2 = kr;
671  inter2 = inter;
672  }
673  else {
674  kr1 = kr;
675  inter1 = inter;
676  }
677  }
678  }
679 
680  // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
681  // We have to compute the derivative of kr for that vertex, equal to:
682  // (kr2 - kr1) / dist(inter1, inter2).
683  // Then we add it to the vector of derivatives.
684  v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
685  kr_derivatives.push_back(v->curvatures()->dKr);
686  }
687 
688  // At that point, we have the derivatives for each vertex of iFace.
689  // All we have to do now is to use linear interpolation to compute the values at the extremities
690  // of the smooth edge.
691  WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
692  WOEdge *sc_oedge = sc_edge->woea();
693  t = sc_edge->ta();
694  if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
695  (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
697  sc_layer->removeSmoothEdge();
698  return;
699  }
700  sc_oedge = sc_edge->woeb();
701  t = sc_edge->tb();
702  if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
703  (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
705  sc_layer->removeSmoothEdge();
706  }
707 }
708 
709 // MATERIAL_BOUNDARY
712 {
714  return;
715  }
716  // Make a pass on the edges to detect material boundaries
717  vector<WEdge *>::iterator we, weend;
718  vector<WEdge *> &wedges = iWShape->getEdgeList();
719  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
721  }
722 }
723 
725 {
726  // check whether the edge is a material boundary?
727  WFace *aFace = iEdge->GetaFace();
728  WFace *bFace = iEdge->GetbFace();
729  if (aFace && bFace && aFace->frs_materialIndex() != bFace->frs_materialIndex()) {
731  }
732 }
733 
734 // EDGE MARKS
737 {
738  // Make a pass on the edges to detect material boundaries
739  vector<WEdge *>::iterator we, weend;
740  vector<WEdge *> &wedges = iShape->getEdgeList();
741  for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
742  ProcessEdgeMarks((WXEdge *)(*we));
743  }
744 }
745 
747 {
748  if (iEdge->GetMark()) {
750  }
751 }
752 
753 // Build Smooth edges
756 {
757  bool hasSmoothEdges = false;
758 
759  // Make a last pass to build smooth edges from the previous stored values:
760  //--------------------------------------------------------------------------
761  vector<WFace *> &wfaces = iShape->GetFaceList();
762  for (vector<WFace *>::iterator f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
763  vector<WXFaceLayer *> &faceLayers = ((WXFace *)(*f))->getSmoothLayers();
764  for (vector<WXFaceLayer *>::iterator wxfl = faceLayers.begin(), wxflend = faceLayers.end();
765  wxfl != wxflend;
766  ++wxfl) {
767  if ((*wxfl)->BuildSmoothEdge()) {
768  hasSmoothEdges = true;
769  }
770  }
771  }
772 
773  if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) {
774  vector<WVertex *> &wvertices = iShape->getVertexList();
775  for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
776  ++wv) {
777  // Compute curvatures
778  WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
779  computeCurvatures(wxv);
780  }
781  _meanK1 /= (real)(_nPoints);
782  _meanKr /= (real)(_nPoints);
783  }
784 }
785 
786 } /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Definition: BKE_global.h:181
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
in reality light always falls off quadratically Particle Retrieve the data of the particle that spawned the object for example to give variation to multiple instances of an object Point Retrieve information about points in a point cloud Retrieve the edges of an object as it appears to Cycles topology will always appear triangulated Convert a blackbody temperature to an RGB value Normal Generate a perturbed normal from an RGB normal map image Typically used for faking highly detailed surfaces Generate an OSL shader from a file or text data block Image Sample an image file as a texture Sky Generate a procedural sky texture Noise Generate fractal Perlin noise Wave Generate procedural bands or rings with noise Voronoi Generate Worley noise based on the distance to random points Typically used to generate textures such as or biological cells Brick Generate a procedural texture producing bricks Texture Retrieve multiple types of texture coordinates nTypically used as inputs for texture nodes Vector Convert a point
#define C
Definition: RandGen.cpp:25
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:97
const Vec3r & Kmin() const
Definition: normal_cycle.h:72
const Vec3r & Kmax() const
Definition: normal_cycle.h:67
virtual void setLabelText(const string &s)
Definition: ProgressBar.h:48
virtual void setProgress(unsigned i)
Definition: ProgressBar.h:43
virtual void reset()
Definition: ProgressBar.h:32
unsigned int getProgress() const
Definition: ProgressBar.h:59
virtual void setTotalSteps(unsigned n)
Definition: ProgressBar.h:38
value_type z() const
Definition: VecMat.h:538
value_type norm() const
Definition: VecMat.h:95
Vec< T, N > & normalize()
Definition: VecMat.h:105
WFace * GetaFace()
Definition: WEdge.h:611
WFace * GetbFace()
Definition: WEdge.h:616
bool GetMark()
Definition: WEdge.h:591
WOEdge * GetaOEdge()
Definition: WEdge.h:576
WVertex * GetaVertex()
Definition: WEdge.h:601
unsigned frs_materialIndex() const
Definition: WEdge.h:738
Vec3f & GetVertexNormal(int index)
Definition: WEdge.h:825
Vec3f & GetNormal()
Definition: WEdge.h:728
int numberOfVertices() const
Definition: WEdge.h:884
bool getOppositeEdge(const WVertex *v, WOEdge *&e)
Definition: WEdge.cpp:376
WVertex * GetVertex(unsigned int index)
Definition: WEdge.h:751
int GetIndex(WVertex *iVertex)
Definition: WEdge.h:764
WFace * GetbFace()
Definition: WEdge.h:402
const Vec3f & GetVec()
Definition: WEdge.h:412
WVertex * GetaVertex()
Definition: WEdge.h:387
WFace * GetaFace()
Definition: WEdge.h:397
WVertex * GetbVertex()
Definition: WEdge.h:392
vector< WEdge * > & getEdgeList()
Definition: WEdge.h:1045
real ComputeMeanEdgeSize() const
Definition: WEdge.cpp:709
vector< WVertex * > & getVertexList()
Definition: WEdge.h:1050
vector< WFace * > & GetFaceList()
Definition: WEdge.h:1055
Vec3f & GetVertex()
Definition: WEdge.h:73
vector< WEdge * > & GetEdges()
Definition: WEdge.h:78
WXNature nature()
Definition: WXEdge.h:149
void setOrder(int i)
Definition: WXEdge.h:180
void AddNature(WXNature iNature)
Definition: WXEdge.h:175
const float dotP(int i) const
Definition: WXEdge.h:364
void setClosestPointIndex(int iIndex)
Definition: WXEdge.h:412
void PushDotP(float iDotP)
Definition: WXEdge.h:448
void ReplaceDotP(unsigned int index, float newDotP)
Definition: WXEdge.h:459
unsigned nPosDotP() const
Definition: WXEdge.h:369
WXSmoothEdge * getSmoothEdge()
Definition: WXEdge.h:402
void removeSmoothEdge()
Definition: WXEdge.h:417
void setDotP(float iDotP)
Definition: WXEdge.h:631
void Clear()
Definition: WXEdge.h:664
void retrieveSmoothLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothLayers)
Definition: WXEdge.h:602
bool front()
Definition: WXEdge.h:551
void retrieveSmoothEdgesLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothEdgesLayers)
Definition: WXEdge.h:591
void AddSmoothLayer(WXFaceLayer *iLayer)
Definition: WXEdge.h:642
void setZ(float z)
Definition: WXEdge.h:621
Vec3f & center()
Definition: WXEdge.h:541
virtual void Reset()
Definition: WXEdge.h:782
void setComputeViewIndependentFlag(bool iFlag)
Definition: WXEdge.h:734
float ta() const
Definition: WXEdge.h:247
float tb() const
Definition: WXEdge.h:252
void setCurvatures(CurvatureInfo *ci)
Definition: WXEdge.h:67
CurvatureInfo * curvatures()
Definition: WXEdge.h:74
vector< WShape * > & getWShapes()
Definition: WEdge.h:1322
struct Vec3f Vec3f
IconTextureDrawCall normal
ccl_gpu_kernel_postfix ccl_global float int int int int float threshold
ccl_device_inline float2 fabs(const float2 &a)
Definition: math_float2.h:222
#define N
#define G(x, y, z)
intersection_test intersectRayPlane(const Vec3r &orig, const Vec3r &dir, const Vec3r &norm, const real d, real &t, const real epsilon)
Definition: GeomUtils.cpp:498
VecMat::Vec3< real > Vec3r
Definition: Geom.h:28
static const EdgeNature BORDER
Definition: Nature.h:38
static const EdgeNature MATERIAL_BOUNDARY
Definition: Nature.h:48
static const EdgeNature EDGE_MARK
Definition: Nature.h:50
static const EdgeNature VALLEY
Definition: Nature.h:44
static const EdgeNature CREASE
Definition: Nature.h:40
static const EdgeNature RIDGE
Definition: Nature.h:42
static const EdgeNature SILHOUETTE
Definition: Nature.h:36
static const EdgeNature SUGGESTIVE_CONTOUR
Definition: Nature.h:46
void compute_curvature_tensor(WVertex *start, real radius, NormalCycle &nc)
Definition: Curvature.cpp:518
void compute_curvature_tensor_one_ring(WVertex *start, NormalCycle &nc)
Definition: Curvature.cpp:560
inherits from class Rep
Definition: AppCanvas.cpp:18
double real
Definition: Precision.h:12
CCL_NAMESPACE_BEGIN struct Window V