Blender V5.0
FEdgeXDetector.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 <cfloat>
11
12#include "FEdgeXDetector.h"
13
16
17#include "BLI_sys_types.h"
18
19#include "BKE_global.hh"
20
21namespace Freestyle {
22
24{
25 bool progressBarDisplay = false;
26#if 0
27 Vec3r Min, Max;
28#endif
29 vector<WShape *> wshapes = we.getWShapes();
30 WXShape *wxs;
31
32 if (_pProgressBar != nullptr) {
33 _pProgressBar->reset();
34 _pProgressBar->setLabelText("Detecting feature lines");
35 _pProgressBar->setTotalSteps(wshapes.size() * 3);
36 _pProgressBar->setProgress(0);
37 progressBarDisplay = true;
38 }
39
40 for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
41 if (_pRenderMonitor && _pRenderMonitor->testBreak()) {
42 break;
43 }
44 wxs = dynamic_cast<WXShape *>(*it);
45#if 0
46 wxs->bbox(Min, Max);
47 _bbox_diagonal = (Max - Min).norm();
48#endif
49 if (_changes) {
50 vector<WFace *> &wfaces = wxs->GetFaceList();
51 for (vector<WFace *>::iterator wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; ++wf)
52 {
53 WXFace *wxf = dynamic_cast<WXFace *>(*wf);
54 wxf->Clear();
55 }
57 }
58 else if (!(wxs)->getComputeViewIndependentFlag()) {
59 wxs->Reset();
61 }
62 else {
64 }
65 preProcessShape(wxs);
66 if (progressBarDisplay) {
67 _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
68 }
72 }
76 }
79 }
82 if (progressBarDisplay) {
83 _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
84 }
85
86 // build smooth edges:
88
89 // Post processing for suggestive contours
92 }
93 if (progressBarDisplay) {
94 _pProgressBar->setProgress(_pProgressBar->getProgress() + 1);
95 }
96
99 _changes = false;
100
101 // reset user data
102 (*it)->ResetUserData();
103 }
104}
105
106// GENERAL STUFF
109{
110 _meanK1 = 0;
111 _meanKr = 0;
112 _minK1 = FLT_MAX;
113 _maxK1 = -FLT_MAX;
114 _minKr = FLT_MAX;
115 _maxKr = -FLT_MAX;
116 _nPoints = 0;
117#if 0
118 _meanEdgeSize = iWShape->getMeanEdgeSize();
119#else
121#endif
122
123 vector<WFace *> &wfaces = iWShape->GetFaceList();
124 vector<WFace *>::iterator f, fend;
125 // view dependent stuff
126 for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
127 preProcessFace((WXFace *)(*f));
128 }
129
131 vector<WVertex *> &wvertices = iWShape->getVertexList();
132 for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
133 ++wv)
134 {
135 // Compute curvatures
136 WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
138 }
139 _meanK1 /= (real)(_nPoints);
140 _meanKr /= (real)(_nPoints);
141 }
142}
143
145{
146 Vec3f firstPoint = iFace->GetVertex(0)->GetVertex();
147 Vec3f N = iFace->GetNormal();
148
149 // Compute the dot product between V (=_Viewpoint - firstPoint) and N:
150 Vec3f V;
152 V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - firstPoint.z());
153 }
154 else {
155 V = Vec3f(_Viewpoint - firstPoint);
156 }
157 N.normalize();
158 V.normalize();
159 iFace->setDotP(N * V);
160
161 // compute the distance between the face center and the viewpoint:
163 iFace->setZ(iFace->center().z() - _Viewpoint.z());
164 }
165 else {
166 Vec3f dist_vec(iFace->center() - _Viewpoint);
167 iFace->setZ(dist_vec.norm());
168 }
169}
170
172{
173 /* TODO: for some reason, the 'vertex' may have no associated edges.
174 * (i.e., WVertex::_EdgeList is empty), which causes a crash due to
175 * a subsequent call of `WVertex::_EdgeList.front()`. */
176 if (vertex->GetEdges().empty()) {
177 if (G.debug & G_DEBUG_FREESTYLE) {
178 printf("Warning: WVertex %d has no associated edges.\n", vertex->GetId());
179 }
180 return;
181 }
182
183 // CURVATURE LAYER
184 // store all the curvature data for each vertex
185
186 // soc unused - real K1, K2
187 real cos2theta, sin2theta;
188 Vec3r e1, n, v;
189 // one vertex curvature info :
190 CurvatureInfo *C;
191 float radius = _sphereRadius * _meanEdgeSize;
192
193 // view independent stuff
195 C = new CurvatureInfo();
196 vertex->setCurvatures(C);
197 OGF::NormalCycle ncycle;
198 ncycle.begin();
199 if (radius > 0) {
200 OGF::compute_curvature_tensor(vertex, radius, ncycle);
201 }
202 else {
204 }
205 ncycle.end();
206 C->K1 = ncycle.kmin();
207 C->K2 = ncycle.kmax();
208 C->e1 = ncycle.Kmax(); // ncycle.kmin() * ncycle.Kmax();
209 C->e2 = ncycle.Kmin(); // ncycle.kmax() * ncycle.Kmin();
210
211 real absK1 = fabs(C->K1);
212 _meanK1 += absK1;
213 if (absK1 > _maxK1) {
214 _maxK1 = absK1;
215 }
216 if (absK1 < _minK1) {
217 _minK1 = absK1;
218 }
219 }
220 // view dependent
221 C = vertex->curvatures();
222 if (C == nullptr) {
223 return;
224 }
225
226 // compute radial curvature :
227 n = C->e1 ^ C->e2;
229 v = Vec3r(0.0, 0.0, _Viewpoint.z() - vertex->GetVertex().z());
230 }
231 else {
232 v = Vec3r(_Viewpoint - vertex->GetVertex());
233 }
234 C->er = v - (v * n) * n;
235 C->er.normalize();
236 e1 = C->e1;
237 e1.normalize();
238 cos2theta = C->er * e1;
239 cos2theta *= cos2theta;
240 sin2theta = 1 - cos2theta;
241 C->Kr = C->K1 * cos2theta + C->K2 * sin2theta;
242 real absKr = fabs(C->Kr);
243 _meanKr += absKr;
244 if (absKr > _maxKr) {
245 _maxKr = absKr;
246 }
247 if (absKr < _minKr) {
248 _minKr = absKr;
249 }
250
251 ++_nPoints;
252}
253
254// SILHOUETTE
257{
258 // Make a first pass on every polygons in order to compute all their silhouette relative values:
259 vector<WFace *> &wfaces = iWShape->GetFaceList();
260 vector<WFace *>::iterator f, fend;
261 for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
263 }
264
265 // Make a pass on the edges to detect the silhouette edges that are not smooth
266 vector<WEdge *>::iterator we, weend;
267 vector<WEdge *> &wedges = iWShape->getEdgeList();
268 for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
270 }
271}
272
274{
275 // SILHOUETTE LAYER
276 Vec3f normal;
277 // Compute the dot products between View direction and N at each vertex of the face:
278 Vec3f point;
279 int closestPointId = 0;
280 float dist, minDist = FLT_MAX;
281 int numVertices = iFace->numberOfVertices();
282 WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SILHOUETTE, true);
283 for (int i = 0; i < numVertices; i++) {
284 point = iFace->GetVertex(i)->GetVertex();
285 normal = iFace->GetVertexNormal(i);
286 normal.normalize();
287 Vec3f V;
289 V = Vec3f(0.0f, 0.0f, _Viewpoint.z() - point.z());
290 }
291 else {
292 V = Vec3f(_Viewpoint - point);
293 }
294 V.normalize();
295 float d = normal * V;
296 faceLayer->PushDotP(d);
297 // Find the point the closest to the viewpoint
299 dist = point.z() - _Viewpoint.z();
300 }
301 else {
302 Vec3f dist_vec(point - _Viewpoint);
303 dist = dist_vec.norm();
304 }
305 if (dist < minDist) {
306 minDist = dist;
307 closestPointId = i;
308 }
309 }
310 // Set the closest point id:
311 faceLayer->setClosestPointIndex(closestPointId);
312 // Add this layer to the face:
313 iFace->AddSmoothLayer(faceLayer);
314}
315
317{
318 if (iEdge->nature() & Nature::BORDER) {
319 return;
320 }
321 // SILHOUETTE ?
322 //-------------
323 WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
324 WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
325
326 /* fA->visible XOR fB->visible (true if one is 0 and the other is 1). */
327 if (fA->front() ^ fB->front()) {
328 // The only edges we want to set as silhouette edges in this way are the ones with 2 different
329 // normals for 1 vertex for these two faces
330 //--------------------
331 // In reality we only test the normals for 1 of the 2 vertices.
332 if (fA->GetVertexNormal(iEdge->GetaVertex()) == fB->GetVertexNormal(iEdge->GetaVertex())) {
333 return;
334 }
336 if (fB->front()) {
337 iEdge->setOrder(1);
338 }
339 else {
340 iEdge->setOrder(-1);
341 }
342 }
343}
344
345// BORDER
348{
350 return;
351 }
352 // Make a pass on the edges to detect the BORDER
353 vector<WEdge *>::iterator we, weend;
354 vector<WEdge *> &wedges = iWShape->getEdgeList();
355 for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
356 ProcessBorderEdge((WXEdge *)(*we));
357 }
358}
359
361{
362 // first check whether it is a border edge: BORDER ?
363 //---------
364 if (iEdge->GetaFace() == nullptr) {
365 // it is a border edge
367 }
368}
369
370// CREASE
373{
375 return;
376 }
377
378 // Make a pass on the edges to detect the CREASE
379 vector<WEdge *>::iterator we, weend;
380 vector<WEdge *> &wedges = iWShape->getEdgeList();
381 for (we = wedges.begin(), weend = wedges.end(); we != weend; ++we) {
382 ProcessCreaseEdge((WXEdge *)(*we));
383 }
384}
385
387{
388 // CREASE ?
389 //---------
390 if (iEdge->nature() & Nature::BORDER) {
391 return;
392 }
393 WXFace *fA = (WXFace *)iEdge->GetaOEdge()->GetaFace();
394 WXFace *fB = (WXFace *)iEdge->GetaOEdge()->GetbFace();
395
396 WVertex *aVertex = iEdge->GetaVertex();
397 if ((fA->GetVertexNormal(aVertex) * fB->GetVertexNormal(aVertex)) <= _creaseAngle) {
399 }
400}
401
402// RIDGES AND VALLEYS
405{
406 // Don't forget to add the built layer to the face at the end of the ProcessFace:
407 // iFace->AddSmoothLayer(faceLayer);
408
410 return;
411 }
412
413 // Here the curvatures must already have been computed
414 vector<WFace *> &wfaces = iWShape->GetFaceList();
415 vector<WFace *>::iterator f, fend;
416 for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
417 ProcessRidgeFace((WXFace *)(*f));
418 }
419}
420
421// RIDGES
424{
425 WXFaceLayer *flayer = new WXFaceLayer(iFace, Nature::RIDGE | Nature::VALLEY, false);
426 iFace->AddSmoothLayer(flayer);
427
429 for (uint i = 0; i < numVertices; ++i) {
430 WVertex *wv = iFace->GetVertex(i);
431 WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
432 flayer->PushDotP(wxv->curvatures()->K1);
433 }
434
435#if 0 // XXX fabs(flayer->dotP(i)) < threshold cannot be true
436 real threshold = 0;
437 // real threshold = _maxK1 - (_maxK1 - _meanK1) / 20.0;
438
439 if (flayer->nPosDotP() != numVertices) {
440 if ((fabs(flayer->dotP(0)) < threshold) && (fabs(flayer->dotP(1)) < threshold) &&
441 (fabs(flayer->dotP(2)) < threshold))
442 {
443 flayer->ReplaceDotP(0, 0);
444 flayer->ReplaceDotP(1, 0);
445 flayer->ReplaceDotP(2, 0);
446 }
447 }
448#endif
449}
450
451#if 0
453{
454 // RIDGE LAYER
455 // Compute the RidgeFunction, that is the derivative of the ppal curvature along e1 at each
456 // vertex of the face
457 WVertex *v;
458 Vec3r v1v2;
459 real t;
460 vector<WXFaceLayer *> SmoothLayers;
461 WXFaceLayer *faceLayer;
462 Face_Curvature_Info *layer_info;
463 real K1_a(0), K1_b(0);
464 Vec3r Inter_a, Inter_b;
465
466 // find the ridge layer of the face
467 iFace->retrieveSmoothLayers(Nature::RIDGE, SmoothLayers);
468 if (SmoothLayers.size() != 1) {
469 return;
470 }
471 faceLayer = SmoothLayers[0];
472 // retrieve the curvature info of this layer
473 layer_info = (Face_Curvature_Info *)faceLayer->userdata;
474
475 int numVertices = iFace->numberOfVertices();
476 for (int i = 0; i < numVertices; i++) {
477 v = iFace->GetVertex(i);
478 // vec_curvature_info[i] contains the curvature info of this vertex
479 Vec3r e2 = layer_info->vec_curvature_info[i]->K2 * layer_info->vec_curvature_info[i]->e2;
480 Vec3r e1 = layer_info->vec_curvature_info[i]->K1 * layer_info->vec_curvature_info[i]->e1;
481 e2.normalize();
482
483 WVertex::face_iterator fit = v->faces_begin();
484 WVertex::face_iterator fitend = v->faces_end();
485 for (; fit != fitend; ++fit) {
486 WXFace *wxf = dynamic_cast<WXFace *>(*fit);
487 WOEdge *oppositeEdge;
488 if (!(wxf->getOppositeEdge(v, oppositeEdge))) {
489 continue;
490 }
491 v1v2 = oppositeEdge->GetbVertex()->GetVertex() - oppositeEdge->GetaVertex()->GetVertex();
494 oppositeEdge->GetaVertex()->GetVertex(), v1v2, e2, -(v->GetVertex() * e2), t, 1.0e-06);
495 if ((res == GeomUtils::DO_INTERSECT) && (t >= 0.0) && (t <= 1.0)) {
496 vector<WXFaceLayer *> second_ridge_layer;
497 wxf->retrieveSmoothLayers(Nature::RIDGE, second_ridge_layer);
498 if (second_ridge_layer.size() != 1) {
499 continue;
500 }
501 Face_Curvature_Info *second_layer_info =
502 (Face_Curvature_Info *)second_ridge_layer[0]->userdata;
503
504 uint index1 = wxf->GetIndex(oppositeEdge->GetaVertex());
505 uint index2 = wxf->GetIndex(oppositeEdge->GetbVertex());
506 real K1_1 = second_layer_info->vec_curvature_info[index1]->K1;
507 real K1_2 = second_layer_info->vec_curvature_info[index2]->K1;
508 real K1 = (1.0 - t) * K1_1 + t * K1_2;
509 Vec3r inter((1.0 - t) * oppositeEdge->GetaVertex()->GetVertex() +
510 t * oppositeEdge->GetbVertex()->GetVertex());
511 Vec3r vtmp(inter - v->GetVertex());
512 // is it K1_a or K1_b ?
513 if (vtmp * e1 > 0) {
514 K1_b = K1;
515 Inter_b = inter;
516 }
517 else {
518 K1_a = K1;
519 Inter_a = inter;
520 }
521 }
522 }
523 // Once we have K1 along the ppal direction compute the derivative : K1b - K1a put it in DotP
524 // real d = fabs(K1_b) - fabs(K1_a);
525 real d = 0;
526 real threshold = _meanK1 + (_maxK1 - _meanK1) / 7.0;
527 // real threshold = _meanK1;
528 // if ((fabs(K1_b) > threshold) || ((fabs(K1_a) > threshold)))
529 d = (K1_b) - (K1_a) / (Inter_b - Inter_a).norm();
530 faceLayer->PushDotP(d);
531 // faceLayer->PushDotP(layer_info->vec_curvature_info[i]->K1);
532 }
533
534 // Make the values relevant by checking whether all principal directions have the "same"
535 // direction:
536 Vec3r e0((layer_info->vec_curvature_info[0]->K1 * layer_info->vec_curvature_info[0]->e1));
537 e0.normalize();
538 Vec3r e1((layer_info->vec_curvature_info[1]->K1 * layer_info->vec_curvature_info[1]->e1));
539 e1.normalize();
540 Vec3r e2((layer_info->vec_curvature_info[2]->K1 * layer_info->vec_curvature_info[2]->e1));
541 e2.normalize();
542 if (e0 * e1 < 0) {
543 // invert dotP[1]
544 faceLayer->ReplaceDotP(1, -faceLayer->dotP(1));
545 }
546 if (e0 * e2 < 0) {
547 // invert dotP[2]
548 faceLayer->ReplaceDotP(2, -faceLayer->dotP(2));
549 }
550
551# if 0 // remove the weakest values;
552 real minDiff = (_maxK1 - _minK1) / 10.0;
553 real minDiff = _meanK1;
554 if ((faceLayer->dotP(0) < minDiff) && (faceLayer->dotP(1) < minDiff) &&
555 (faceLayer->dotP(2) < minDiff))
556 {
557 faceLayer->ReplaceDotP(0, 0);
558 faceLayer->ReplaceDotP(1, 0);
559 faceLayer->ReplaceDotP(2, 0);
560 }
561# endif
562}
563#endif
564
565// SUGGESTIVE CONTOURS
567
569{
570 // Here the curvatures must already have been computed
571 vector<WFace *> &wfaces = iWShape->GetFaceList();
572 vector<WFace *>::iterator f, fend;
573 for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
575 }
576}
577
579{
580 WXFaceLayer *faceLayer = new WXFaceLayer(iFace, Nature::SUGGESTIVE_CONTOUR, true);
581 iFace->AddSmoothLayer(faceLayer);
582
584 for (uint i = 0; i < numVertices; ++i) {
585 WVertex *wv = iFace->GetVertex(i);
586 WXVertex *wxv = dynamic_cast<WXVertex *>(wv);
587 faceLayer->PushDotP(wxv->curvatures()->Kr);
588 }
589
590#if 0 // FIXME: find a more clever way to compute the threshold
591 real threshold = _meanKr;
592 if (faceLayer->nPosDotP() != numVertices) {
593 if ((fabs(faceLayer->dotP(0)) < threshold) && (fabs(faceLayer->dotP(1)) < threshold) &&
594 (fabs(faceLayer->dotP(2)) < threshold))
595 {
596 faceLayer->ReplaceDotP(0, 0);
597 faceLayer->ReplaceDotP(1, 0);
598 faceLayer->ReplaceDotP(2, 0);
599 }
600 }
601#endif
602}
603
605{
606 vector<WFace *> &wfaces = iShape->GetFaceList();
607 vector<WFace *>::iterator f, fend;
608 for (f = wfaces.begin(), fend = wfaces.end(); f != fend; ++f) {
610 }
611}
612
614{
615 // Compute the derivative of the radial curvature in the radial direction, at the two extremities
616 // of the smooth edge.
617 // If the derivative is smaller than a given threshold _kr_derivative_epsilon, discard the edge.
618
619 // Find the suggestive contour layer of the face (zero or one edge).
620 vector<WXFaceLayer *> sc_layers;
622 if (sc_layers.empty()) {
623 return;
624 }
625
626 WXFaceLayer *sc_layer;
627 sc_layer = sc_layers[0];
628
629 // Compute the derivative value at each vertex of the face, and add it in a vector.
630 vector<real> kr_derivatives;
631
632 uint vertices_nb = iFace->numberOfVertices();
633 WXVertex *v, *opposite_vertex_a, *opposite_vertex_b;
634 WXFace *wxf;
635 WOEdge *opposite_edge;
636 Vec3r normal_vec, radial_normal_vec, er_vec, v_vec, inter, inter1, inter2, tmp_vec;
638 real kr(0), kr1(0), kr2(0), t;
639
640 for (uint i = 0; i < vertices_nb; ++i) {
641 v = (WXVertex *)iFace->GetVertex(i);
642
643 // v is a singular vertex, skip it.
644 if (v->isBoundary()) {
645 kr_derivatives.push_back(0);
646 continue;
647 }
648
649 v_vec = v->GetVertex();
650 er_vec = v->curvatures()->er;
651
652 // For each vertex, iterate on its adjacent faces.
653 for (WVertex::face_iterator fit = v->faces_begin(), fitend = v->faces_end(); fit != fitend;
654 ++fit)
655 {
656 wxf = dynamic_cast<WXFace *>(*fit);
657 if (!wxf->getOppositeEdge(v, opposite_edge)) {
658 continue;
659 }
660
661 opposite_vertex_a = (WXVertex *)opposite_edge->GetaVertex();
662 opposite_vertex_b = (WXVertex *)opposite_edge->GetbVertex();
663 normal_vec = wxf->GetVertexNormal(v); // FIXME: what about e1 ^ e2 ?
664 radial_normal_vec = er_vec ^ normal_vec;
665
666 // Test whether the radial plan intersects with the edge at the opposite of v.
667 res = GeomUtils::intersectRayPlane(opposite_vertex_a->GetVertex(),
668 opposite_edge->GetVec(),
669 radial_normal_vec,
670 -(v_vec * radial_normal_vec),
671 t,
672 1.0e-06);
673
674 // If there is an intersection, compute the value of the derivative ath that point.
675 if ((res == GeomUtils::DO_INTERSECT) && (t >= 0) && (t <= 1)) {
676 kr = t * opposite_vertex_a->curvatures()->Kr +
677 (1 - t) * opposite_vertex_b->curvatures()->Kr;
678 inter = opposite_vertex_a->GetVertex() + t * opposite_edge->GetVec();
679 tmp_vec = inter - v->GetVertex();
680 // Is it kr1 or kr2?
681 if (tmp_vec * er_vec > 0) {
682 kr2 = kr;
683 inter2 = inter;
684 }
685 else {
686 kr1 = kr;
687 inter1 = inter;
688 }
689 }
690 }
691
692 // Now we have kr1 and kr2 along the radial direction, for one vertex of iFace.
693 // We have to compute the derivative of kr for that vertex, equal to:
694 // (kr2 - kr1) / dist(inter1, inter2).
695 // Then we add it to the vector of derivatives.
696 v->curvatures()->dKr = (kr2 - kr1) / (inter2 - inter1).norm();
697 kr_derivatives.push_back(v->curvatures()->dKr);
698 }
699
700 // At that point, we have the derivatives for each vertex of iFace.
701 // All we have to do now is to use linear interpolation to compute the values at the extremities
702 // of the smooth edge.
703 WXSmoothEdge *sc_edge = sc_layer->getSmoothEdge();
704 WOEdge *sc_oedge = sc_edge->woea();
705 t = sc_edge->ta();
706 if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
707 (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
709 {
710 sc_layer->removeSmoothEdge();
711 return;
712 }
713 sc_oedge = sc_edge->woeb();
714 t = sc_edge->tb();
715 if (t * kr_derivatives[iFace->GetIndex(sc_oedge->GetaVertex())] +
716 (1 - t) * kr_derivatives[iFace->GetIndex(sc_oedge->GetbVertex())] <
718 {
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 {
782 if ((*wxfl)->BuildSmoothEdge()) {
783 hasSmoothEdges = true;
784 }
785 }
786 }
787
788 if (hasSmoothEdges && !_computeRidgesAndValleys && !_computeSuggestiveContours) {
789 vector<WVertex *> &wvertices = iShape->getVertexList();
790 for (vector<WVertex *>::iterator wv = wvertices.begin(), wvend = wvertices.end(); wv != wvend;
791 ++wv)
792 {
793 // Compute curvatures
794 WXVertex *wxv = dynamic_cast<WXVertex *>(*wv);
796 }
797 _meanK1 /= (real)(_nPoints);
798 _meanKr /= (real)(_nPoints);
799 }
800}
801
802} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
unsigned int uint
Detects/flags/builds extended features edges on the WXEdge structure.
Various tools for geometry.
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:95
const Vec3r & Kmin() const
const Vec3r & Kmax() const
value_type z() const
Definition VecMat.h:509
Vec< T, N > & normalize()
Definition VecMat.h:102
value_type norm() const
Definition VecMat.h:92
WVertex * GetaVertex()
Definition WEdge.h:591
WFace * GetaFace()
Definition WEdge.h:601
bool GetMark()
Definition WEdge.h:581
WOEdge * GetaOEdge()
Definition WEdge.h:566
WFace * GetbFace()
Definition WEdge.h:606
Vec3f & GetNormal()
Definition WEdge.h:714
int numberOfVertices() const
Definition WEdge.h:874
bool getOppositeEdge(const WVertex *v, WOEdge *&e)
Definition WEdge.cpp:380
Vec3f & GetVertexNormal(int index)
Definition WEdge.h:814
uint frs_materialIndex() const
Definition WEdge.h:724
WVertex * GetVertex(uint index)
Definition WEdge.h:737
int GetIndex(WVertex *iVertex)
Definition WEdge.h:750
WFace * GetaFace()
Definition WEdge.h:389
WVertex * GetaVertex()
Definition WEdge.h:379
WFace * GetbFace()
Definition WEdge.h:394
const Vec3f & GetVec()
Definition WEdge.h:404
WVertex * GetbVertex()
Definition WEdge.h:384
vector< WVertex * > & getVertexList()
Definition WEdge.h:1039
real ComputeMeanEdgeSize() const
Definition WEdge.cpp:714
vector< WEdge * > & getEdgeList()
Definition WEdge.h:1034
vector< WFace * > & GetFaceList()
Definition WEdge.h:1044
vector< WEdge * > & GetEdges()
Definition WEdge.h:76
Vec3f & GetVertex()
Definition WEdge.h:71
WXNature nature()
Definition WXEdge.h:145
void setOrder(int i)
Definition WXEdge.h:176
void AddNature(WXNature iNature)
Definition WXEdge.h:171
void setClosestPointIndex(int iIndex)
Definition WXEdge.h:402
uint nPosDotP() const
Definition WXEdge.h:359
void ReplaceDotP(uint index, float newDotP)
Definition WXEdge.h:449
WXSmoothEdge * getSmoothEdge()
Definition WXEdge.h:392
void PushDotP(float iDotP)
Definition WXEdge.h:438
float dotP(int i) const
Definition WXEdge.h:354
void setDotP(float iDotP)
Definition WXEdge.h:625
void retrieveSmoothLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothLayers)
Definition WXEdge.h:595
void retrieveSmoothEdgesLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothEdgesLayers)
Definition WXEdge.h:583
void AddSmoothLayer(WXFaceLayer *iLayer)
Definition WXEdge.h:636
void setZ(float z)
Definition WXEdge.h:615
Vec3f & center()
Definition WXEdge.h:531
virtual void Reset()
Definition WXEdge.h:775
void setComputeViewIndependentFlag(bool iFlag)
Definition WXEdge.h:727
float ta() const
Definition WXEdge.h:239
float tb() const
Definition WXEdge.h:244
void setCurvatures(CurvatureInfo *ci)
Definition WXEdge.h:67
CurvatureInfo * curvatures()
Definition WXEdge.h:74
vector< WShape * > & getWShapes()
Definition WEdge.h:1311
#define printf(...)
ccl_device_inline float2 fabs(const float2 a)
#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)
VecMat::Vec3< float > Vec3f
Definition Geom.h:28
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
static const EdgeNature BORDER
Definition Nature.h:42
static const EdgeNature MATERIAL_BOUNDARY
Definition Nature.h:52
static const EdgeNature EDGE_MARK
Definition Nature.h:54
static const EdgeNature VALLEY
Definition Nature.h:48
static const EdgeNature CREASE
Definition Nature.h:44
static const EdgeNature RIDGE
Definition Nature.h:46
static const EdgeNature SILHOUETTE
Definition Nature.h:40
static const EdgeNature SUGGESTIVE_CONTOUR
Definition Nature.h:50
void compute_curvature_tensor(WVertex *start, real radius, NormalCycle &nc)
void compute_curvature_tensor_one_ring(WVertex *start, NormalCycle &nc)
inherits from class Rep
Definition AppCanvas.cpp:20
double real
Definition Precision.h:14
#define FLT_MAX
Definition stdcycles.h:14
i
Definition text_draw.cc:230
CCL_NAMESPACE_BEGIN struct Window V