Blender V4.3
Stroke.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 "Stroke.h"
12#include "StrokeIterators.h"
13#include "StrokeRenderer.h"
14
15#include "BKE_global.hh"
16#include "BKE_node.hh"
17
18namespace Freestyle {
19
20/**********************************/
21/* */
22/* */
23/* StrokeAttribute */
24/* */
25/* */
26/**********************************/
27
29{
30 int i;
31 _alpha = 1.0f;
32 _thickness[0] = 1.0f;
33 _thickness[1] = 1.0f;
34 for (i = 0; i < 3; ++i) {
35 _color[i] = 0.2f;
36 }
37 _color[0] = 0.8f;
38 _userAttributesReal = nullptr;
39 _userAttributesVec2f = nullptr;
40 _userAttributesVec3f = nullptr;
41 _visible = true;
42}
43
45{
46 _alpha = iBrother._alpha;
47 _thickness[0] = iBrother._thickness[0];
48 _thickness[1] = iBrother._thickness[1];
49 for (int i = 0; i < 3; ++i) {
50 _color[i] = iBrother._color[i];
51 }
52 _visible = iBrother._visible;
53 if (iBrother._userAttributesReal) {
54 _userAttributesReal = new realMap(*iBrother._userAttributesReal);
55 }
56 else {
57 _userAttributesReal = nullptr;
58 }
59 if (iBrother._userAttributesVec2f) {
60 _userAttributesVec2f = new Vec2fMap(*iBrother._userAttributesVec2f);
61 }
62 else {
63 _userAttributesVec2f = nullptr;
64 }
65 if (iBrother._userAttributesVec3f) {
66 _userAttributesVec3f = new Vec3fMap(*iBrother._userAttributesVec3f);
67 }
68 else {
69 _userAttributesVec3f = nullptr;
70 }
71}
72
74 float iGColor,
75 float iBColor,
76 float iAlpha,
77 float iRThickness,
78 float iLThickness)
79{
80 _color[0] = iRColor;
81 _color[1] = iGColor;
82 _color[2] = iBColor;
83
84 _alpha = iAlpha;
85
86 _thickness[0] = iRThickness;
87 _thickness[1] = iLThickness;
88
89 _visible = true;
90
91 _userAttributesReal = nullptr;
92 _userAttributesVec2f = nullptr;
93 _userAttributesVec3f = nullptr;
94}
95
97{
98 _alpha = (1 - t) * a1._alpha + t * a2._alpha;
99 _thickness[0] = (1 - t) * a1._thickness[0] + t * a2._thickness[0];
100 _thickness[1] = (1 - t) * a1._thickness[1] + t * a2._thickness[1];
101 for (int i = 0; i < 3; ++i) {
102 _color[i] = (1 - t) * a1._color[i] + t * a2._color[i];
103 }
104
105 _visible = a1.isVisible();
106
107 // FIXME: to be checked (and enhanced)
108 if ((a1._userAttributesReal) && (a2._userAttributesReal)) {
109 if (a1._userAttributesReal->size() == a2._userAttributesReal->size()) {
110 _userAttributesReal = new realMap;
111 realMap::iterator it1 = a1._userAttributesReal->begin(),
112 it1end = a1._userAttributesReal->end();
113 realMap::iterator it2 = a2._userAttributesReal->begin();
114 for (; it1 != it1end; ++it1, ++it2) {
115 (*_userAttributesReal)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
116 }
117 }
118 }
119 else {
120 _userAttributesReal = nullptr;
121 }
122 if ((a1._userAttributesVec2f) && (a2._userAttributesVec2f)) {
123 if (a1._userAttributesVec2f->size() == a2._userAttributesVec2f->size()) {
124 _userAttributesVec2f = new Vec2fMap;
125 Vec2fMap::iterator it1 = a1._userAttributesVec2f->begin(),
126 it1end = a1._userAttributesVec2f->end();
127 Vec2fMap::iterator it2 = a2._userAttributesVec2f->begin();
128 for (; it1 != it1end; ++it1, ++it2) {
129 (*_userAttributesVec2f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
130 }
131 }
132 }
133 else {
134 _userAttributesVec2f = nullptr;
135 }
136 if ((a1._userAttributesVec3f) && (a2._userAttributesVec3f)) {
137 if (a1._userAttributesVec3f->size() == a2._userAttributesVec3f->size()) {
138 _userAttributesVec3f = new Vec3fMap;
139 Vec3fMap::iterator it1 = a1._userAttributesVec3f->begin(),
140 it1end = a1._userAttributesVec3f->end();
141 Vec3fMap::iterator it2 = a2._userAttributesVec3f->begin();
142 for (; it1 != it1end; ++it1, ++it2) {
143 (*_userAttributesVec3f)[(*it1).first] = ((1 - t) * (*it1).second + t * (*it2).second);
144 }
145 }
146 }
147 else {
148 _userAttributesVec3f = nullptr;
149 }
150}
151
153{
154 if (_userAttributesReal) {
155 _userAttributesReal->clear();
156 delete _userAttributesReal;
157 }
158 if (_userAttributesVec2f) {
159 _userAttributesVec2f->clear();
160 delete _userAttributesVec2f;
161 }
162 if (_userAttributesVec3f) {
163 _userAttributesVec3f->clear();
164 delete _userAttributesVec3f;
165 }
166}
167
169{
170 int i;
171 _alpha = iBrother._alpha;
172 _thickness[0] = iBrother._thickness[0];
173 _thickness[1] = iBrother._thickness[1];
174 for (i = 0; i < 3; ++i) {
175 _color[i] = iBrother._color[i];
176 }
177 _visible = iBrother._visible;
178 if (iBrother._userAttributesReal) {
179 if (!_userAttributesReal) {
180 _userAttributesReal = new realMap;
181 }
182 _userAttributesReal = new realMap(*(iBrother._userAttributesReal));
183 }
184 else {
185 _userAttributesReal = nullptr;
186 }
187 if (iBrother._userAttributesVec2f) {
188 if (!_userAttributesVec2f) {
189 _userAttributesVec2f = new Vec2fMap;
190 }
191 _userAttributesVec2f = new Vec2fMap(*(iBrother._userAttributesVec2f));
192 }
193 else {
194 _userAttributesVec2f = nullptr;
195 }
196 if (iBrother._userAttributesVec3f) {
197 if (!_userAttributesVec3f) {
198 _userAttributesVec3f = new Vec3fMap;
199 }
200 _userAttributesVec3f = new Vec3fMap(*(iBrother._userAttributesVec3f));
201 }
202 else {
203 _userAttributesVec3f = nullptr;
204 }
205 return *this;
206}
207
208float StrokeAttribute::getAttributeReal(const char *iName) const
209{
210 if (!_userAttributesReal) {
211 if (G.debug & G_DEBUG_FREESTYLE) {
212 cout << "StrokeAttribute warning: no real attribute was defined" << endl;
213 }
214 return 0.0f;
215 }
216 realMap::iterator a = _userAttributesReal->find(iName);
217 if (a == _userAttributesReal->end()) {
218 if (G.debug & G_DEBUG_FREESTYLE) {
219 cout << "StrokeAttribute warning: no real attribute was added with the name " << iName
220 << endl;
221 }
222 return 0.0f;
223 }
224 return (*a).second;
225}
226
228{
229 if (!_userAttributesVec2f) {
230 if (G.debug & G_DEBUG_FREESTYLE) {
231 cout << "StrokeAttribute warning: no Vec2f attribute was defined" << endl;
232 }
233 return 0;
234 }
235 Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
236 if (a == _userAttributesVec2f->end()) {
237 if (G.debug & G_DEBUG_FREESTYLE) {
238 cout << "StrokeAttribute warning: no Vec2f attribute was added with the name " << iName
239 << endl;
240 }
241 return 0;
242 }
243 return (*a).second;
244}
245
247{
248 if (!_userAttributesVec3f) {
249 if (G.debug & G_DEBUG_FREESTYLE) {
250 cout << "StrokeAttribute warning: no Vec3f attribute was defined" << endl;
251 }
252 return 0;
253 }
254 Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
255 if (a == _userAttributesVec3f->end()) {
256 if (G.debug & G_DEBUG_FREESTYLE) {
257 cout << "StrokeAttribute warning: no Vec3f attribute was added with the name " << iName
258 << endl;
259 }
260 return 0;
261 }
262 return (*a).second;
263}
264
265bool StrokeAttribute::isAttributeAvailableReal(const char *iName) const
266{
267 if (!_userAttributesReal) {
268 return false;
269 }
270 realMap::iterator a = _userAttributesReal->find(iName);
271 if (a == _userAttributesReal->end()) {
272 return false;
273 }
274 return true;
275}
276
278{
279 if (!_userAttributesVec2f) {
280 return false;
281 }
282 Vec2fMap::iterator a = _userAttributesVec2f->find(iName);
283 if (a == _userAttributesVec2f->end()) {
284 return false;
285 }
286 return true;
287}
288
290{
291 if (!_userAttributesVec3f) {
292 return false;
293 }
294 Vec3fMap::iterator a = _userAttributesVec3f->find(iName);
295 if (a == _userAttributesVec3f->end()) {
296 return false;
297 }
298 return true;
299}
300
301void StrokeAttribute::setAttributeReal(const char *iName, float att)
302{
303 if (!_userAttributesReal) {
304 _userAttributesReal = new realMap;
305 }
306 (*_userAttributesReal)[iName] = att;
307}
308
309void StrokeAttribute::setAttributeVec2f(const char *iName, const Vec2f &att)
310{
311 if (!_userAttributesVec2f) {
312 _userAttributesVec2f = new Vec2fMap;
313 }
314 (*_userAttributesVec2f)[iName] = att;
315}
316
317void StrokeAttribute::setAttributeVec3f(const char *iName, const Vec3f &att)
318{
319 if (!_userAttributesVec3f) {
320 _userAttributesVec3f = new Vec3fMap;
321 }
322 (*_userAttributesVec3f)[iName] = att;
323}
324
325/**********************************/
326/* */
327/* */
328/* StrokeVertex */
329/* */
330/* */
331/**********************************/
332
334{
335 _CurvilignAbscissa = 0.0f;
336 _StrokeLength = 0.0f;
337}
338
340{
341 _Attribute = iBrother._Attribute;
342 _CurvilignAbscissa = 0.0f;
343 _StrokeLength = 0.0f;
344}
345
346StrokeVertex::StrokeVertex(SVertex *iSVertex) : CurvePoint(iSVertex, nullptr, 0.0f)
347{
348 _CurvilignAbscissa = 0.0f;
349 _StrokeLength = 0.0f;
350}
351
353{
354 _CurvilignAbscissa = 0.0f;
355 _StrokeLength = 0.0f;
356}
357
359{
360 // interpolate attributes:
361 _Attribute = StrokeAttribute(iA->attribute(), iB->attribute(), t3);
362 _CurvilignAbscissa = (1 - t3) * iA->curvilinearAbscissa() + t3 * iB->curvilinearAbscissa();
363 _StrokeLength = iA->strokeLength();
364}
365
367 : CurvePoint(iSVertex, nullptr, 0.0f)
368{
369 _Attribute = iAttribute;
370 _CurvilignAbscissa = 0.0f;
371 _StrokeLength = 0.0f;
372}
373
375{
376 ((CurvePoint *)this)->operator=(iBrother);
377 _Attribute = iBrother._Attribute;
378
379 _CurvilignAbscissa = 0.0f;
380
381 _StrokeLength = 0.0f;
382 return *this;
383}
384
385/**********************************/
386/* */
387/* */
388/* Stroke */
389/* */
390/* */
391/**********************************/
392
394{
395 _Length = 0;
396 _id = 0;
397 _sampling = FLT_MAX;
398 //_mediumType = DEFAULT_STROKE;
399 _mediumType = OPAQUE_MEDIUM;
400 _textureId = 0;
401 _textureStep = 1.0;
402 for (int a = 0; a < MAX_MTEX; a++) {
403 _mtex[a] = nullptr;
404 }
405 _nodeTree = nullptr;
406 _tips = false;
407 _rep = nullptr;
408}
409
410Stroke::Stroke(const Stroke &iBrother) : Interface1D(iBrother)
411{
412 for (vertex_container::const_iterator v = iBrother._Vertices.begin(),
413 vend = iBrother._Vertices.end();
414 v != vend;
415 v++)
416 {
417 _Vertices.push_back(*v);
418 }
419 _Length = 0;
420 _id = iBrother._id;
421 _ViewEdges = iBrother._ViewEdges;
422 _sampling = iBrother._sampling;
423 _mediumType = iBrother._mediumType;
424 _textureId = iBrother._textureId;
425 _textureStep = iBrother._textureStep;
426 for (int a = 0; a < MAX_MTEX; a++) {
427 _mtex[a] = iBrother._mtex[a];
428 }
429 _nodeTree = iBrother._nodeTree;
430 _tips = iBrother._tips;
431 if (iBrother._rep) {
432 _rep = new StrokeRep(*(iBrother._rep));
433 }
434 else {
435 _rep = nullptr;
436 }
437}
438
440{
441 if (!_Vertices.empty()) {
442 for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; v++)
443 {
444 delete (*v);
445 }
446 _Vertices.clear();
447 }
448
449 _ViewEdges.clear();
450 if (_rep) {
451 delete _rep;
452 _rep = nullptr;
453 }
454}
455
457{
458 if (!_Vertices.empty()) {
459 _Vertices.clear();
460 }
461
462 for (vertex_container::const_iterator v = iBrother._Vertices.begin(),
463 vend = iBrother._Vertices.end();
464 v != vend;
465 v++)
466 {
467 _Vertices.push_back(*v);
468 }
469 _Length = iBrother._Length;
470 _id = iBrother._id;
471 _ViewEdges = iBrother._ViewEdges;
472 _sampling = iBrother._sampling;
473 delete _rep;
474 if (iBrother._rep) {
475 _rep = new StrokeRep(*(iBrother._rep));
476 }
477 else {
478 _rep = nullptr;
479 }
480 return *this;
481}
482
483void Stroke::setLength(float iLength)
484{
485 _Length = iLength;
486 for (vertex_container::iterator v = _Vertices.begin(), vend = _Vertices.end(); v != vend; ++v) {
487 (*v)->setStrokeLength(iLength);
488 }
489}
490
491float Stroke::ComputeSampling(int iNVertices)
492{
493 if (iNVertices <= int(_Vertices.size())) { // soc
494 return _sampling;
495 }
496
497 float sampling = _Length / float(iNVertices - _Vertices.size() + 1);
498 return sampling;
499}
500
502 public:
505 float _length;
506 int _n;
509
512 float ilength,
513 int in,
514 float isampling)
515 {
516 _begin = ibegin;
517 _end = iend;
518 _length = ilength;
519 _n = in;
520 _sampling = isampling;
521 _resampled = false;
522 }
523};
524
525int Stroke::Resample(int iNPoints)
526{
527 int NPointsToAdd = iNPoints - strokeVerticesSize();
528 if (NPointsToAdd <= 0) {
529 return 0;
530 }
531
534 ++next;
536
537 vertex_container newVertices;
538 real t = 0.0f;
539 StrokeVertex *newVertex = nullptr;
540 vector<StrokeSegment> strokeSegments;
541 int N = 0;
542 float meanlength = 0;
543 int nsegments = 0;
544 while ((it != itend) && (next != itend)) {
545 Vec2r a((it)->getPoint());
546 Vec2r b((next)->getPoint());
547 Vec2r vec_tmp(b - a);
548 real norm_var = vec_tmp.norm();
549 int numberOfPointsToAdd = int(floor(NPointsToAdd * norm_var / _Length));
550 float csampling = norm_var / float(numberOfPointsToAdd + 1);
551 strokeSegments.emplace_back(it, next, norm_var, numberOfPointsToAdd, csampling);
552 N += numberOfPointsToAdd;
553 meanlength += norm_var;
554 ++nsegments;
555 ++it;
556 ++next;
557 }
558 meanlength /= float(nsegments);
559
560 // if we don't have enough points let's resample finer some segments
561 bool checkEveryone = false;
562 bool resampled;
563 while (N < NPointsToAdd) {
564 resampled = false;
565 for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end();
566 s != send;
567 ++s)
568 {
569 if (s->_sampling == 0.0f) {
570 continue;
571 }
572
573 if (s->_resampled == false) {
574 if ((!checkEveryone) && (s->_length < meanlength)) {
575 continue;
576 }
577 // resample
578 s->_n = s->_n + 1;
579 s->_sampling = s->_length / float(s->_n + 1);
580 s->_resampled = resampled = true;
581 N++;
582 if (N == NPointsToAdd) {
583 break;
584 }
585 }
586 }
587 if (checkEveryone && !resampled) {
588 break;
589 }
590 checkEveryone = true;
591 }
592 if (N < NPointsToAdd) {
593 // fatal error, likely because _Length is inconsistent with the stroke length computed with the
594 // vertices
595 return -1;
596 }
597 // actually resample:
598 for (vector<StrokeSegment>::iterator s = strokeSegments.begin(), send = strokeSegments.end();
599 s != send;
600 ++s)
601 {
602 newVertices.push_back(&*(s->_begin));
603 if (s->_sampling < _sampling) {
604 _sampling = s->_sampling;
605 }
606
607 t = s->_sampling / s->_length;
608 for (int i = 0; i < s->_n; ++i) {
609 newVertex = new StrokeVertex(&*(s->_begin), &*(s->_end), t);
610 newVertices.push_back(newVertex);
611 t += s->_sampling / s->_length;
612 }
613 it = s->_begin;
614 next = s->_end;
615 }
616
617 // add last:
618 ++it;
619 ++next;
620 if ((it != itend) && (next == itend) /* && (t == 0.0f) */) {
621 newVertices.push_back(&(*it));
622 }
623
624 int newsize = newVertices.size();
625 if (newsize != iNPoints) {
626 cerr << "Warning: incorrect points number" << endl;
627 }
628
629 _Vertices.clear();
630 _Vertices = newVertices;
631 newVertices.clear();
632
633 return 0;
634}
635
636int Stroke::Resample(float iSampling)
637{
638 // cerr << "old size :" << strokeVerticesSize() << endl;
639 if (iSampling == 0) {
640 return 0;
641 }
642 if (iSampling >= _sampling) {
643 return 0;
644 }
645
646 _sampling = iSampling;
647 // Resample...
648 // real curvilinearLength = 0.0f;
649 vertex_container newVertices;
650 real t = 0.0f;
651 const real limit = 0.99;
652 StrokeVertex *newVertex = nullptr;
655 ++next;
657 while ((it != itend) && (next != itend)) {
658 newVertices.push_back(&(*it));
659 Vec2r a((it)->getPoint());
660 Vec2r b((next)->getPoint());
661 Vec2r vec_tmp(b - a);
662 real norm_var = vec_tmp.norm();
663 if (norm_var <= _sampling) {
664 // curvilinearLength += norm_var;
665 ++it;
666 ++next;
667 continue;
668 }
669
670 // curvilinearLength += _sampling;
671 t = _sampling / norm_var;
672 while (t < limit) {
673 newVertex = new StrokeVertex(&(*it), &(*next), t);
674 // newVertex->setCurvilinearAbscissa(curvilinearLength);
675 newVertices.push_back(newVertex);
676 t = t + _sampling / norm_var;
677 }
678 ++it;
679 ++next;
680 }
681 // add last:
682 if ((it != itend) && (next == itend) /* && (t == 0.0f) */) {
683 newVertices.push_back(&(*it));
684 }
685
686 _Vertices.clear();
687 _Vertices = newVertices;
688 newVertices.clear();
689
690 return 0;
691}
692
694{
695 vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
696 for (; it != itend; ++it) {
697 delete (*it);
698 }
699 _Vertices.clear();
700 UpdateLength();
701}
702
704{
705 vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
706 for (; it != itend; ++it) {
707 if ((*it) == iVertex) {
708 delete iVertex;
709 it = _Vertices.erase(it); // it is now the element just after the erased element
710 break;
711 }
712 }
713 UpdateLength();
714}
715
717{
718 vertex_container::iterator itnext = next.getIt();
719 _Vertices.insert(itnext, iVertex);
720 UpdateLength();
721}
722
724{
725 // recompute curvilinear abscissa and stroke length
726 float curvabsc = 0.0f;
727 vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end();
728 vertex_container::iterator previous = it;
729 for (; it != itend; ++it) {
730 curvabsc += ((*it)->getPoint() - (*previous)->getPoint()).norm();
731 (*it)->setCurvilinearAbscissa(curvabsc);
732 previous = it;
733 }
734 _Length = curvabsc;
735 for (it = _Vertices.begin(); it != itend; ++it) {
736 (*it)->setStrokeLength(_Length);
737 }
738}
739
742{
743 return const_vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
744}
745
747{
748 return const_vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
749}
750
752{
753 return vertex_iterator(_Vertices.end(), _Vertices.begin(), _Vertices.end());
754}
755
757{
758 if ((t != 0) && (t < _sampling)) {
759 Resample(t);
760 }
762 this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end());
763}
764
766{
768 this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end());
769}
770
772{
774 this->_Vertices.begin(), this->_Vertices.begin(), this->_Vertices.end()));
775 return ret;
776}
777
779{
781 this->_Vertices.end(), this->_Vertices.begin(), this->_Vertices.end()));
782 return ret;
783}
784
786{
787 return verticesBegin(); // FIXME
788}
789
791{
792 return verticesEnd();
793}
794
795void Stroke::ScaleThickness(float iFactor)
796{
797 for (vertex_container::iterator it = _Vertices.begin(), itend = _Vertices.end(); it != itend;
798 ++it)
799 {
800 StrokeAttribute &attr = (*it)->attribute();
801 attr.setThickness(iFactor * attr.getThicknessR(), iFactor * attr.getThicknessL());
802 }
803}
804
805void Stroke::Render(const StrokeRenderer *iRenderer)
806{
807 if (!_rep) {
808 _rep = new StrokeRep(this);
809 }
810 iRenderer->RenderStrokeRep(_rep);
811}
812
814{
815 if (!_rep) {
816 _rep = new StrokeRep(this);
817 }
818 iRenderer->RenderStrokeRep(_rep);
819}
820
822{
823 // Resample if necessary
824 if ((sampling != 0) && (sampling < _sampling)) {
825 Resample(sampling);
826 }
827 return vertex_iterator(_Vertices.begin(), _Vertices.begin(), _Vertices.end());
828 // return _Vertices.begin();
829}
830
831#if 0
832Stroke::vertex_iterator Stroke::vertices_last()
833{
835 vertex_iterator next = res;
836 ++next;
837 while (!next.end()) {
838 ++next;
839 ++res;
840 }
841 return res;
842}
843
844Stroke::const_vertex_iterator Stroke::vertices_last() const
845{
848 ++next;
849 while (!next.end()) {
850 ++next;
851 ++res;
852 }
853 return res;
854}
855
856Stroke::vertex_container::reverse_iterator Stroke::vertices_last(float sampling)
857{
858 // Resample if necessary
859 if (sampling < _sampling) {
860 Resample(sampling);
861 }
862 return _Vertices.rbegin();
863}
864
865inline Vec3r shaded_color(int iCombination = 0) const;
866
867inline Vec<3, real> Stroke::orientation2d(const_vertex_iterator it) const
868{
869 return iterator_edge_orientation2d_function<Stroke, const_vertex_iterator>(this, it);
870}
871
872Vec3r Stroke::orientation2d(int iCombination) const
873{
874 return edge_orientation2d_function<Stroke>(*this, iCombination);
875}
876
877inline Vec3r Stroke::orientation3d(const_vertex_iterator it) const
878{
879 return iterator_edge_orientation3d_function<Stroke, const_vertex_iterator>(*this, it);
880}
881
882Vec3r Stroke::orientation3d(int iCombination) const
883{
884 return edge_orientation3d_function<Stroke>(*this, iCombination);
885}
886
887Material Stroke::material() const
888{
890 Material mat = (*v)->material();
891 for (; v != vend; ++v) {
892 if (mat != (*v)->material()) {
894 }
895 }
896 return mat;
897}
898
899int Stroke::qi() const
900{
902 int qi_ = (*v)->qi();
903 for (; v != vend; ++v) {
904 if ((*v)->qi() != qi_) {
906 }
907 }
908 return qi_;
909}
910
911inline occluder_container::const_iterator occluders_begin() const
912{
913 return _FEdgeA->occluders().begin();
914}
915
916inline occluder_container::const_iterator occluders_end() const
917{
918 return _FEdgeA->occluders().end();
919}
920
921int Stroke::occluders_size() const
922{
923 return qi();
924}
925
926bool Stroke::occluders_empty() const
927{
929 bool empty = (*v)->occluders_empty();
930 for (; v != vend; ++v) {
931 if ((*v)->occluders_empty() != empty) {
933 }
934 }
935 return empty;
936}
937
938# if 0
939inline const polygon3d &occludee() const
940{
941 return *(_FEdgeA->aFace());
942}
943# endif
944
945const SShape *Stroke::occluded_shape() const
946{
948 const SShape *sshape = (*v)->occluded_shape();
949 for (; v != vend; ++v) {
950 if ((*v)->occluded_shape() != sshape) {
952 }
953 }
954 return sshape;
955}
956
957const bool Stroke::occludee_empty() const
958{
960 bool empty = (*v)->occludee_empty();
961 for (; v != vend; ++v) {
962 if ((*v)->occludee_empty() != empty) {
964 }
965 }
966 return empty;
967}
968
969const SShape *Stroke::shape() const
970{
972 const SShape *sshape = (*v)->shape();
973 for (; v != vend; ++v) {
974 if ((*v)->shape() != sshape) {
976 }
977 }
978 return sshape;
979}
980
981real Stroke::z_discontinuity(int iCombination) const
982{
983 return z_discontinuity_edge_function<Stroke>(*this, iCombination);
984}
985
986Vec3r Stroke::curvature2d_as_vector(int iCombination) const
987{
988 return curvature2d_as_vector_edge_function<Stroke>(*this, iCombination);
989}
990
991real Stroke::curvature2d_as_angle(int iCombination) const
992{
993 return curvature2d_as_angle_edge_function<Stroke>(*this, iCombination);
994}
995
996float Stroke::shape_importance(int iCombination) const
997{
998 return shape_importance_edge_function<Stroke>(*this, iCombination);
999}
1000
1001float Stroke::local_average_depth(int iCombination) const
1002{
1003 return local_average_depth_edge_function<Stroke>(*this, iCombination);
1004}
1005
1006float Stroke::local_depth_variance(int iCombination) const
1007{
1008 return local_depth_variance_edge_function<Stroke>(*this, iCombination);
1009}
1010
1011real Stroke::local_average_density(float sigma, int iCombination) const
1012{
1013 return density_edge_function<Stroke>(*this, iCombination);
1014}
1015#endif
1016
1017} /* namespace Freestyle */
@ G_DEBUG_FREESTYLE
Iterators used to iterate over the elements of the Stroke. Can't be used in python.
Iterators used to iterate over the elements of the Stroke.
Classes to render a stroke with OpenGL.
Classes to define a stroke.
#define MAX_MTEX
Definition Stroke.h:33
ATTR_WARN_UNUSED_RESULT const BMVert * v
SIMD_FORCE_INLINE btScalar norm() const
Return the norm (length) of the vector.
Definition btVector3.h:263
static int raiseException(exception_type exception=UNDEFINED)
Definition Exception.h:32
bool isAttributeAvailableVec3f(const char *iName) const
Definition Stroke.cpp:289
void setThickness(float tr, float tl)
Definition Stroke.h:235
Vec3f getAttributeVec3f(const char *iName) const
Definition Stroke.cpp:246
void setAttributeReal(const char *iName, float att)
Definition Stroke.cpp:301
const float getThicknessR() const
Definition Stroke.h:142
void setAttributeVec3f(const char *iName, const Vec3f &att)
Definition Stroke.cpp:317
bool isVisible() const
Definition Stroke.h:161
const float getThicknessL() const
Definition Stroke.h:148
bool isAttributeAvailableVec2f(const char *iName) const
Definition Stroke.cpp:277
Vec2f getAttributeVec2f(const char *iName) const
Definition Stroke.cpp:227
void setAttributeVec2f(const char *iName, const Vec2f &att)
Definition Stroke.cpp:309
StrokeAttribute & operator=(const StrokeAttribute &iBrother)
Definition Stroke.cpp:168
bool isAttributeAvailableReal(const char *iName) const
Definition Stroke.cpp:265
float getAttributeReal(const char *iName) const
Definition Stroke.cpp:208
virtual void RenderStrokeRep(StrokeRep *iStrokeRep) const =0
StrokeInternal::StrokeVertexIterator _end
Definition Stroke.cpp:504
StrokeSegment(StrokeInternal::StrokeVertexIterator ibegin, StrokeInternal::StrokeVertexIterator iend, float ilength, int in, float isampling)
Definition Stroke.cpp:510
StrokeInternal::StrokeVertexIterator _begin
Definition Stroke.cpp:503
float curvilinearAbscissa() const
Definition Stroke.h:388
float strokeLength() const
Definition Stroke.h:394
const StrokeAttribute & attribute() const
Definition Stroke.h:376
StrokeVertex & operator=(const StrokeVertex &iBrother)
Definition Stroke.cpp:374
virtual Interface0DIterator pointsEnd(float t=0.0f)
Definition Stroke.cpp:790
const_vertex_iterator vertices_begin() const
embedding vertex iterator
Definition Stroke.cpp:741
void ScaleThickness(float iFactor)
Definition Stroke.cpp:795
virtual Interface0DIterator verticesBegin()
Definition Stroke.cpp:771
StrokeInternal::vertex_iterator_base< StrokeInternal::vertex_nonconst_traits > vertex_iterator
Definition Stroke.h:516
StrokeInternal::vertex_iterator_base< StrokeInternal::vertex_const_traits > const_vertex_iterator
Definition Stroke.h:518
void RemoveAllVertices()
Definition Stroke.cpp:693
virtual ~Stroke()
Definition Stroke.cpp:439
void RemoveVertex(StrokeVertex *iVertex)
Definition Stroke.cpp:703
void InsertVertex(StrokeVertex *iVertex, StrokeInternal::StrokeVertexIterator next)
Definition Stroke.cpp:716
const_vertex_iterator vertices_end() const
Definition Stroke.cpp:746
std::deque< StrokeVertex * > vertex_container
Definition Stroke.h:513
virtual Interface0DIterator verticesEnd()
Definition Stroke.cpp:778
void UpdateLength()
Definition Stroke.cpp:723
void Render(const StrokeRenderer *iRenderer)
Definition Stroke.cpp:805
uint strokeVerticesSize() const
Definition Stroke.h:839
virtual Interface0DIterator pointsBegin(float t=0.0f)
Definition Stroke.cpp:785
void RenderBasic(const StrokeRenderer *iRenderer)
Definition Stroke.cpp:813
Stroke & operator=(const Stroke &iBrother)
Definition Stroke.cpp:456
void setLength(float iLength)
Definition Stroke.cpp:483
float ComputeSampling(int iNVertices)
Definition Stroke.cpp:491
StrokeInternal::StrokeVertexIterator strokeVerticesEnd()
Definition Stroke.cpp:765
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.0f)
Definition Stroke.cpp:756
int Resample(int iNPoints)
Definition Stroke.cpp:525
value_type norm() const
Definition VecMat.h:94
local_group_size(16, 16) .push_constant(Type b
draw_view in_light_buf[] float
draw_view push_constant(Type::INT, "radiance_src") .push_constant(Type capture_info_buf storage_buf(1, Qualifier::READ, "ObjectBounds", "bounds_buf[]") .push_constant(Type draw_view int
ccl_device_inline float2 floor(const float2 a)
static ulong * next
#define N
#define G(x, y, z)
VecMat::Vec3< real > Vec3r
Definition Geom.h:30
inherits from class Rep
Definition AppCanvas.cpp:20
static uint a[3]
Definition RandGen.cpp:82
double real
Definition Precision.h:14
return ret
#define FLT_MAX
Definition stdcycles.h:14