Blender  V2.93
AdvancedStrokeShaders.cpp
Go to the documentation of this file.
1 /*
2  * This program is free software; you can redistribute it and/or
3  * modify it under the terms of the GNU General Public License
4  * as published by the Free Software Foundation; either version 2
5  * of the License, or (at your option) any later version.
6  *
7  * This program is distributed in the hope that it will be useful,
8  * but WITHOUT ANY WARRANTY; without even the implied warranty of
9  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10  * GNU General Public License for more details.
11  *
12  * You should have received a copy of the GNU General Public License
13  * along with this program; if not, write to the Free Software Foundation,
14  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
15  */
16 
22 #include "AdvancedStrokeShaders.h"
23 #include "StrokeIterators.h"
24 
25 #include "../system/PseudoNoise.h"
26 #include "../system/RandGen.h"
27 
28 namespace Freestyle {
29 
31 //
32 // CALLIGRAPHICS SHADER
33 //
35 
37  real iMaxThickness,
38  const Vec2f &iOrientation,
39  bool clamp)
40 {
41  _minThickness = iMinThickness;
42  _maxThickness = iMaxThickness;
43  _orientation = iOrientation;
45  _clamp = clamp;
46 }
47 
48 int CalligraphicShader::shade(Stroke &ioStroke) const
49 {
52  StrokeVertex *sv;
53  for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) {
54  real thickness;
55  if (fun(v) < 0) {
56  return -1;
57  }
58 
59  Vec2f vertexOri(fun.result);
60  Vec2r ori2d(-vertexOri[1], vertexOri[0]);
61  ori2d.normalizeSafe();
62  real scal = ori2d * _orientation;
63  sv = dynamic_cast<StrokeVertex *>(&(*v));
64  if (_clamp && (scal < 0)) {
65  scal = 0.0;
66  sv->attribute().setColor(1, 1, 1);
67  }
68  else {
69  scal = fabs(scal);
70  sv->attribute().setColor(0, 0, 0);
71  }
72  thickness = _minThickness + scal * (_maxThickness - _minThickness);
73  if (thickness < 0.0) {
74  thickness = 0.0;
75  }
76  sv->attribute().setThickness(thickness / 2.0, thickness / 2.0);
77  }
78 
79  return 0;
80 }
81 
83 //
84 // SPATIAL NOISE SHADER
85 //
87 
88 static const unsigned NB_VALUE_NOISE = 512;
89 
91  float iAmount, float ixScale, int nbOctave, bool smooth, bool pureRandom)
92 {
93  _amount = iAmount;
94  if (ixScale == 0) {
95  _xScale = 0;
96  }
97  else {
98  _xScale = 1.0 / ixScale / real(NB_VALUE_NOISE);
99  }
100  _nbOctave = nbOctave;
101  _smooth = smooth;
102  _pureRandom = pureRandom;
103 }
104 
105 int SpatialNoiseShader::shade(Stroke &ioStroke) const
106 {
108  v = ioStroke.verticesBegin();
109  Vec2r p(v->getProjectedX(), v->getProjectedY());
110  v2 = v;
111  ++v2;
112  Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
113  p0 = p + 2 * (p - p0);
114  StrokeVertex *sv;
115  sv = dynamic_cast<StrokeVertex *>(&(*v));
116  real initU = sv->strokeLength() * real(NB_VALUE_NOISE);
117  if (_pureRandom) {
118  initU += RandGen::drand48() * real(NB_VALUE_NOISE);
119  }
120 
122  while (!v.isEnd()) {
123  sv = dynamic_cast<StrokeVertex *>(&(*v));
124  Vec2r p(sv->getPoint());
125  if (fun(v) < 0) {
126  return -1;
127  }
128  Vec2r vertexOri(fun.result);
129  Vec2r ori2d(vertexOri[0], vertexOri[1]);
130  ori2d = Vec2r(p - p0);
131  ori2d.normalizeSafe();
132 
133  PseudoNoise mynoise;
134  real bruit;
135 
136  if (_smooth) {
137  bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
138  }
139  else {
140  bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
141  }
142 
143  Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit);
144 
145  sv->setPoint(p[0] + noise[0], p[1] + noise[1]);
146  p0 = p;
147 
148  ++v;
149  }
150 
151  ioStroke.UpdateLength();
152 
153  return 0;
154 }
155 
157 //
158 // SMOOTHING SHADER
159 //
161 
163  real iFactorPoint,
164  real ifactorCurvature,
165  real iFactorCurvatureDifference,
166  real iAnisoPoint,
167  real iAnisoNormal,
168  real iAnisoCurvature,
169  real iCarricatureFactor)
170 {
171  _nbIterations = iNbIteration;
172  _factorCurvature = ifactorCurvature;
173  _factorCurvatureDifference = iFactorCurvatureDifference;
174  _anisoNormal = iAnisoNormal;
175  _anisoCurvature = iAnisoCurvature;
176  _carricatureFactor = iCarricatureFactor;
177  _factorPoint = iFactorPoint;
178  _anisoPoint = iAnisoPoint;
179 }
180 
181 int SmoothingShader::shade(Stroke &ioStroke) const
182 {
183  // cerr << " Smoothing a stroke " << endl;
184 
185  Smoother smoother(ioStroke);
186  smoother.smooth(_nbIterations,
187  _factorPoint,
190  _anisoPoint,
191  _anisoNormal,
194  return 0;
195 }
196 
197 // SMOOTHER
199 
201 {
202  _stroke = &ioStroke;
203 
204  _nbVertices = ioStroke.vertices_size();
205  _vertex = new Vec2r[_nbVertices];
206  _curvature = new real[_nbVertices];
207  _normal = new Vec2r[_nbVertices];
209  int i = 0;
210  for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend;
211  ++v, ++i) {
212  _vertex[i] = (v)->getPoint();
213  }
214  Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]);
215  _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
216 
217  _safeTest = (_nbVertices > 4);
218 }
219 
221 {
222  delete[] _vertex;
223  delete[] _curvature;
224  delete[] _normal;
225 }
226 
227 void Smoother::smooth(int nbIteration,
228  real iFactorPoint,
229  real ifactorCurvature,
230  real iFactorCurvatureDifference,
231  real iAnisoPoint,
232  real iAnisoNormal,
233  real iAnisoCurvature,
234  real iCarricatureFactor)
235 {
236  _factorCurvature = ifactorCurvature;
237  _factorCurvatureDifference = iFactorCurvatureDifference;
238  _anisoNormal = iAnisoNormal;
239  _anisoCurvature = iAnisoCurvature;
240  _carricatureFactor = iCarricatureFactor;
241  _factorPoint = iFactorPoint;
242  _anisoPoint = iAnisoPoint;
243 
244  for (int i = 0; i < nbIteration; ++i) {
245  iteration();
246  }
247  copyVertices();
248 }
249 
250 static real edgeStopping(real x, real sigma)
251 {
252  if (sigma == 0.0) {
253  return 1.0;
254  }
255  return exp(-x * x / (sigma * sigma));
256 }
257 
259 {
261  for (int i = 1; i < (_nbVertices - 1); ++i) {
262  real motionNormal = _factorCurvature * _curvature[i] *
264 
265  real diffC1 = _curvature[i] - _curvature[i - 1];
266  real diffC2 = _curvature[i] - _curvature[i + 1];
267  real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
268  edgeStopping(diffC2, _anisoCurvature) *
269  diffC2; //_factorCurvatureDifference;
270  motionCurvature *= _factorCurvatureDifference;
271  // motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
272  if (_safeTest) {
273  _vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]);
274  }
275  Vec2r v1(_vertex[i - 1] - _vertex[i]);
276  Vec2r v2(_vertex[i + 1] - _vertex[i]);
277  real d1 = v1.norm();
278  real d2 = v2.norm();
279  _vertex[i] = Vec2r(
280  _vertex[i] + _factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) +
281  _factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i]));
282  }
283 
284  if (_isClosedCurve) {
285  real motionNormal = _factorCurvature * _curvature[0] *
287 
288  real diffC1 = _curvature[0] - _curvature[_nbVertices - 2];
289  real diffC2 = _curvature[0] - _curvature[1];
290  real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
291  edgeStopping(diffC2, _anisoCurvature) *
292  diffC2; //_factorCurvatureDifference;
293  motionCurvature *= _factorCurvatureDifference;
294  // motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
295  _vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]);
296  _vertex[_nbVertices - 1] = _vertex[0];
297  }
298 }
299 
301 {
302  int i;
303  Vec2r BA, BC, normalCurvature;
304  for (i = 1; i < (_nbVertices - 1); ++i) {
305  BA = _vertex[i - 1] - _vertex[i];
306  BC = _vertex[i + 1] - _vertex[i];
307  real lba = BA.norm(), lbc = BC.norm();
308  BA.normalizeSafe();
309  BC.normalizeSafe();
310  normalCurvature = BA + BC;
311 
312  _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
313  _normal[i].normalizeSafe();
314 
315  _curvature[i] = normalCurvature * _normal[i];
316  if (lba + lbc > M_EPSILON) {
317  _curvature[i] /= (0.5 * lba + lbc);
318  }
319  }
320  _curvature[0] = _curvature[1];
322  Vec2r di(_vertex[1] - _vertex[0]);
323  _normal[0] = Vec2r(-di[1], di[0]);
324  _normal[0].normalizeSafe();
325  di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2];
326  _normal[_nbVertices - 1] = Vec2r(-di[1], di[0]);
328 
329  if (_isClosedCurve) {
330  BA = _vertex[_nbVertices - 2] - _vertex[0];
331  BC = _vertex[1] - _vertex[0];
332  real lba = BA.norm(), lbc = BC.norm();
333  BA.normalizeSafe();
334  BC.normalizeSafe();
335  normalCurvature = BA + BC;
336 
337  _normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
338  _normal[i].normalizeSafe();
339 
340  _curvature[i] = normalCurvature * _normal[i];
341  if (lba + lbc > M_EPSILON) {
342  _curvature[i] /= (0.5 * lba + lbc);
343  }
344 
345  _normal[_nbVertices - 1] = _normal[0];
347  }
348 }
349 
351 {
352  int i = 0;
354  for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) {
355  const Vec2r p0((v)->getPoint());
356  const Vec2r p1(_vertex[i]);
357  Vec2r p(p0 + _carricatureFactor * (p1 - p0));
358 
359  (v)->setPoint(p[0], p[1]);
360  ++i;
361  }
363 }
364 
365 } /* namespace Freestyle */
Fredo's stroke shaders.
_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 v1
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 turbulenceSmooth(real x, unsigned nbOctave=8)
Definition: PseudoNoise.cpp:96
real turbulenceLinear(real x, unsigned nbOctave=8)
static real drand48()
Definition: RandGen.cpp:104
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:247
void setColor(float r, float g, float b)
Definition: Stroke.h:214
const StrokeAttribute & attribute() const
Definition: Stroke.h:388
float strokeLength() const
Definition: Stroke.h:406
virtual Interface0DIterator verticesBegin()
Definition: Stroke.cpp:779
int vertices_size() const
Definition: Stroke.h:684
void UpdateLength()
Definition: Stroke.cpp:731
StrokeInternal::StrokeVertexIterator strokeVerticesEnd()
Definition: Stroke.cpp:773
StrokeInternal::StrokeVertexIterator strokeVerticesBegin(float t=0.0f)
Definition: Stroke.cpp:764
Vec< T, N > & normalizeSafe()
Definition: VecMat.h:128
value_type norm() const
Definition: VecMat.h:109
Vec< T, N > & normalize()
Definition: VecMat.h:119
VecMat::Vec2< real > Vec2r
Definition: Geom.h:36
inherits from class Rep
Definition: AppCanvas.cpp:32
static const unsigned NB_VALUE_NOISE
static const real M_EPSILON
Definition: Precision.h:29
static unsigned x[3]
Definition: RandGen.cpp:87
static real edgeStopping(real x, real sigma)
double real
Definition: Precision.h:26
INLINE Rall1d< T, V, S > exp(const Rall1d< T, V, S > &arg)
Definition: rall1d.h:295
static float noise(int n)
ccl_device_inline int clamp(int a, int mn, int mx)
Definition: util_math.h:283
ccl_device_inline float2 fabs(const float2 &a)