Blender V4.3
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
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) {
34 _pProgressBar->setLabelText("Detecting feature lines");
35 _pProgressBar->setTotalSteps(wshapes.size() * 3);
37 progressBarDisplay = true;
38 }
39
40 for (vector<WShape *>::const_iterator it = wshapes.begin(); it != wshapes.end(); it++) {
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) {
68 }
72 }
76 }
79 }
82 if (progressBarDisplay) {
84 }
85
86 // build smooth edges:
88
89 // Post processing for suggestive contours
92 }
93 if (progressBarDisplay) {
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 :
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.
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 Gabor Generate Gabor noise Gradient Generate interpolated color and intensity values based on the input vector Magic Generate a psychedelic color texture 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:29
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:99
const Vec3r & Kmin() const
const Vec3r & Kmax() const
virtual void setLabelText(const string &s)
Definition ProgressBar.h:48
virtual void reset()
Definition ProgressBar.h:32
virtual void setTotalSteps(uint n)
Definition ProgressBar.h:38
virtual void setProgress(uint i)
Definition ProgressBar.h:43
uint getProgress() const
Definition ProgressBar.h:59
value_type z() const
Definition VecMat.h:513
Vec< T, N > & normalize()
Definition VecMat.h:104
value_type norm() const
Definition VecMat.h:94
WVertex * GetaVertex()
Definition WEdge.h:601
WFace * GetaFace()
Definition WEdge.h:611
bool GetMark()
Definition WEdge.h:591
WOEdge * GetaOEdge()
Definition WEdge.h:576
WFace * GetbFace()
Definition WEdge.h:616
Vec3f & GetNormal()
Definition WEdge.h:726
int numberOfVertices() const
Definition WEdge.h:886
bool getOppositeEdge(const WVertex *v, WOEdge *&e)
Definition WEdge.cpp:380
Vec3f & GetVertexNormal(int index)
Definition WEdge.h:826
uint frs_materialIndex() const
Definition WEdge.h:736
WVertex * GetVertex(uint index)
Definition WEdge.h:749
int GetIndex(WVertex *iVertex)
Definition WEdge.h:762
WFace * GetaFace()
Definition WEdge.h:397
WVertex * GetaVertex()
Definition WEdge.h:387
WFace * GetbFace()
Definition WEdge.h:402
const Vec3f & GetVec()
Definition WEdge.h:412
WVertex * GetbVertex()
Definition WEdge.h:392
vector< WVertex * > & getVertexList()
Definition WEdge.h:1053
real ComputeMeanEdgeSize() const
Definition WEdge.cpp:714
vector< WEdge * > & getEdgeList()
Definition WEdge.h:1048
vector< WFace * > & GetFaceList()
Definition WEdge.h:1058
Vec3f & GetVertex()
Definition WEdge.h:73
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:362
void setClosestPointIndex(int iIndex)
Definition WXEdge.h:410
uint nPosDotP() const
Definition WXEdge.h:367
void ReplaceDotP(uint index, float newDotP)
Definition WXEdge.h:457
WXSmoothEdge * getSmoothEdge()
Definition WXEdge.h:400
void PushDotP(float iDotP)
Definition WXEdge.h:446
void setDotP(float iDotP)
Definition WXEdge.h:635
void retrieveSmoothLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothLayers)
Definition WXEdge.h:605
void retrieveSmoothEdgesLayers(WXNature iNature, vector< WXFaceLayer * > &oSmoothEdgesLayers)
Definition WXEdge.h:593
void AddSmoothLayer(WXFaceLayer *iLayer)
Definition WXEdge.h:646
void setZ(float z)
Definition WXEdge.h:625
Vec3f & center()
Definition WXEdge.h:541
virtual void Reset()
Definition WXEdge.h:787
void setComputeViewIndependentFlag(bool iFlag)
Definition WXEdge.h:739
float ta() const
Definition WXEdge.h:245
float tb() const
Definition WXEdge.h:250
CurvatureInfo * curvatures()
Definition WXEdge.h:76
vector< WShape * > & getWShapes()
Definition WEdge.h:1327
#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
CCL_NAMESPACE_BEGIN struct Window V