Fix for a number of compiler warnings as well as a bug hidden by the warnings.
[blender.git] / source / blender / freestyle / intern / stroke / AdvancedStrokeShaders.cpp
1
2 //
3 //  Copyright (C) : Please refer to the COPYRIGHT file distributed 
4 //   with this source distribution. 
5 //
6 //  This program is free software; you can redistribute it and/or
7 //  modify it under the terms of the GNU General Public License
8 //  as published by the Free Software Foundation; either version 2
9 //  of the License, or (at your option) any later version.
10 //
11 //  This program is distributed in the hope that it will be useful,
12 //  but WITHOUT ANY WARRANTY; without even the implied warranty of
13 //  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14 //  GNU General Public License for more details.
15 //
16 //  You should have received a copy of the GNU General Public License
17 //  along with this program; if not, write to the Free Software
18 //  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
19 //
20 ///////////////////////////////////////////////////////////////////////////////
21
22 #include "AdvancedStrokeShaders.h"
23 #include "../system/PseudoNoise.h"
24 #include "../system/RandGen.h"
25 #include "StrokeIterators.h"
26
27 /////////////////////////////////////////
28 //
29 //  CALLIGRAPHICS SHADER
30 //
31 /////////////////////////////////////////
32
33
34 CalligraphicShader::CalligraphicShader (real iMinThickness, real iMaxThickness,
35                                         const Vec2f &iOrientation, bool clamp)
36   : StrokeShader()
37 {
38   _minThickness=iMinThickness;
39   _maxThickness=iMaxThickness;
40   _orientation = iOrientation;
41   _orientation.normalize();
42   _clamp = clamp;
43 }
44
45 float ksinToto=0;
46
47 int 
48 CalligraphicShader::shade(Stroke &ioStroke) const 
49 {
50   Interface0DIterator v;
51   Functions0D::VertexOrientation2DF0D fun;
52   StrokeVertex* sv;
53   for(v=ioStroke.verticesBegin();
54       !v.isEnd();
55       ++v)
56     {
57       real thickness;
58           if (fun(v) < 0)
59                 return -1;
60           Vec2f vertexOri(fun.result);
61       Vec2r ori2d(-vertexOri[1], vertexOri[0]);
62       ori2d.normalizeSafe();
63       real scal = ori2d * _orientation;
64       sv = dynamic_cast<StrokeVertex*>(&(*v));
65       if (_clamp && (scal<0)) {
66         scal=0.0;
67         sv->attribute().setColor(1,1,1);
68       }
69       else {
70         scal=fabs(scal);
71         sv->attribute().setColor(0,0,0);
72       }
73       thickness=_minThickness+scal*(_maxThickness-_minThickness);
74       if (thickness<0.0)
75         thickness=0.0;
76       sv->attribute().setThickness(thickness/2.0,thickness/2.0);
77     }
78
79   return 0;
80 }
81
82 //void 
83 //TipRemoverShader::shade(Stroke &ioStroke) const 
84 //{
85 //  
86 //  StrokeInternal::StrokeVertexIterator v, vend;
87 //  for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
88 //      v!=vend;
89 //      ++v)
90 //    {
91 //      if (((*v)->curvilinearAbscissa()<_tipLength) ||
92 //        ((*v)->strokeLength()-(*v)->curvilinearAbscissa()<_tipLength))
93 //      { 
94 //        (*v)->attribute().setThickness(0.0, 0.0);
95 //        (*v)->attribute().setColor(1,1,1);
96 //      } 
97 //    }
98 //
99 //}
100
101
102
103 /////////////////////////////////////////
104 //
105 //  SPATIAL NOISE SHADER
106 //
107 /////////////////////////////////////////
108
109 static const unsigned NB_VALUE_NOISE = 512;
110
111 SpatialNoiseShader::SpatialNoiseShader (float ioamount, float ixScale, int nbOctave, 
112                                         bool smooth, bool pureRandom)
113   : StrokeShader()
114 {
115   _amount = ioamount;
116   if (ixScale==0) _xScale=0;
117   else _xScale=1.0/ixScale/real(NB_VALUE_NOISE);
118   _nbOctave=nbOctave;
119   _smooth=smooth;
120   _pureRandom=pureRandom;
121 }
122 int
123 SpatialNoiseShader::shade(Stroke &ioStroke) const 
124 {
125   Interface0DIterator v, v2;
126   v=ioStroke.verticesBegin();
127   Vec2r p(v->getProjectedX(), v->getProjectedY());
128   v2=v; ++v2;
129   Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
130   p0=p+2*(p-p0);
131   StrokeVertex* sv;
132   sv = dynamic_cast<StrokeVertex*>(&(*v));
133   real initU = sv->strokeLength()*real(NB_VALUE_NOISE);
134   if (_pureRandom) initU+=RandGen::drand48()*real(NB_VALUE_NOISE);
135
136   Functions0D::VertexOrientation2DF0D fun;
137   while (!v.isEnd())
138     {
139       sv = dynamic_cast<StrokeVertex*>(&(*v));
140       Vec2r p(sv->getPoint());
141           if (fun(v) < 0)
142                 return -1;
143           Vec2r vertexOri(fun.result);
144       Vec2r ori2d(vertexOri[0], vertexOri[1]);
145       ori2d = Vec2r(p-p0);
146       ori2d.normalizeSafe();
147
148       PseudoNoise mynoise;
149       real bruit;
150
151       if (_smooth)
152         bruit=mynoise.turbulenceSmooth(_xScale*sv->curvilinearAbscissa()+initU,
153                                        _nbOctave);
154       else
155         bruit=mynoise.turbulenceLinear(_xScale*sv->curvilinearAbscissa()+initU,
156                                        _nbOctave);
157       
158       Vec2r noise(-ori2d[1]*_amount*bruit,
159                   ori2d[0]*_amount*bruit);
160
161       sv->setPoint(p[0]+noise[0], p[1]+noise[1]);
162       p0=p;
163
164       ++v;
165     }
166
167   return 0;
168 }
169
170
171  
172 /////////////////////////////////////////
173 //
174 //  SMOOTHING SHADER
175 //
176 /////////////////////////////////////////
177
178
179 SmoothingShader::SmoothingShader (int ionbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
180                                   real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor) 
181   : StrokeShader()
182 {
183   _nbIterations=ionbIteration;
184   _factorCurvature=ifactorCurvature;
185   _factorCurvatureDifference=iFactorCurvatureDifference;
186   _anisoNormal=iAnisoNormal;
187   _anisoCurvature=iAnisoCurvature;
188   _carricatureFactor=iCarricatureFactor;
189   _factorPoint=iFactorPoint;
190   _anisoPoint=iAnisoPoint;
191 }
192
193
194
195 int
196 SmoothingShader::shade(Stroke &ioStroke) const 
197 {
198   //cerr<<" Smoothing a stroke  "<<endl;
199
200   Smoother smoother(ioStroke);
201   smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference, 
202                   _anisoPoint, _anisoNormal, _anisoCurvature, _carricatureFactor);
203   return 0;
204 }
205
206 // SMOOTHER
207 ////////////////////////////
208
209 Smoother::Smoother(Stroke &ioStroke)
210 {
211   _stroke=&ioStroke;
212
213   _nbVertices=ioStroke.vertices_size();
214   _vertex=new Vec2r[_nbVertices];
215   _curvature=new real[_nbVertices];
216   _normal=new Vec2r[_nbVertices];
217   StrokeInternal::StrokeVertexIterator v, vend;
218   int i=0;
219   for(v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd();
220       v != vend;
221       ++v)
222     {
223       _vertex[i]=(v)->getPoint();       
224       i++;
225     }
226   Vec2r vec_tmp(_vertex[0]-_vertex[_nbVertices-1]);
227   _isClosedCurve = (vec_tmp.norm() < M_EPSILON);
228
229   _safeTest=(_nbVertices>4);
230 }
231
232 void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
233                       real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
234 {
235   _factorCurvature=ifactorCurvature;
236   _factorCurvatureDifference=iFactorCurvatureDifference;
237   _anisoNormal=iAnisoNormal;
238   _anisoCurvature=iAnisoCurvature;
239   _carricatureFactor=iCarricatureFactor;
240   _factorPoint=iFactorPoint;
241   _anisoPoint=iAnisoPoint;
242
243   for (int i=0; i<nbIteration; i++)
244     iteration ();
245   copyVertices(); 
246 }
247
248 static real edgeStopping (real x, real sigma)
249 {
250   if (sigma==0.0) return 1.0;
251   return exp(-x*x/(sigma*sigma));
252 }
253
254 void 
255 Smoother::iteration ()
256 {
257   computeCurvature();
258   for (int i=1; i<_nbVertices-1; i++)
259     {
260       real motionNormal=_factorCurvature*_curvature[i]*
261         edgeStopping(_curvature[i], _anisoNormal);
262
263       real diffC1=_curvature[i]-_curvature[i-1];
264       real diffC2=_curvature[i]-_curvature[i+1];
265       real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
266         edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
267       motionCurvature*=_factorCurvatureDifference;
268       //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
269       if (_safeTest)
270         _vertex[i]=Vec2r(_vertex[i]+(motionNormal+motionCurvature)*_normal[i]);
271       Vec2r v1(_vertex[i-1]-_vertex[i]);
272       Vec2r v2(_vertex[i+1]-_vertex[i]);
273       real d1 = v1.norm();
274       real d2 = v2.norm();
275       _vertex[i]=Vec2r(_vertex[i]+ 
276                        _factorPoint*edgeStopping(d2, _anisoPoint)*(_vertex[i-1]-_vertex[i]) +
277                        _factorPoint*edgeStopping(d1, _anisoPoint)*(_vertex[i+1]-_vertex[i]) );
278     }
279
280   if (_isClosedCurve)
281     {
282       real motionNormal=_factorCurvature*_curvature[0]*
283         edgeStopping(_curvature[0], _anisoNormal);
284
285       real diffC1=_curvature[0]-_curvature[_nbVertices-2];
286       real diffC2=_curvature[0]-_curvature[1];
287       real motionCurvature=edgeStopping(diffC1, _anisoCurvature)*diffC1 +
288         edgeStopping(diffC2, _anisoCurvature)*diffC2;//_factorCurvatureDifference;
289       motionCurvature*=_factorCurvatureDifference;
290       //motionCurvature=_factorCurvatureDifference*(diffC1+diffC2);
291       _vertex[0]=Vec2r(_vertex[0]+(motionNormal+motionCurvature)*_normal[0]);
292       _vertex[_nbVertices-1]=_vertex[0];
293     }
294 }
295
296
297 void 
298 Smoother::computeCurvature ()
299 {
300   int i;
301   Vec2r BA, BC, normalCurvature;
302   for (i = 1; i < _nbVertices - 1; i++)
303     {
304       BA=_vertex[i-1]-_vertex[i];
305       BC=_vertex[i+1]-_vertex[i];
306       real lba=BA.norm(), lbc=BC.norm();
307       BA.normalizeSafe();
308       BC.normalizeSafe();
309       normalCurvature = BA + BC;
310
311       _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
312       _normal[i].normalizeSafe();
313
314       _curvature[i] = normalCurvature * _normal[i];
315       if (lba+lbc > M_EPSILON)
316         _curvature[i]/=(0.5*lba+lbc);
317     }
318   _curvature[0]=_curvature[1];
319   _curvature[_nbVertices-1]=_curvature[_nbVertices-2];
320   Vec2r di(_vertex[1]-_vertex[0]); 
321   _normal[0] = Vec2r(-di[1], di[0]);
322   _normal[0].normalizeSafe();
323   di=_vertex[_nbVertices-1]-_vertex[_nbVertices-2];
324   _normal[_nbVertices-1]=Vec2r(-di[1], di[0]);
325   _normal[_nbVertices-1].normalizeSafe();
326
327   if (_isClosedCurve)
328     {
329       BA=_vertex[_nbVertices-2]-_vertex[0];
330       BC=_vertex[1]-_vertex[0];
331       real lba=BA.norm(), lbc=BC.norm();
332       BA.normalizeSafe();
333       BC.normalizeSafe();
334       normalCurvature = BA + BC;
335
336       _normal[i]=Vec2r(-(BC-BA)[1], (BC-BA)[0]);
337       _normal[i].normalizeSafe();
338
339       _curvature[i] = normalCurvature * _normal[i];
340       if (lba+lbc > M_EPSILON)
341         _curvature[i]/=(0.5*lba+lbc);
342
343       _normal[_nbVertices-1]=_normal[0];
344       _curvature[_nbVertices-1]=_curvature[0];
345     }
346 }
347
348 void 
349 Smoother::copyVertices ()
350 {
351   int i=0;
352   StrokeInternal::StrokeVertexIterator v, vend;
353   for(v=_stroke->strokeVerticesBegin(), vend=_stroke->strokeVerticesEnd();
354       v!=vend;
355       ++v)
356     {
357       const Vec2r p0((v)->getPoint());
358       const Vec2r p1(_vertex[i]);
359       Vec2r p(p0 + _carricatureFactor * (p1 - p0));
360
361       (v)->setPoint(p[0], p[1]);
362       i++;
363     }
364
365 }
366
367  
368 #if 0 // FIXME
369
370 /////////////////////////////////////////
371 //
372 //  OMISSION SHADER
373 //
374 /////////////////////////////////////////
375
376 OmissionShader::OmissionShader (real sizeWindow, real thrVari, real thrFlat, real lFlat)
377 {
378   _sizeWindow=sizeWindow;
379   _thresholdVariation=thrVari;
380   _thresholdFlat=thrFlat;
381   _lengthFlat=lFlat;
382 }
383
384 int
385 OmissionShader::shade(Stroke &ioStroke) const 
386 {
387   Omitter omi(ioStroke);
388   omi.omit(_sizeWindow, _thresholdVariation, _thresholdFlat, _lengthFlat);
389
390   return 0;
391 }
392
393
394 // OMITTER
395 ///////////////////////////
396
397 Omitter::Omitter (Stroke &ioStroke)
398   :Smoother (ioStroke)
399 {
400   StrokeInternal::StrokeVertexIterator v, vend;
401   int i=0;
402   for(v=ioStroke.strokeVerticesBegin(), vend=ioStroke.strokeVerticesEnd();
403       v!=vend;
404       ++v)
405     {
406       _u[i]=(v)->curvilinearAbscissa();
407       i++;
408     }
409
410 }
411
412 void
413 Omitter::omit (real sizeWindow, real thrVari, real thrFlat, real lFlat)
414 {
415   _sizeWindow=sizeWindow;
416   _thresholdVariation=thrVari;
417   _thresholdFlat=thrFlat;
418   _lengthFlat=lFlat;
419
420   for (int i=1; i<_nbVertices-1; i++)
421     {
422       if (_u[i]<_lengthFlat) continue;
423       // is the previous segment flat?
424       int j=i-1; 
425       while ((j>=0) && (_u[i]-_u[j]<_lengthFlat))
426         {
427           if ((_normal[j] * _normal[i]) < _thresholdFlat)
428             ; // FIXME
429           j--;
430         }
431
432     }
433 }
434
435 #endif