c507f137f4c36f7224a0da51f5ed05ab4c4a25de
[blender.git] / source / blender / freestyle / intern / stroke / BasicStrokeShaders.cpp
1 /*
2  * ***** BEGIN GPL LICENSE BLOCK *****
3  *
4  * This program is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU General Public License
6  * as published by the Free Software Foundation; either version 2
7  * of the License, or (at your option) any later version.
8  *
9  * This program is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  * GNU General Public License for more details.
13  *
14  * You should have received a copy of the GNU General Public License
15  * along with this program; if not, write to the Free Software Foundation,
16  * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
17  *
18  * ***** END GPL LICENSE BLOCK *****
19  */
20
21 /** \file blender/freestyle/intern/stroke/BasicStrokeShaders.cpp
22  *  \ingroup freestyle
23  *  \brief Class gathering basic stroke shaders
24  *  \author Stephane Grabli
25  *  \date 17/12/2002
26  */
27
28 #include <fstream>
29
30 #include "AdvancedFunctions0D.h"
31 #include "AdvancedFunctions1D.h"
32 #include "BasicStrokeShaders.h"
33 #include "StrokeIO.h"
34 #include "StrokeIterators.h"
35 #include "StrokeRenderer.h"
36
37 #include "../system/PseudoNoise.h"
38 #include "../system/RandGen.h"
39 #include "../system/StringUtils.h"
40
41 #include "../view_map/Functions0D.h"
42 #include "../view_map/Functions1D.h"
43
44 #include "BKE_global.h"
45
46 //soc #include <qimage.h>
47 //soc #include <QString>
48
49 extern "C" {
50 #  include "IMB_imbuf.h"
51 #  include "IMB_imbuf_types.h"
52 }
53
54 namespace Freestyle {
55
56 // Internal function
57
58 #if 0 // soc
59 void convert(const QImage& iImage, float **oArray, unsigned &oSize)
60 {
61         oSize = iImage.width();
62         *oArray = new float[oSize];
63         for (unsigned int i = 0; i < oSize; ++i) {
64                 QRgb rgb = iImage.pixel(i,0);
65                 (*oArray)[i] = ((float)qBlue(rgb)) / 255.0f;
66         }
67 }
68 #endif
69
70 static void convert(ImBuf *imBuf, float **oArray, unsigned &oSize)
71 {
72         oSize = imBuf->x;
73         *oArray = new float[oSize];
74
75         char *pix;
76         for (unsigned int i = 0; i < oSize; ++i) {
77                 pix = (char *) imBuf->rect + i * 4;
78                 (*oArray)[i] = ((float) pix[2]) / 255.0f;
79         }
80 }
81
82 namespace StrokeShaders {
83
84 //
85 //  Thickness modifiers
86 //
87 //////////////////////////////////////////////////////////
88
89 int ConstantThicknessShader::shade(Stroke& stroke) const
90 {
91         StrokeInternal::StrokeVertexIterator v, vend;
92         int i = 0;
93         int size = stroke.strokeVerticesSize();
94         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
95                 // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
96                 if ((1 == i) || (size - 2 == i))
97                         v->attribute().setThickness(_thickness / 4.0, _thickness / 4.0);
98                 if ((0 == i) || (size - 1 == i))
99                         v->attribute().setThickness(0, 0);
100
101                 v->attribute().setThickness(_thickness / 2.0, _thickness / 2.0);
102         }
103         return 0;
104 }
105
106 int ConstantExternThicknessShader::shade(Stroke& stroke) const
107 {
108         StrokeInternal::StrokeVertexIterator v, vend;
109         int i = 0;
110         int size = stroke.strokeVerticesSize();
111         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
112                 // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
113                 if ((1 == i) || (size - 2 == i))
114                         v->attribute().setThickness(_thickness / 2.0, 0);
115                 if ((0 == i) || (size - 1 == i))
116                         v->attribute().setThickness(0, 0);
117
118                 v->attribute().setThickness(_thickness, 0);
119         }
120         return 0;
121 }
122
123 int IncreasingThicknessShader::shade(Stroke& stroke) const
124 {
125         int n = stroke.strokeVerticesSize() - 1, i;
126         StrokeInternal::StrokeVertexIterator v, vend;
127         for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
128              v != vend;
129              ++v, ++i)
130         {
131                 float t;
132                 if (i < (float)n / 2.0f)
133                         t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * _ThicknessMax;
134                 else
135                         t = (1.0 - (float)i / (float)n) * _ThicknessMax + (float)i / (float)n * _ThicknessMin;
136                 v->attribute().setThickness(t / 2.0, t / 2.0);
137         }
138         return 0;
139 }
140
141 int ConstrainedIncreasingThicknessShader::shade(Stroke& stroke) const
142 {
143         float slength = stroke.getLength2D();
144         float maxT = min(_ratio * slength, _ThicknessMax);
145         int n = stroke.strokeVerticesSize() - 1, i;
146         StrokeInternal::StrokeVertexIterator v, vend;
147         for (i = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
148              v != vend;
149              ++v, ++i)
150         {
151                 // XXX Why not using an if/else here? Else, if last condition is true, everything else is computed for nothing!
152                 float t;
153                 if (i < (float)n / 2.0f)
154                         t = (1.0 - (float)i / (float)n) * _ThicknessMin + (float)i / (float)n * maxT;
155                 else
156                         t = (1.0 - (float)i / (float)n) * maxT + (float)i / (float)n * _ThicknessMin;
157                 v->attribute().setThickness(t / 2.0, t / 2.0);
158                 if (i == n - 1)
159                         v->attribute().setThickness(_ThicknessMin / 2.0, _ThicknessMin / 2.0);
160         }
161         return 0;
162 }
163
164
165 int LengthDependingThicknessShader::shade(Stroke& stroke) const
166 {
167         float step = (_maxThickness - _minThickness) / 3.0f;
168         float l = stroke.getLength2D();
169         float thickness = 0.0f;
170         if (l > 300.0f)
171                 thickness = _minThickness + 3.0f * step;
172         else if ((l < 300.0f) && (l > 100.0f))
173                 thickness = _minThickness + 2.0f * step;
174         else if ((l < 100.0f) && (l > 50.0f))
175                 thickness = _minThickness + 1.0f * step;
176         else // else if (l <  50.0f), tsst...
177                 thickness = _minThickness;
178
179         StrokeInternal::StrokeVertexIterator v, vend;
180         int i = 0;
181         int size = stroke.strokeVerticesSize();
182         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
183                 // XXX What's the use of i here? And is not the thickness always overriden by the last line of the loop?
184                 if ((1 == i) || (size - 2 == i))
185                         v->attribute().setThickness(thickness / 4.0, thickness / 4.0);
186                 if ((0 == i) || (size - 1 == i))
187                         v->attribute().setThickness(0, 0);
188
189                 v->attribute().setThickness(thickness / 2.0, thickness / 2.0);
190         }
191         return 0;
192 }
193
194
195 ThicknessVariationPatternShader::ThicknessVariationPatternShader(const string pattern_name, float iMinThickness,
196                                                                  float iMaxThickness, bool stretch)
197 : StrokeShader()
198 {
199         _stretch = stretch;
200         _minThickness = iMinThickness;
201         _maxThickness = iMaxThickness;
202         ImBuf *image = NULL;
203         vector<string> pathnames;
204         StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames);
205         for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) {
206                 ifstream ifs(j->c_str());
207                 if (ifs.is_open()) {
208                         /* OCIO_TODO: support different input color space */
209                         image = IMB_loadiffname(j->c_str(), 0, NULL);
210                         break;
211                 }
212         }
213         if (image == NULL)
214                 cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl;
215         else
216                 convert(image, &_aThickness, _size);
217         IMB_freeImBuf(image);
218 }
219
220
221 int ThicknessVariationPatternShader::shade(Stroke& stroke) const
222 {
223         StrokeInternal::StrokeVertexIterator v, vend;
224         float *array = NULL;
225         /* int size; */ /* UNUSED */
226         array = _aThickness;
227         /* size = _size; */ /* UNUSED */
228         int vert_size = stroke.strokeVerticesSize();
229         int sig = 0;
230         unsigned index;
231         const float *originalThickness;
232         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
233                 originalThickness = v->attribute().getThickness();
234                 if (_stretch) {
235                         float tmp = v->u() * (_size - 1);
236                         index = (unsigned)floor(tmp);
237                         if ((tmp - index) > (index + 1 - tmp))
238                                 ++index;
239                 }
240                 else {
241                         index = (unsigned)floor(v->curvilinearAbscissa());
242                 }
243                 index %= _size;
244                 float thicknessR = array[index] * originalThickness[0];
245                 float thicknessL = array[index] * originalThickness[1];
246                 if (thicknessR + thicknessL < _minThickness) {
247                         thicknessL = _minThickness / 2.0f;
248                         thicknessR = _minThickness / 2.0f;
249                 }
250                 if (thicknessR + thicknessL > _maxThickness) {
251                         thicknessL = _maxThickness / 2.0f;
252                         thicknessR = _maxThickness / 2.0f;
253                 }
254                 if ((sig == 0) || (sig == vert_size - 1))
255                         v->attribute().setThickness(1, 1);
256                 else
257                         v->attribute().setThickness(thicknessR, thicknessL);
258                 ++sig;
259         }
260         return 0;
261 }
262
263
264 static const unsigned NB_VALUE_NOISE = 512;
265
266 ThicknessNoiseShader::ThicknessNoiseShader() : StrokeShader()
267 {
268         _amplitude = 1.0f;
269         _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE;
270 }
271
272 ThicknessNoiseShader::ThicknessNoiseShader(float iAmplitude, float iPeriod) : StrokeShader()
273 {
274         _amplitude = iAmplitude;
275         _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE;
276 }
277
278 int ThicknessNoiseShader::shade(Stroke& stroke) const
279 {
280         StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
281         real initU1 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
282         real initU2 = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
283
284         real bruit, bruit2;
285         PseudoNoise mynoise, mynoise2;
286         for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
287                 bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU1, 2); // 2 : nbOctaves
288                 bruit2 = mynoise2.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU2, 2); // 2 : nbOctaves
289                 const float *originalThickness = v->attribute().getThickness();
290                 float r = bruit * _amplitude + originalThickness[0];
291                 float l = bruit2 * _amplitude + originalThickness[1];
292                 v->attribute().setThickness(r, l);
293         }
294
295         return 0;
296 }
297
298 //
299 //  Color shaders
300 //
301 ///////////////////////////////////////////////////////////////////////////////
302
303 int ConstantColorShader::shade(Stroke& stroke) const
304 {
305         StrokeInternal::StrokeVertexIterator v, vend;
306         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
307                 v->attribute().setColor(_color[0], _color[1], _color[2]);
308                 v->attribute().setAlpha(_color[3]);
309         }
310         return 0;
311 }
312
313 int IncreasingColorShader::shade(Stroke& stroke) const
314 {
315         StrokeInternal::StrokeVertexIterator v, vend;
316         int n = stroke.strokeVerticesSize() - 1, yo;
317         float newcolor[4];
318         for (yo = 0, v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
319              v != vend;
320              ++v, ++yo)
321         {
322                 for (int i = 0; i < 4; ++i) {
323                         newcolor[i] = (1.0 - (float) yo / (float)n) * _colorMin[i] + (float)yo / (float)n * _colorMax[i];
324                 }
325                 v->attribute().setColor(newcolor[0], newcolor[1], newcolor[2]);
326                 v->attribute().setAlpha(newcolor[3]);
327         }
328         return 0;
329 }
330
331 ColorVariationPatternShader::ColorVariationPatternShader(const string pattern_name, bool stretch) : StrokeShader()
332 {
333         _stretch = stretch;
334         ImBuf *image = NULL;
335         vector<string> pathnames;
336         StringUtils::getPathName(TextureManager::Options::getPatternsPath(), pattern_name, pathnames);
337         for (vector<string>::const_iterator j = pathnames.begin(); j != pathnames.end(); ++j) {
338                 ifstream ifs(j->c_str());
339                 if (ifs.is_open()) {
340                         /* OCIO_TODO: support different input color space */
341                         image = IMB_loadiffname(j->c_str(), 0, NULL); //soc
342                         break;
343                 }
344         }
345         if (image == NULL)
346                 cerr << "Error: cannot find pattern \"" << pattern_name << "\" - check the path in the Options" << endl;
347         else
348                 convert(image, &_aVariation, _size);
349         IMB_freeImBuf(image);
350 }
351
352 int ColorVariationPatternShader::shade(Stroke& stroke) const
353 {
354         StrokeInternal::StrokeVertexIterator v, vend;
355         unsigned index;
356         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
357                 const float *originalColor = v->attribute().getColor();
358                 if (_stretch) {
359                         float tmp = v->u() * (_size - 1);
360                         index = (unsigned)floor(tmp);
361                         if ((tmp - index) > (index + 1 - tmp))
362                                 ++index;
363                 }
364                 else {
365                         index = (unsigned)floor(v->curvilinearAbscissa());
366                 }
367                 index %= _size;
368                 float r = _aVariation[index] * originalColor[0];
369                 float g = _aVariation[index] * originalColor[1];
370                 float b = _aVariation[index] * originalColor[2];
371                 v->attribute().setColor(r, g, b);
372         }
373         return 0;
374 }
375
376 int MaterialColorShader::shade(Stroke& stroke) const
377 {
378         Interface0DIterator v, vend;
379         Functions0D::MaterialF0D fun;
380         StrokeVertex *sv;
381         for (v = stroke.verticesBegin(), vend = stroke.verticesEnd(); v != vend; ++v) {
382                 if (fun(v) < 0)
383                         return -1;
384                 const float *diffuse = fun.result.diffuse();
385                 sv = dynamic_cast<StrokeVertex*>(&(*v));
386                 sv->attribute().setColor(diffuse[0] * _coefficient, diffuse[1] * _coefficient, diffuse[2] * _coefficient);
387                 sv->attribute().setAlpha(diffuse[3]);
388         }
389         return 0;
390 }
391
392
393 int CalligraphicColorShader::shade(Stroke& stroke) const
394 {
395         Interface0DIterator v;
396         Functions0D::VertexOrientation2DF0D fun;
397         StrokeVertex *sv;
398         for (v = stroke.verticesBegin(); !v.isEnd(); ++v) {
399                 if (fun(v) < 0)
400                         return -1;
401                 Vec2f vertexOri(fun.result);
402                 Vec2d ori2d(-vertexOri[1], vertexOri[0]);
403                 ori2d.normalizeSafe();
404                 real scal = ori2d * _orientation;
405                 sv = dynamic_cast<StrokeVertex*>(&(*v));
406                 if ((scal < 0))
407                         sv->attribute().setColor(0, 0, 0);
408                 else
409                         sv->attribute().setColor(1, 1, 1);
410         }
411         return 0;
412 }
413
414
415 ColorNoiseShader::ColorNoiseShader() : StrokeShader()
416 {
417         _amplitude = 1.0f;
418         _scale = 1.0f / 2.0f / (float)NB_VALUE_NOISE;
419 }
420
421 ColorNoiseShader::ColorNoiseShader(float iAmplitude, float iPeriod) : StrokeShader()
422 {
423         _amplitude = iAmplitude;
424         _scale = 1.0f / iPeriod / (float)NB_VALUE_NOISE;
425 }
426
427 int ColorNoiseShader::shade(Stroke& stroke) const
428 {
429         StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
430         real initU = v->strokeLength() * real(NB_VALUE_NOISE) + RandGen::drand48() * real(NB_VALUE_NOISE);
431
432         real bruit;
433         PseudoNoise mynoise;
434         for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
435                 bruit = mynoise.turbulenceSmooth(_scale * v->curvilinearAbscissa() + initU, 2); // 2 : nbOctaves
436                 const float *originalColor = v->attribute().getColor();
437                 float r = bruit * _amplitude + originalColor[0];
438                 float g = bruit * _amplitude + originalColor[1];
439                 float b = bruit * _amplitude + originalColor[2];
440                 v->attribute().setColor(r, g, b);
441         }
442
443         return 0;
444 }
445
446
447 //
448 //  Texture Shaders
449 //
450 ///////////////////////////////////////////////////////////////////////////////
451
452 int TextureAssignerShader::shade(Stroke& stroke) const
453 {
454 #if 0
455         getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::HUMID_MEDIUM);
456         getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::HUMID_MEDIUM);
457         getBrushTextureIndex(TEXTURES_DIR "/brushes/oil.bmp", Stroke::HUMID_MEDIUM);
458         getBrushTextureIndex(TEXTURES_DIR "/brushes/oilnoblend.bmp", Stroke::HUMID_MEDIUM);
459         getBrushTextureIndex(TEXTURES_DIR "/brushes/charcoalAlpha.bmp", Stroke::DRY_MEDIUM);
460         getBrushTextureIndex(TEXTURES_DIR "/brushes/washbrushAlpha.bmp", Stroke::DRY_MEDIUM);
461         getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueDryBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
462         getBrushTextureIndex(TEXTURES_DIR "/brushes/opaqueBrushAlpha.bmp", Stroke::OPAQUE_MEDIUM);
463 #endif
464
465         TextureManager *instance = TextureManager::getInstance();
466         if (!instance)
467                 return 0;
468         string pathname;
469         Stroke::MediumType mediumType;
470         bool hasTips = false;
471         switch (_textureId) {
472                 case 0:
473                         //pathname = TextureManager::Options::getBrushesPath() + "/charcoalAlpha.bmp";
474                         pathname = "/charcoalAlpha.bmp";
475                         mediumType = Stroke::HUMID_MEDIUM;
476                         hasTips = false;
477                         break;
478                 case 1:
479                         pathname = "/washbrushAlpha.bmp";
480                         mediumType = Stroke::HUMID_MEDIUM;
481                         hasTips = true;
482                         break;
483                 case 2:
484                         pathname = "/oil.bmp";
485                         mediumType = Stroke::HUMID_MEDIUM;
486                         hasTips = true;
487                         break;
488                 case 3:
489                         pathname = "/oilnoblend.bmp";
490                         mediumType = Stroke::HUMID_MEDIUM;
491                         hasTips = true;
492                         break;
493                 case 4:
494                         pathname = "/charcoalAlpha.bmp";
495                         mediumType = Stroke::DRY_MEDIUM;
496                         hasTips = false;
497                         break;
498                 case 5:
499                         mediumType = Stroke::DRY_MEDIUM;
500                         hasTips = true;
501                         break;
502                 case 6:
503                         pathname = "/opaqueDryBrushAlpha.bmp";
504                         mediumType = Stroke::OPAQUE_MEDIUM;
505                         hasTips = true;
506                         break;
507                 case 7:
508                         pathname = "/opaqueBrushAlpha.bmp";
509                         mediumType = Stroke::OPAQUE_MEDIUM;
510                         hasTips = true;
511                         break;
512                 default:
513                         pathname = "/smoothAlpha.bmp";
514                         mediumType = Stroke::OPAQUE_MEDIUM;
515                         hasTips = false;
516                         break;
517         }
518         unsigned int texId = instance->getBrushTextureIndex(pathname, mediumType);
519         stroke.setMediumType(mediumType);
520         stroke.setTips(hasTips);
521         stroke.setTextureId(texId);
522         return 0;
523 }
524
525 // FIXME
526 int StrokeTextureShader::shade(Stroke& stroke) const
527 {
528         TextureManager *instance = TextureManager::getInstance();
529         if (!instance)
530                 return 0;
531         string pathname = TextureManager::Options::getBrushesPath() + "/" + _texturePath;
532         unsigned int texId = instance->getBrushTextureIndex(pathname, _mediumType);
533         stroke.setMediumType(_mediumType);
534         stroke.setTips(_tips);
535         stroke.setTextureId(texId);
536         return 0;
537 }
538
539 //
540 //  Geometry Shaders
541 //
542 ///////////////////////////////////////////////////////////////////////////////
543
544 int BackboneStretcherShader::shade(Stroke& stroke) const
545 {
546         float l = stroke.getLength2D();
547         if (l <= 1.0e-6)
548                 return 0;
549
550         StrokeInternal::StrokeVertexIterator v0 = stroke.strokeVerticesBegin();
551         StrokeInternal::StrokeVertexIterator v1 = v0;
552         ++v1;
553         StrokeInternal::StrokeVertexIterator vn = stroke.strokeVerticesEnd();
554         --vn;
555         StrokeInternal::StrokeVertexIterator vn_1 = vn;
556         --vn_1;
557
558
559         Vec2d first((v0)->x(), (v0)->y());
560         Vec2d last((vn)->x(), (vn)->y());
561
562         Vec2d d1(first - Vec2d((v1)->x(), (v1)->y()));
563         d1.normalize();
564         Vec2d dn(last - Vec2d((vn_1)->x(), (vn_1)->y()));
565         dn.normalize();
566
567         Vec2d newFirst(first + _amount * d1);
568         (v0)->setPoint(newFirst[0], newFirst[1]);
569         Vec2d newLast(last + _amount * dn);
570         (vn)->setPoint(newLast[0], newLast[1]);
571
572         stroke.UpdateLength();
573         return 0;
574 }
575
576 int SamplingShader::shade(Stroke& stroke) const
577 {
578         stroke.Resample(_sampling);
579         stroke.UpdateLength();
580         return 0;
581 }
582
583 int ExternalContourStretcherShader::shade(Stroke& stroke) const
584 {
585         //float l = stroke.getLength2D();
586         Interface0DIterator it;
587         Functions0D::Normal2DF0D fun;
588         StrokeVertex *sv;
589         for (it = stroke.verticesBegin(); !it.isEnd(); ++it) {
590                 if (fun(it) < 0)
591                         return -1;
592                 Vec2f n(fun.result);
593                 sv = dynamic_cast<StrokeVertex*>(&(*it));
594                 Vec2d newPoint(sv->x() + _amount * n.x(), sv->y() + _amount * n.y());
595                 sv->setPoint(newPoint[0], newPoint[1]);
596         }
597         stroke.UpdateLength();
598         return 0;
599 }
600
601 int BSplineShader::shade(Stroke& stroke) const
602 {
603         if (stroke.strokeVerticesSize() < 4)
604                 return 0;
605
606         // Find the new vertices
607         vector<Vec2d> newVertices;
608         double t = 0.0;
609         float _sampling = 5.0f;
610
611         StrokeInternal::StrokeVertexIterator p0, p1, p2, p3, end;
612         p0 = stroke.strokeVerticesBegin();
613         p1 = p0;
614         p2 = p1;
615         p3 = p2;
616         end = stroke.strokeVerticesEnd();
617         double a[4], b[4];
618         int n = 0;
619         while (p1 != end) {
620 #if 0
621                 if (p1 == end)
622                         p1 = p0;
623 #endif
624                 if (p2 == end)
625                         p2 = p1;
626                 if (p3 == end)
627                         p3 = p2;
628                 // compute new matrix
629                 a[0] = (-(p0)->x() + 3 * (p1)->x() - 3 * (p2)->x() + (p3)->x()) / 6.0;
630                 a[1] = (3 * (p0)->x() - 6 * (p1)->x() + 3 * (p2)->x()) / 6.0;
631                 a[2] = (-3 * (p0)->x() + 3 * (p2)->x()) / 6.0;
632                 a[3] = ((p0)->x() + 4 * (p1)->x() + (p2)->x()) / 6.0;
633
634                 b[0] = (-(p0)->y() + 3 * (p1)->y() - 3 * (p2)->y() + (p3)->y()) / 6.0;
635                 b[1] = (3 * (p0)->y() - 6 * (p1)->y() + 3 * (p2)->y()) / 6.0;
636                 b[2] = (-3 * (p0)->y() + 3 * (p2)->y()) / 6.0;
637                 b[3] = ((p0)->y() + 4 * (p1)->y() + (p2)->y()) / 6.0;
638
639                 // draw the spline depending on resolution:
640                 Vec2d p1p2((p2)->x() - (p1)->x(), (p2)->y() - (p1)->y());
641                 double norm = p1p2.norm();
642                 //t = _sampling / norm;
643                 t = 0;
644                 while (t < 1) {
645                         newVertices.push_back(Vec2d((a[3] + t * (a[2] + t * (a[1] + t * a[0]))),
646                                                     (b[3] + t * (b[2] + t * (b[1] + t * b[0])))));
647                         t = t + _sampling / norm;
648                 }
649                 if (n > 2) {
650                         ++p0;
651                         ++p1;
652                         ++p2;
653                         ++p3;
654                 }
655                 else {
656                         if (n == 0)
657                                 ++p3;
658                         if (n == 1) {
659                                 ++p2;
660                                 ++p3;
661                         }
662                         if (n == 2) {
663                                 ++p1;
664                                 ++p2;
665                                 ++p3;
666                         }
667                         ++n;
668                 }
669         }
670         //last point:
671         newVertices.push_back(Vec2d((p0)->x(), (p0)->y()));
672
673         int originalSize = newVertices.size();
674         _sampling = stroke.ComputeSampling(originalSize);
675
676         // Resample and set x,y coordinates
677         stroke.Resample(_sampling);
678         int newsize = stroke.strokeVerticesSize();
679
680         int nExtraVertex = 0;
681         if (newsize < originalSize) {
682                 cerr << "Warning: unsufficient resampling" << endl;
683         }
684         else {
685                 nExtraVertex = newsize - originalSize;
686         }
687
688         // assigns the new coordinates:
689         vector<Vec2d>::iterator p = newVertices.begin(), pend = newVertices.end();
690         vector<Vec2d>::iterator last = p;
691         n = 0;
692         StrokeInternal::StrokeVertexIterator it, itend;
693         for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd();
694              (it != itend) && (p != pend);
695              ++it, ++p, ++n)
696         {
697                 it->setX(p->x());
698                 it->setY(p->y());
699                 last = p;
700         }
701
702         // nExtraVertex should stay unassigned
703         for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) {
704                 it->setX(last->x());
705                 it->setY(last->y());
706                 if (it.isEnd()) {
707                         // XXX Shouldn't we break in this case???
708                         cerr << "Warning: Problem encountered while creating B-spline" << endl;
709                 }
710         }
711         stroke.UpdateLength();
712         return 0;
713 }
714
715 //!! Bezier curve stroke shader
716 int BezierCurveShader::shade(Stroke& stroke) const
717 {
718         if (stroke.strokeVerticesSize() < 4)
719                 return 0;
720
721         // Build the Bezier curve from this set of data points:
722         vector<Vec2d> data;
723         StrokeInternal::StrokeVertexIterator v = stroke.strokeVerticesBegin(), vend;
724         data.push_back(Vec2d(v->x(), v->y())); //first one
725         StrokeInternal::StrokeVertexIterator previous = v;
726         ++v;
727         for (vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
728                 if (!((fabs(v->x() - (previous)->x()) < M_EPSILON) && ((fabs(v->y() - (previous)->y()) < M_EPSILON))))
729                         data.push_back(Vec2d(v->x(), v->y()));
730                 previous = v;
731         }
732
733 #if 0
734         Vec2d tmp;
735         bool equal = false;
736         if (data.front() == data.back()) {
737                 tmp = data.back();
738                 data.pop_back();
739                 equal = true;
740         }
741 #endif
742         // here we build the bezier curve
743         BezierCurve bcurve(data, _error);
744
745         // bad performances are here !!! // FIXME
746         vector<Vec2d> CurveVertices;
747         vector<BezierCurveSegment*>& bsegments = bcurve.segments();
748         vector<BezierCurveSegment*>::iterator s = bsegments.begin(), send;
749         vector<Vec2d>& segmentsVertices = (*s)->vertices();
750         vector<Vec2d>::iterator p, pend;
751         // first point
752         CurveVertices.push_back(segmentsVertices[0]);
753         for (send = bsegments.end(); s != send; ++s) {
754                 segmentsVertices = (*s)->vertices();
755                 p = segmentsVertices.begin();
756                 ++p;
757                 for (pend = segmentsVertices.end(); p != pend; ++p) {
758                         CurveVertices.push_back((*p));
759                 }
760         }
761
762 #if 0
763         if (equal) {
764                 if (data.back() == data.front()) {
765                         vector<Vec2d>::iterator d = data.begin(), dend;
766                         if (G.debug & G_DEBUG_FREESTYLE) {
767                                 cout << "ending point = starting point" << endl;
768                                 cout << "---------------DATA----------" << endl;
769                                 for (dend = data.end(); d != dend; ++d) {
770                                         cout << d->x() << "-" << d->y() << endl;
771                                 }
772                                 cout << "--------------BEZIER RESULT----------" << endl;
773                                 for (d = CurveVertices.begin(), dend = CurveVertices.end(); d != dend; ++d) {
774                                         cout << d->x() << "-" << d->y() << endl;
775                                 }
776                         }
777                 }
778         }
779 #endif
780
781         // Resample the Stroke depending on the number of vertices of the bezier curve:
782         int originalSize = CurveVertices.size();
783 #if 0
784         float sampling = stroke.ComputeSampling(originalSize);
785         stroke.Resample(sampling);
786 #endif
787         stroke.Resample(originalSize);
788         int newsize = stroke.strokeVerticesSize();
789         int nExtraVertex = 0;
790         if (newsize < originalSize) {
791                 cerr << "Warning: unsufficient resampling" << endl;
792         }
793         else {
794 #if 0
795                 if (G.debug & G_DEBUG_FREESTYLE) {
796                         cout << "Oversampling" << endl;
797                 }
798 #endif
799                 nExtraVertex = newsize - originalSize;
800                 if (nExtraVertex != 0) {
801                         if (G.debug & G_DEBUG_FREESTYLE) {
802                                 cout << "Bezier Shader : Stroke " << stroke.getId() << " have not been resampled" << endl;
803                         }
804                 }
805         }
806
807         // assigns the new coordinates:
808         p = CurveVertices.begin();
809         vector<Vec2d>::iterator last = p;
810         int n;
811         StrokeInternal::StrokeVertexIterator it, itend;
812 #if 0
813         for (; p != pend; ++n, ++p);
814 #endif
815         for (n = 0, it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd(), pend = CurveVertices.end();
816              (it != itend) && (p != pend);
817              ++it, ++p, ++n)
818         {
819                 it->setX(p->x());
820                 it->setY(p->y());
821 #if 0
822                 double x = p->x();
823                 double y = p->y();
824                 if (G.debug & G_DEBUG_FREESTYLE) {
825                         cout << "x = " << x << "-" << "y = " << y << endl;
826                 }
827 #endif
828                 last = p;
829         }
830         stroke.UpdateLength();
831
832         // Deal with extra vertices:
833         if (nExtraVertex == 0)
834                 return 0;
835
836         // nExtraVertex should stay unassigned
837         vector<StrokeAttribute> attributes;
838         vector<StrokeVertex*> verticesToRemove;
839         for (int i = 0; i < nExtraVertex; ++i, ++it, ++n) {
840                 verticesToRemove.push_back(&(*it));
841                 if (it.isEnd()) {
842                         // XXX Shocking! :P Shouldn't we break in this case???
843                         if (G.debug & G_DEBUG_FREESTYLE) {
844                                 cout << "fucked up" << endl;
845                         }
846                 }
847         }
848         for (it = stroke.strokeVerticesBegin(); it != itend; ++it) {
849                 attributes.push_back(it->attribute());
850         }
851
852         for (vector<StrokeVertex*>::iterator vr = verticesToRemove.begin(), vrend = verticesToRemove.end();
853              vr != vrend;
854              ++vr)
855         {
856                 stroke.RemoveVertex(*vr);
857         }
858
859         vector<StrokeAttribute>::iterator a = attributes.begin(), aend = attributes.end();
860         int index = 0;
861         int index1 = (int)floor((float)originalSize / 2.0);
862         int index2 = index1 + nExtraVertex;
863         for (it = stroke.strokeVerticesBegin(), itend = stroke.strokeVerticesEnd();
864              (it != itend) && (a != aend);
865              ++it)
866         {
867                 (it)->setAttribute(*a);
868                 if ((index <= index1) || (index > index2))
869                         ++a;
870                         ++index;
871         }
872         return 0;
873 }
874
875 int InflateShader::shade(Stroke& stroke) const
876 {
877         // we're computing the curvature variance of the stroke. (Combo 5)
878         // If it's too high, forget about it
879         Functions1D::Curvature2DAngleF1D fun;
880         if (fun(stroke) < 0)
881                 return -1;
882         if (fun.result > _curvatureThreshold)
883                 return 0;
884
885         Functions0D::VertexOrientation2DF0D ori_fun;
886         Functions0D::Curvature2DAngleF0D curv_fun;
887         Functions1D::Normal2DF1D norm_fun;
888         Interface0DIterator it;
889         StrokeVertex *sv;
890         for (it = stroke.verticesBegin(); !it.isEnd(); ++it) {
891                 if (ori_fun(it) < 0)
892                         return -1;
893                 Vec2f ntmp(ori_fun.result);
894                 Vec2f n(ntmp.y(), -ntmp.x());
895                 if (norm_fun(stroke) < 0)
896                         return -1;
897                 Vec2f strokeN(norm_fun.result);
898                 if (n * strokeN < 0) {
899                         n[0] = -n[0];
900                         n[1] = -n[1];
901                 }
902                 sv = dynamic_cast<StrokeVertex*>(&(*it));
903                 float u = sv->u();
904                 float t = 4.0f * (0.25f - (u - 0.5) * (u - 0.5));
905                 if (curv_fun(it) < 0)
906                         return -1;
907                 float curvature_coeff = (M_PI - curv_fun.result) / M_PI;
908                 Vec2d newPoint(sv->x() + curvature_coeff * t * _amount * n.x(),
909                                sv->y() + curvature_coeff * t * _amount * n.y());
910                 sv->setPoint(newPoint[0], newPoint[1]);
911         }
912         stroke.UpdateLength();
913         return 0;
914 }
915
916 class CurvePiece
917 {
918 public:
919         StrokeInternal::StrokeVertexIterator _begin;
920         StrokeInternal::StrokeVertexIterator _last;
921         Vec2d A;
922         Vec2d B;
923         int size;
924         float _error;
925
926         CurvePiece(StrokeInternal::StrokeVertexIterator b, StrokeInternal::StrokeVertexIterator l, int iSize)
927         {
928                 _begin = b;
929                 _last = l;
930                 A = Vec2d((_begin)->x(), (_begin)->y());
931                 B = Vec2d((_last)->x(), (_last)->y());
932                 size = iSize;
933         }
934
935         float error()
936         {
937                 float maxE = 0.0f;
938                 for (StrokeInternal::StrokeVertexIterator it = _begin; it != _last; ++it) {
939                         Vec2d P(it->x(), it->y());
940                         float d = GeomUtils::distPointSegment(P, A, B);
941                         if (d > maxE)
942                                 maxE = d;
943                 }
944                 _error = maxE;
945                 return maxE;
946         }
947
948         //! Subdivides the curve into two pieces.
949         //  The first piece is this same object (modified)
950         //  The second piece is returned by the method
951         CurvePiece *subdivide()
952         {
953                 StrokeInternal::StrokeVertexIterator it = _begin;
954                 int ns = size - 1; // number of segments (ns > 1)
955                 int ns1 = ns / 2;
956                 int ns2 = ns - ns1;
957                 for (int i = 0; i < ns1; ++it, ++i);
958
959                 CurvePiece *second = new CurvePiece(it, _last, ns2 + 1);
960                 size = ns1 + 1;
961                 _last = it;
962                 B = Vec2d((_last)->x(), (_last)->y());
963                 return second;
964         }
965 };
966
967 int PolygonalizationShader::shade(Stroke& stroke) const
968 {
969         vector<CurvePiece*> _pieces;
970         vector<CurvePiece*> _results;
971         vector<CurvePiece*>::iterator cp, cpend;
972
973         // Compute first approx:
974         StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin();
975         StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd();
976         --b;
977         int size = stroke.strokeVerticesSize();
978
979         CurvePiece *piece = new CurvePiece(a, b, size);
980         _pieces.push_back(piece);
981
982         while (!_pieces.empty()) {
983                 piece = _pieces.back();
984                 _pieces.pop_back();
985                 if (piece->size > 2 && piece->error() > _error) {
986                         CurvePiece *second = piece->subdivide();
987                         _pieces.push_back(second);
988                         _pieces.push_back(piece);
989                 }
990                 else {
991                         _results.push_back(piece);
992                 }
993         }
994
995         // actually modify the geometry for each piece:
996         for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) {
997                 a = (*cp)->_begin;
998                 b = (*cp)->_last;
999                 Vec2d u = (*cp)->B - (*cp)->A;
1000                 Vec2d n(u[1], -u[0]);
1001                 n.normalize();
1002                 //Vec2d n(0, 0);
1003                 float offset = ((*cp)->_error);
1004                 StrokeInternal::StrokeVertexIterator v;
1005                 for (v = a; v != b; ++v) {
1006                         v->setPoint((*cp)->A.x() + v->u() * u.x() + n.x() * offset,
1007                                     (*cp)->A.y() + v->u() * u.y() + n.y() * offset);
1008                 }
1009 #if 0
1010                 u.normalize();
1011                 (*a)->setPoint((*a)->x() - u.x() * 10, (*a)->y() - u.y() * 10);
1012 #endif
1013         }
1014         stroke.UpdateLength();
1015
1016         // delete stuff
1017         for (cp = _results.begin(), cpend = _results.end(); cp != cpend; ++cp) {
1018                 delete (*cp);
1019         }
1020         _results.clear();
1021         return 0;
1022 }
1023
1024 int GuidingLinesShader::shade(Stroke& stroke) const
1025 {
1026         Functions1D::Normal2DF1D norm_fun;
1027         StrokeInternal::StrokeVertexIterator a = stroke.strokeVerticesBegin();
1028         StrokeInternal::StrokeVertexIterator b = stroke.strokeVerticesEnd();
1029         --b;
1030         int size = stroke.strokeVerticesSize();
1031         CurvePiece piece(a, b, size);
1032
1033         Vec2d u = piece.B - piece.A;
1034         Vec2f n(u[1], -u[0]);
1035         n.normalize();
1036         if (norm_fun(stroke) < 0)
1037                 return -1;
1038         Vec2f strokeN(norm_fun.result);
1039         if (n * strokeN < 0) {
1040                 n[0] = -n[0];
1041                 n[1] = -n[1];
1042         }
1043         float offset = (piece.error()) / 2.0f * _offset;
1044         StrokeInternal::StrokeVertexIterator v, vend;
1045         for (v = a, vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
1046                 v->setPoint(piece.A.x() + v->u() * u.x() + n.x() * offset,
1047                             piece.A.y() + v->u() * u.y() + n.y() * offset);
1048         }
1049         stroke.UpdateLength();
1050         return 0;
1051 }
1052
1053 /////////////////////////////////////////
1054 //
1055 //  Tip Remover
1056 //
1057 /////////////////////////////////////////
1058
1059
1060 TipRemoverShader::TipRemoverShader(real tipLength) : StrokeShader()
1061 {
1062         _tipLength = tipLength;
1063 }
1064
1065 int TipRemoverShader::shade(Stroke& stroke) const
1066 {
1067         int originalSize = stroke.strokeVerticesSize();
1068
1069         if (originalSize < 4)
1070                 return 0;
1071
1072         StrokeInternal::StrokeVertexIterator v, vend;
1073         vector<StrokeVertex*> verticesToRemove;
1074         vector<StrokeAttribute> oldAttributes;
1075         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd(); v != vend; ++v) {
1076                 if ((v->curvilinearAbscissa() < _tipLength) || (v->strokeLength() - v->curvilinearAbscissa() < _tipLength)) {
1077                         verticesToRemove.push_back(&(*v));
1078                 }
1079                 oldAttributes.push_back(v->attribute());
1080         }
1081
1082         if (originalSize - verticesToRemove.size() < 2)
1083                 return 0;
1084
1085         vector<StrokeVertex*>::iterator sv, svend;
1086         for (sv = verticesToRemove.begin(), svend = verticesToRemove.end(); sv != svend; ++sv) {
1087                 stroke.RemoveVertex((*sv));
1088         }
1089
1090         // Resample so that our new stroke have the same number of vertices than before
1091         stroke.Resample(originalSize);
1092
1093         if ((int)stroke.strokeVerticesSize() != originalSize) //soc
1094                 cerr << "Warning: resampling problem" << endl;
1095
1096         // assign old attributes to new stroke vertices:
1097         vector<StrokeAttribute>::iterator a = oldAttributes.begin(), aend = oldAttributes.end();
1098 #if 0
1099         if (G.debug & G_DEBUG_FREESTYLE) {
1100                 cout << "-----------------------------------------------" << endl;
1101         }
1102 #endif
1103         for (v = stroke.strokeVerticesBegin(), vend = stroke.strokeVerticesEnd();
1104              (v != vend) && (a != aend);
1105              ++v, ++a)
1106         {
1107                 v->setAttribute(*a);
1108 #if 0
1109                 if (G.debug & G_DEBUG_FREESTYLE) {
1110                         cout << "thickness = " << (*a).getThickness()[0] << "-" << (*a).getThickness()[1] << endl;
1111                 }
1112 #endif
1113         }
1114         // we're done!
1115         return 0;
1116 }
1117
1118 int streamShader::shade(Stroke& stroke) const
1119 {
1120         if (G.debug & G_DEBUG_FREESTYLE) {
1121                 cout << stroke << endl;
1122         }
1123         return 0;
1124 }
1125
1126 int fstreamShader::shade(Stroke& stroke) const
1127 {
1128         _stream << stroke << endl;
1129         return 0;
1130 }
1131
1132 } // end of namespace StrokeShaders
1133
1134 } /* namespace Freestyle */