// // Filename : BasicStrokeShaders.h // Author : Stephane Grabli // Purpose : Class gathering basic stroke shaders // Date of creation : 17/12/2002 // /////////////////////////////////////////////////////////////////////////////// // // Copyright (C) : Please refer to the COPYRIGHT file distributed // with this source distribution. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // as published by the Free Software Foundation; either version 2 // of the License, or (at your option) any later version. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // /////////////////////////////////////////////////////////////////////////////// #ifndef BASIC_STROKE_SHADERS_H # define BASIC_STROKE_SHADERS_H # include "Stroke.h" # include "../geometry/Geom.h" # include "../geometry/Bezier.h" # include "StrokeShader.h" # include using namespace std; using namespace Geometry; namespace StrokeShaders { // // Thickness modifiers // ////////////////////////////////////////////////////// /*! [ Thickness Shader ]. * Assigns an absolute constant thickness to every * vertices of the Stroke. */ class LIB_STROKE_EXPORT ConstantThicknessShader : public StrokeShader { public: /*! Builds the shader. * \param thickness * The thickness that must be assigned * to the stroke. */ ConstantThicknessShader(float thickness) : StrokeShader() { _thickness = thickness; } /*! Destructor. */ virtual ~ConstantThicknessShader() {} /*! Returns the string "ConstantThicknessShader".*/ virtual string getName() const { return "ConstantThicknessShader"; } /*! The shading method. */ virtual void shade(Stroke& stroke) const; private: float _thickness; }; /* [ Thickness Shader ]. * Assigns an absolute constant external thickness to every * vertices of the Stroke. The external thickness of a point * is its thickness from the point to the strip border * in the direction pointing outside the object the * Stroke delimitates. */ class LIB_STROKE_EXPORT ConstantExternThicknessShader : public StrokeShader { public: ConstantExternThicknessShader(float thickness) : StrokeShader() { _thickness = thickness; } virtual ~ConstantExternThicknessShader() {} virtual string getName() const { return "ConstantExternThicknessShader"; } virtual void shade(Stroke& stroke) const; private: float _thickness; }; /*! [ Thickness Shader ]. * Assigns thicknesses values such as the thickness * increases from a thickness value A to a thickness value B * between the first vertex to the midpoint vertex and * then decreases from B to a A between this midpoint vertex * and the last vertex. * The thickness is linearly interpolated from A to B. */ class LIB_STROKE_EXPORT IncreasingThicknessShader : public StrokeShader { public: /*! Builds the shader. * \param iThicknessMin * The first thickness value. * \param iThicknessMax * The second thickness value. */ IncreasingThicknessShader(float iThicknessMin, float iThicknessMax) : StrokeShader() { _ThicknessMin = iThicknessMin; _ThicknessMax = iThicknessMax; } /*! Destructor.*/ virtual ~IncreasingThicknessShader() {} /*! The shading method. */ virtual void shade(Stroke& stroke) const; private: float _ThicknessMin; float _ThicknessMax; }; /*! [ Thickness shader ]. * Same as previous but * here we allow the user to control the ratio thickness/length so that * we don't get fat short lines */ class LIB_STROKE_EXPORT ConstrainedIncreasingThicknessShader : public StrokeShader { private: float _ThicknessMin; float _ThicknessMax; float _ratio; public: /*! Builds the shader. * \param iThicknessMin * The first thickness value. * \param iThicknessMax * The second thickness value. * \param iRatio * The ration thickness/length we don't want to * exceed. */ ConstrainedIncreasingThicknessShader(float iThicknessMin, float iThicknessMax, float iRatio) : StrokeShader() { _ThicknessMin = iThicknessMin; _ThicknessMax = iThicknessMax; _ratio = iRatio; } /*! Destructor.*/ virtual ~ConstrainedIncreasingThicknessShader() {} /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; /* [ Thickness Shader ]. * Modifys the thickness in a relative way * depending on its length. */ class LIB_STROKE_EXPORT LengthDependingThicknessShader : public StrokeShader { private: float _minThickness; float _maxThickness; // We divide the strokes in 4 categories: // l > 300 // 100 < l < 300 // 50 < l < 100 // l < 50 public: LengthDependingThicknessShader(float iMinThickness, float iMaxThickness) : StrokeShader() { _minThickness = iMinThickness; _maxThickness = iMaxThickness; } virtual ~LengthDependingThicknessShader() {} virtual void shade(Stroke& stroke) const; }; /*! [ Thickness Shader ]. * Applys a pattern (texture) to vary thickness. * The new thicknesses are the result of the multiplication * of the pattern and the original thickness */ class LIB_STROKE_EXPORT ThicknessVariationPatternShader : public StrokeShader { public: /*! Builds the shader. * \param pattern_name * The texture file name. * \param iMinThickness * The minimum thickness we don't want to exceed. * \param iMaxThickness * The maximum thickness we don't want to exceed. * \param stretch * Tells whether the pattern texture must * be stretched or repeted to fit the stroke. */ ThicknessVariationPatternShader(const string pattern_name, float iMinThickness = 1.f, float iMaxThickness = 5.f, bool stretch = true); /*! Destructor.*/ virtual ~ThicknessVariationPatternShader() { if(0 != _aThickness) { delete [] _aThickness; _aThickness = 0; } } /*! The shading method. */ virtual void shade(Stroke& stroke) const; private: float* _aThickness; // array of thickness values, in % of the max (i.e comprised between 0 and 1) unsigned _size; float _minThickness; float _maxThickness; bool _stretch; }; /*! [ Thickness Shader ]. * Adds some noise to the stroke thickness. * \see \htmlonly noise/noise.html\endhtmlonly */ class LIB_STROKE_EXPORT ThicknessNoiseShader : public StrokeShader { private: float _amplitude; float _scale; public: ThicknessNoiseShader(); /*! Builds a Thickness Noise Shader * \param iAmplitude * The amplitude of the noise signal * \param iPeriod * The period of the noise signal */ ThicknessNoiseShader(float iAmplitude, float iPeriod); /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; // // Color shaders // ///////////////////////////////////////////////////////// /*! [ Color Shader ]. * Assigns a constant color to every vertices of the Stroke. */ class LIB_STROKE_EXPORT ConstantColorShader : public StrokeShader { public: /*! Builds the shader from a user-specified color. * \param iR * The red component * \param iG * The green component * \param iB * The blue component * \param iAlpha * The alpha value */ ConstantColorShader(float iR, float iG, float iB, float iAlpha=1.f) : StrokeShader() { _color[0] = iR; _color[1] = iG; _color[2] = iB; _color[3] = iAlpha; } virtual string getName() const { return "ConstantColorShader"; } /*! The shading method. */ virtual void shade(Stroke& stroke) const; private: float _color[4]; }; /*! [ Color Shader ]. * Assigns a varying color to the stroke. * The user specifies 2 colors A and B. The stroke * color will change linearly from A to B between the * first and the last vertex. */ class LIB_STROKE_EXPORT IncreasingColorShader : public StrokeShader { private: float _colorMin[4]; float _colorMax[4]; public: /*! Builds the shader from 2 user-specified colors. * \param iRm * The first color red component * \param iGm * The first color green component * \param iBm * The first color blue component * \param iAlpham * The first color alpha value * \param iRM * The second color red component * \param iGM * The second color green component * \param iBM * The second color blue component * \param iAlphaM * The second color alpha value */ IncreasingColorShader(float iRm, float iGm, float iBm, float iAlpham, float iRM, float iGM, float iBM, float iAlphaM) : StrokeShader() { _colorMin[0] = iRm; _colorMin[1] = iGm; _colorMin[2] = iBm; _colorMin[3] = iAlpham; _colorMax[0] = iRM; _colorMax[1] = iGM; _colorMax[2] = iBM; _colorMax[3] = iAlphaM; } /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; /*! [ Color Shader ]. * Applys a pattern to vary original color. * The new color is the result of the multiplication * of the pattern and the original color */ class LIB_STROKE_EXPORT ColorVariationPatternShader : public StrokeShader { public: /*! Builds the shader from the pattern texture file name. * \param pattern_name * The file name of the texture file to use as pattern * \param stretch * Tells whether the texture must be strecthed or repeted * to fit the stroke. */ ColorVariationPatternShader(const string pattern_name, bool stretch = true); /*! Destructor */ virtual ~ColorVariationPatternShader() { if(0 != _aVariation) { delete [] _aVariation; _aVariation = 0; } } /*! The shading method. */ virtual void shade(Stroke& stroke) const; private: float* _aVariation; // array of coef values, in % of the max (i.e comprised between 0 and 1) unsigned _size; bool _stretch; }; /* [ Color Shader ]. * Assigns a color to the stroke depending * on the material of the shape to which ot belongs * to. (Disney shader) */ class LIB_STROKE_EXPORT MaterialColorShader : public StrokeShader { private: float _coefficient; public: MaterialColorShader(float coeff=1.f) : StrokeShader() {_coefficient=coeff;} virtual void shade(Stroke& stroke) const; }; class LIB_STROKE_EXPORT CalligraphicColorShader : public StrokeShader { private: int _textureId; Vec2d _orientation; public: CalligraphicColorShader( const Vec2d &iOrientation) : StrokeShader() { _orientation=iOrientation; _orientation.normalize(); } virtual void shade(Stroke& stroke) const; }; /*! [ Color Shader ]. * Shader to add noise to the stroke colors. */ class LIB_STROKE_EXPORT ColorNoiseShader : public StrokeShader { private: float _amplitude; float _scale; public: ColorNoiseShader(); /*! Builds a Color Noise Shader * \param iAmplitude * The amplitude of the noise signal * \param iPeriod * The period of the noise signal */ ColorNoiseShader(float iAmplitude, float iPeriod); /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; // // Texture Shaders // /////////////////////////////////////////////////////////////////////////////// /*! [ Texture Shader ]. * Assigns a texture to the stroke in order to simulate * its marks system. This shader takes as input an integer value * telling which texture and blending mode to use among a set of * predefined textures. * Here are the different presets: * 0) -> /brushes/charcoalAlpha.bmp, HUMID_MEDIUM * 1) -> /brushes/washbrushAlpha.bmp, HUMID_MEDIUM * 2) -> /brushes/oil.bmp, HUMID_MEDIUM * 3) -> /brushes/oilnoblend.bmp, HUMID_MEDIUM * 4) -> /brushes/charcoalAlpha.bmp, DRY_MEDIUM * 5) -> /brushes/washbrushAlpha.bmp, DRY_MEDIUM * 6) -> /brushes/opaqueDryBrushAlpha.bmp, OPAQUE_MEDIUM * 7) -> /brushes/opaqueBrushAlpha.bmp, Stroke::OPAQUE_MEDIUM * Any other value will lead to the following preset: * default) -> /brushes/smoothAlpha.bmp, OPAQUE_MEDIUM. */ class LIB_STROKE_EXPORT TextureAssignerShader : public StrokeShader // FIXME { private: int _textureId; public: /*! Builds the shader. * \param id * The number of the preset to use. */ TextureAssignerShader(int id) : StrokeShader() { _textureId = id; } /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /*! [ Texture Shader ]. * Assigns a texture and a blending mode to the stroke * in order to simulate its marks system. */ class LIB_STROKE_EXPORT StrokeTextureShader : public StrokeShader { private: string _texturePath; Stroke::MediumType _mediumType; bool _tips; // 0 or 1 public: /*! Builds the shader from the texture file name and the blending mode to use. * \param textureFile * The the texture file name. * \attention The textures must be placed in the $FREESTYLE_DIR/data/textures/brushes * directory. * \param mediumType * The medium type and therefore, the blending mode that must * be used for the rendering of this stroke. * \param iTips * Tells whether the texture includes tips or not. * If it is the case, the texture image must respect the following * format: * \verbatim * __________ * | | * | A | * |__________| * | | | * | B | C | * |_____|____| * * \endverbatim * - A : The stroke's corpus texture * - B : The stroke's left extremity texture * - C : The stroke's right extremity texture */ StrokeTextureShader(const string textureFile, Stroke::MediumType mediumType = Stroke::OPAQUE_MEDIUM, bool iTips = false) : StrokeShader() { _texturePath = textureFile; _mediumType = mediumType; _tips = iTips; } /*! The shading method */ virtual void shade(Stroke& stroke) const; }; // // Geometry Shaders // /////////////////////////////////////////////////////////////////////////////// /*! [ Geometry Shader ]. * Stretches the stroke at its two extremities and following the * respective directions: v(1)v(0) and v(n-1)v(n). */ class LIB_STROKE_EXPORT BackboneStretcherShader : public StrokeShader { private: float _amount; public: /*! Builds the shader. * \param iAmount * The stretching amount value. */ BackboneStretcherShader(float iAmount=2.f) : StrokeShader() { _amount = iAmount; } /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /*! [ Geometry Shader. ] * Resamples the stroke. * @see Stroke::Resample(float). */ class LIB_STROKE_EXPORT SamplingShader: public StrokeShader { private: float _sampling; public: /*! Builds the shader. * \param sampling * The sampling to use for the * stroke resampling */ SamplingShader(float sampling) : StrokeShader() { _sampling = sampling; } /*! The shading method */ virtual void shade(Stroke& stroke) const; }; class LIB_STROKE_EXPORT ExternalContourStretcherShader : public StrokeShader { private: float _amount; public: ExternalContourStretcherShader(float iAmount=2.f) : StrokeShader() { _amount = iAmount; } virtual void shade(Stroke& stroke) const; }; // B-Spline stroke shader class LIB_STROKE_EXPORT BSplineShader: public StrokeShader { public: BSplineShader() : StrokeShader() {} virtual void shade(Stroke& stroke) const; }; // Bezier curve stroke shader /*! [ Geometry Shader ]. * Transforms the stroke backbone geometry * so that it corresponds to a Bezier Curve * approximation of the original backbone geometry. * @see \htmlonly bezier/bezier.html \endhtmlonly */ class LIB_STROKE_EXPORT BezierCurveShader : public StrokeShader { private: float _error; public: /*! Builds the shader. * \param error * The error we're allowing for the approximation. * This error is the max distance allowed between * the new curve and the original geometry. */ BezierCurveShader(float error = 4.0) : StrokeShader() {_error=error;} /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /* Shader to inflate the curves. It keeps the extreme * points positions and moves the other ones along * the 2D normal. The displacement value is proportional * to the 2d curvature at the considered point (the higher * the curvature, the smaller the displacement) and to a value * specified by the user. */ class LIB_STROKE_EXPORT InflateShader : public StrokeShader { private: float _amount; float _curvatureThreshold; public: /*! Builds an inflate shader * \param iAmount * A multiplicative coefficient that * acts on the amount and direction of displacement * \param iThreshold * The curves having a 2d curvature > iThreshold * at one of their points is not inflated */ InflateShader(float iAmount,float iThreshold) : StrokeShader() { _amount = iAmount; _curvatureThreshold = iThreshold; } /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /*! [ Geometry Shader ]. * Shader to modify the Stroke geometry so that * it looks more "polygonal". * The basic idea is to start from the * minimal stroke approximation consisting in * a line joining the first vertex to the last one and * to subdivide using the original stroke vertices * until a certain error is reached. */ class LIB_STROKE_EXPORT PolygonalizationShader : public StrokeShader { private: float _error; public: /*! Builds the shader. * \param iError * The error we want our polygonal approximation * to have with respect to the original geometry. * The smaller, the closer the new stroke to * the orinal one. * This error corresponds to the maximum distance * between the new stroke and the old one. */ PolygonalizationShader(float iError) : StrokeShader() {_error = iError;} /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /*! [ Geometry Shader ]. * Shader to modify the Stroke geometry so that * it corresponds to its main direction line. * This shader must be used together with the * splitting operator using the curvature criterion. * Indeed, the precision of the approximation * will depend on the size of the stroke's pieces. * The bigger the pieces, the rougher the approximation. */ class LIB_STROKE_EXPORT GuidingLinesShader : public StrokeShader { private: float _offset; public: /*! Builds a Guiding Lines shader * \param iOffset * The line that replaces the stroke * is initially in the middle * of the initial stroke "bbox". * iOffset is the value of the displacement * which is applied to this line along its * normal. */ GuidingLinesShader(float iOffset) : StrokeShader() {_offset = iOffset;} /*! The shading method */ virtual void shade(Stroke& stroke) const; }; /*! [ Geometry Shader ]. * Removes the stroke's extremities. */ class LIB_STROKE_EXPORT TipRemoverShader : public StrokeShader { public: /*! Builds the shader. * \param tipLength * The length of the piece of stroke * we want to remove at each extremity. */ TipRemoverShader (real tipLength); /*! Destructor. */ virtual ~TipRemoverShader () {} /*! The shading method */ virtual void shade(Stroke &stroke) const; protected: real _tipLength; }; /*! [ output Shader ]. * streams the Stroke */ class LIB_STROKE_EXPORT streamShader : public StrokeShader { public: /*! Destructor. */ virtual ~streamShader() {} /*! Returns the string "streamShader".*/ virtual string getName() const { return "streamShader"; } /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; /*! [ output Shader ]. * streams the Stroke in a file */ class LIB_STROKE_EXPORT fstreamShader : public StrokeShader { protected: mutable ofstream _stream; public: /*! Builds the shader from the output file name */ fstreamShader(const char *iFileName) : StrokeShader(){ _stream .open(iFileName); if(!_stream.is_open()){ cout << "couldn't open file " << iFileName << endl; } } /*! Destructor. */ virtual ~fstreamShader() {_stream.close();} /*! Returns the string "fstreamShader".*/ virtual string getName() const { return "fstreamShader"; } /*! The shading method. */ virtual void shade(Stroke& stroke) const; }; } // end of namespace StrokeShaders #endif // BASIC_STROKE_SHADERS_H