Blender V4.3
AdvancedStrokeShaders.cpp
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2008-2022 Blender Authors
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
11#include "StrokeIterators.h"
12
14#include "../system/RandGen.h"
15
16#include "BLI_sys_types.h"
17
18namespace Freestyle {
19
21//
22// CALLIGRAPHICS SHADER
23//
25
27 real iMaxThickness,
28 const Vec2f &iOrientation,
29 bool clamp)
30{
31 _minThickness = iMinThickness;
32 _maxThickness = iMaxThickness;
33 _orientation = iOrientation;
35 _clamp = clamp;
36}
37
39{
42 StrokeVertex *sv;
43 for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) {
44 real thickness;
45 if (fun(v) < 0) {
46 return -1;
47 }
48
49 Vec2f vertexOri(fun.result);
50 Vec2r ori2d(-vertexOri[1], vertexOri[0]);
51 ori2d.normalizeSafe();
52 real scal = ori2d * _orientation;
53 sv = dynamic_cast<StrokeVertex *>(&(*v));
54 if (_clamp && (scal < 0)) {
55 scal = 0.0;
56 sv->attribute().setColor(1, 1, 1);
57 }
58 else {
59 scal = fabs(scal);
60 sv->attribute().setColor(0, 0, 0);
61 }
62 thickness = _minThickness + scal * (_maxThickness - _minThickness);
63 if (thickness < 0.0) {
64 thickness = 0.0;
65 }
66 sv->attribute().setThickness(thickness / 2.0, thickness / 2.0);
67 }
68
69 return 0;
70}
71
73//
74// SPATIAL NOISE SHADER
75//
77
78static const uint NB_VALUE_NOISE = 512;
79
81 float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom)
82{
83 _amount = iAmount;
84 if (ixScale == 0) {
85 _xScale = 0;
86 }
87 else {
88 _xScale = 1.0 / ixScale / real(NB_VALUE_NOISE);
89 }
90 _nbOctave = nbOctave;
92 _pureRandom = pureRandom;
93}
94
96{
98 v = ioStroke.verticesBegin();
99 Vec2r p(v->getProjectedX(), v->getProjectedY());
100 v2 = v;
101 ++v2;
102 Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
103 p0 = p + 2 * (p - p0);
104 StrokeVertex *sv;
105 sv = dynamic_cast<StrokeVertex *>(&(*v));
106 real initU = sv->strokeLength() * real(NB_VALUE_NOISE);
107 if (_pureRandom) {
109 }
110
112 while (!v.isEnd()) {
113 sv = dynamic_cast<StrokeVertex *>(&(*v));
114 Vec2r p(sv->getPoint());
115 if (fun(v) < 0) {
116 return -1;
117 }
118 Vec2r vertexOri(fun.result);
119 Vec2r ori2d(vertexOri[0], vertexOri[1]);
120 ori2d = Vec2r(p - p0);
121 ori2d.normalizeSafe();
122
123 PseudoNoise mynoise;
124 real bruit;
125
126 if (_smooth) {
127 bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
128 }
129 else {
130 bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
131 }
132
133 Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit);
134
135 sv->setPoint(p[0] + noise[0], p[1] + noise[1]);
136 p0 = p;
137
138 ++v;
139 }
140
141 ioStroke.UpdateLength();
142
143 return 0;
144}
145
147//
148// SMOOTHING SHADER
149//
151
153 real iFactorPoint,
154 real ifactorCurvature,
155 real iFactorCurvatureDifference,
156 real iAnisoPoint,
157 real iAnisoNormal,
158 real iAnisoCurvature,
159 real iCarricatureFactor)
160{
161 _nbIterations = iNbIteration;
162 _factorCurvature = ifactorCurvature;
163 _factorCurvatureDifference = iFactorCurvatureDifference;
164 _anisoNormal = iAnisoNormal;
165 _anisoCurvature = iAnisoCurvature;
166 _carricatureFactor = iCarricatureFactor;
167 _factorPoint = iFactorPoint;
168 _anisoPoint = iAnisoPoint;
169}
170
171int SmoothingShader::shade(Stroke &ioStroke) const
172{
173 // cerr << " Smoothing a stroke " << endl;
174
175 Smoother smoother(ioStroke);
176 smoother.smooth(_nbIterations,
184 return 0;
185}
186
187// SMOOTHER
189
191{
192 _stroke = &ioStroke;
193
194 _nbVertices = ioStroke.vertices_size();
199 int i = 0;
200 for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend;
201 ++v, ++i)
202 {
203 _vertex[i] = (v)->getPoint();
204 }
205 Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]);
206 _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
207
208 _safeTest = (_nbVertices > 4);
209}
210
212{
213 delete[] _vertex;
214 delete[] _curvature;
215 delete[] _normal;
216}
217
218void Smoother::smooth(int nbIteration,
219 real iFactorPoint,
220 real ifactorCurvature,
221 real iFactorCurvatureDifference,
222 real iAnisoPoint,
223 real iAnisoNormal,
224 real iAnisoCurvature,
225 real iCarricatureFactor)
226{
227 _factorCurvature = ifactorCurvature;
228 _factorCurvatureDifference = iFactorCurvatureDifference;
229 _anisoNormal = iAnisoNormal;
230 _anisoCurvature = iAnisoCurvature;
231 _carricatureFactor = iCarricatureFactor;
232 _factorPoint = iFactorPoint;
233 _anisoPoint = iAnisoPoint;
234
235 for (int i = 0; i < nbIteration; ++i) {
236 iteration();
237 }
238 copyVertices();
239}
240
241static real edgeStopping(real x, real sigma)
242{
243 if (sigma == 0.0) {
244 return 1.0;
245 }
246 return exp(-x * x / (sigma * sigma));
247}
248
250{
252 for (int i = 1; i < (_nbVertices - 1); ++i) {
253 real motionNormal = _factorCurvature * _curvature[i] *
255
256 real diffC1 = _curvature[i] - _curvature[i - 1];
257 real diffC2 = _curvature[i] - _curvature[i + 1];
258 real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
260 diffC2; //_factorCurvatureDifference;
261 motionCurvature *= _factorCurvatureDifference;
262 // motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
263 if (_safeTest) {
264 _vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]);
265 }
266 Vec2r v1(_vertex[i - 1] - _vertex[i]);
267 Vec2r v2(_vertex[i + 1] - _vertex[i]);
268 real d1 = v1.norm();
269 real d2 = v2.norm();
270 _vertex[i] = Vec2r(
271 _vertex[i] + _factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) +
272 _factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i]));
273 }
274
275 if (_isClosedCurve) {
276 real motionNormal = _factorCurvature * _curvature[0] *
278
279 real diffC1 = _curvature[0] - _curvature[_nbVertices - 2];
280 real diffC2 = _curvature[0] - _curvature[1];
281 real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
283 diffC2; //_factorCurvatureDifference;
284 motionCurvature *= _factorCurvatureDifference;
285 // motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
286 _vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]);
287 _vertex[_nbVertices - 1] = _vertex[0];
288 }
289}
290
292{
293 int i;
294 Vec2r BA, BC, normalCurvature;
295 for (i = 1; i < (_nbVertices - 1); ++i) {
296 BA = _vertex[i - 1] - _vertex[i];
297 BC = _vertex[i + 1] - _vertex[i];
298 real lba = BA.norm(), lbc = BC.norm();
299 BA.normalizeSafe();
300 BC.normalizeSafe();
301 normalCurvature = BA + BC;
302
303 _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
305
306 _curvature[i] = normalCurvature * _normal[i];
307 if (lba + lbc > M_EPSILON) {
308 _curvature[i] /= (0.5 * lba + lbc);
309 }
310 }
311 _curvature[0] = _curvature[1];
313 Vec2r di(_vertex[1] - _vertex[0]);
314 _normal[0] = Vec2r(-di[1], di[0]);
316 di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2];
317 _normal[_nbVertices - 1] = Vec2r(-di[1], di[0]);
319
320 if (_isClosedCurve) {
321 BA = _vertex[_nbVertices - 2] - _vertex[0];
322 BC = _vertex[1] - _vertex[0];
323 real lba = BA.norm(), lbc = BC.norm();
324 BA.normalizeSafe();
325 BC.normalizeSafe();
326 normalCurvature = BA + BC;
327
328 _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
330
331 _curvature[i] = normalCurvature * _normal[i];
332 if (lba + lbc > M_EPSILON) {
333 _curvature[i] /= (0.5 * lba + lbc);
334 }
335
336 _normal[_nbVertices - 1] = _normal[0];
338 }
339}
340
342{
343 int i = 0;
345 for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) {
346 const Vec2r p0((v)->getPoint());
347 const Vec2r p1(_vertex[i]);
348 Vec2r p(p0 + _carricatureFactor * (p1 - p0));
349
350 (v)->setPoint(p[0], p[1]);
351 ++i;
352 }
354}
355
356} /* namespace Freestyle */
Fredo's stroke shaders.
unsigned int uint
Class to define a pseudo Perlin noise.
Pseudo-random number generator.
Iterators used to iterate over the elements of the Stroke.
ATTR_WARN_UNUSED_RESULT const BMVert * v2
ATTR_WARN_UNUSED_RESULT const BMVert * v
CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp)
virtual int shade(Stroke &ioStroke) const
real turbulenceLinear(real x, uint nbOctave=8)
real turbulenceSmooth(real x, uint nbOctave=8)
static real drand48()
Definition RandGen.cpp:94
void smooth(int nbIterations, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor)
virtual int shade(Stroke &ioStroke) const
SmoothingShader(int iNbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference, real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real icarricatureFactor)
virtual int shade(Stroke &ioStroke) const
SpatialNoiseShader(float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom)
void setThickness(float tr, float tl)
Definition Stroke.h:235
void setColor(float r, float g, float b)
Definition Stroke.h:202
float strokeLength() const
Definition Stroke.h:394
const StrokeAttribute & attribute() const
Definition Stroke.h:376
virtual Interface0DIterator verticesBegin()
Definition Stroke.cpp:771
int vertices_size() const
Definition Stroke.h:672
void UpdateLength()
Definition Stroke.cpp:723
StrokeInternal::StrokeVertexIterator strokeVerticesEnd()
Definition Stroke.cpp:765
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.0f)
Definition Stroke.cpp:756
Vec< T, N > & normalizeSafe()
Definition VecMat.h:113
Vec< T, N > & normalize()
Definition VecMat.h:104
value_type norm() const
Definition VecMat.h:94
smooth(Type::VEC3, "P") .flat(Type out_color storage_buf(0, Qualifier::READ, "Surfel", "surfels_buf[]") .push_constant(Type smooth(Type::VEC4, "interp_color")
ccl_device_inline float2 fabs(const float2 a)
ccl_device_inline float3 exp(float3 v)
VecMat::Vec2< real > Vec2r
Definition Geom.h:24
inherits from class Rep
Definition AppCanvas.cpp:20
static const real M_EPSILON
Definition Precision.h:17
static const uint NB_VALUE_NOISE
static real edgeStopping(real x, real sigma)
double real
Definition Precision.h:14
ccl_device_inline int clamp(int a, int mn, int mx)
Definition util/math.h:379