Files
test/source/blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp

337 lines
9.6 KiB
C++
Raw Normal View History

/*
* ***** BEGIN GPL LICENSE BLOCK *****
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* ***** END GPL LICENSE BLOCK *****
*/
/** \file blender/freestyle/intern/stroke/AdvancedStrokeShaders.cpp
* \ingroup freestyle
* \brief Fredo's stroke shaders
* \author Fredo Durand
* \date 17/12/2002
*/
2008-04-30 15:41:54 +00:00
#include "AdvancedStrokeShaders.h"
#include "StrokeIterators.h"
2008-04-30 15:41:54 +00:00
#include "../system/PseudoNoise.h"
#include "../system/RandGen.h"
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
namespace Freestyle {
2008-04-30 15:41:54 +00:00
/////////////////////////////////////////
//
// CALLIGRAPHICS SHADER
//
/////////////////////////////////////////
CalligraphicShader::CalligraphicShader(real iMinThickness, real iMaxThickness, const Vec2f &iOrientation, bool clamp)
: StrokeShader()
2008-04-30 15:41:54 +00:00
{
_minThickness = iMinThickness;
_maxThickness = iMaxThickness;
_orientation = iOrientation;
_orientation.normalize();
_clamp = clamp;
2008-04-30 15:41:54 +00:00
}
int CalligraphicShader::shade(Stroke &ioStroke) const
2008-04-30 15:41:54 +00:00
{
Interface0DIterator v;
Functions0D::VertexOrientation2DF0D fun;
StrokeVertex *sv;
for (v = ioStroke.verticesBegin(); !v.isEnd(); ++v) {
real thickness;
if (fun(v) < 0)
return -1;
Vec2f vertexOri(fun.result);
Vec2r ori2d(-vertexOri[1], vertexOri[0]);
ori2d.normalizeSafe();
real scal = ori2d * _orientation;
sv = dynamic_cast<StrokeVertex*>(&(*v));
if (_clamp && (scal<0)) {
scal = 0.0;
sv->attribute().setColor(1, 1, 1);
}
else {
scal = fabs(scal);
sv->attribute().setColor(0, 0, 0);
}
thickness = _minThickness + scal * (_maxThickness - _minThickness);
if (thickness < 0.0)
thickness = 0.0;
sv->attribute().setThickness(thickness / 2.0, thickness / 2.0);
}
2008-04-30 15:41:54 +00:00
return 0;
}
2008-04-30 15:41:54 +00:00
/////////////////////////////////////////
//
// SPATIAL NOISE SHADER
//
/////////////////////////////////////////
static const unsigned NB_VALUE_NOISE = 512;
SpatialNoiseShader::SpatialNoiseShader(float ioamount, float ixScale, int nbOctave, bool smooth, bool pureRandom)
: StrokeShader()
2008-04-30 15:41:54 +00:00
{
_amount = ioamount;
if (ixScale == 0)
_xScale = 0;
else
_xScale = 1.0 / ixScale / real(NB_VALUE_NOISE);
_nbOctave = nbOctave;
_smooth = smooth;
_pureRandom = pureRandom;
2008-04-30 15:41:54 +00:00
}
int SpatialNoiseShader::shade(Stroke &ioStroke) const
2008-04-30 15:41:54 +00:00
{
Interface0DIterator v, v2;
v = ioStroke.verticesBegin();
Vec2r p(v->getProjectedX(), v->getProjectedY());
v2 = v;
++v2;
Vec2r p0(v2->getProjectedX(), v2->getProjectedY());
p0 = p + 2 * (p - p0);
StrokeVertex *sv;
sv = dynamic_cast<StrokeVertex*>(&(*v));
real initU = sv->strokeLength() * real(NB_VALUE_NOISE);
if (_pureRandom)
initU += RandGen::drand48() * real(NB_VALUE_NOISE);
Functions0D::VertexOrientation2DF0D fun;
while (!v.isEnd()) {
sv = dynamic_cast<StrokeVertex*>(&(*v));
Vec2r p(sv->getPoint());
if (fun(v) < 0)
return -1;
Vec2r vertexOri(fun.result);
Vec2r ori2d(vertexOri[0], vertexOri[1]);
ori2d = Vec2r(p - p0);
ori2d.normalizeSafe();
PseudoNoise mynoise;
real bruit;
if (_smooth)
bruit = mynoise.turbulenceSmooth(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
else
bruit = mynoise.turbulenceLinear(_xScale * sv->curvilinearAbscissa() + initU, _nbOctave);
Vec2r noise(-ori2d[1] * _amount * bruit, ori2d[0] * _amount * bruit);
sv->setPoint(p[0] + noise[0], p[1] + noise[1]);
p0 = p;
++v;
}
2008-04-30 15:41:54 +00:00
ioStroke.UpdateLength();
return 0;
}
2008-04-30 15:41:54 +00:00
/////////////////////////////////////////
//
// SMOOTHING SHADER
//
/////////////////////////////////////////
SmoothingShader::SmoothingShader(int ionbIteration, real iFactorPoint, real ifactorCurvature,
real iFactorCurvatureDifference, real iAnisoPoint, real iAnisoNormal,
real iAnisoCurvature, real iCarricatureFactor)
: StrokeShader()
2008-04-30 15:41:54 +00:00
{
_nbIterations = ionbIteration;
_factorCurvature = ifactorCurvature;
_factorCurvatureDifference = iFactorCurvatureDifference;
_anisoNormal = iAnisoNormal;
_anisoCurvature = iAnisoCurvature;
_carricatureFactor = iCarricatureFactor;
_factorPoint = iFactorPoint;
_anisoPoint = iAnisoPoint;
2008-04-30 15:41:54 +00:00
}
int SmoothingShader::shade(Stroke &ioStroke) const
2008-04-30 15:41:54 +00:00
{
// cerr << " Smoothing a stroke " << endl;
2008-04-30 15:41:54 +00:00
Smoother smoother(ioStroke);
smoother.smooth(_nbIterations, _factorPoint, _factorCurvature, _factorCurvatureDifference, _anisoPoint,
_anisoNormal, _anisoCurvature, _carricatureFactor);
return 0;
2008-04-30 15:41:54 +00:00
}
// SMOOTHER
////////////////////////////
Smoother::Smoother(Stroke &ioStroke)
{
_stroke = &ioStroke;
_nbVertices = ioStroke.vertices_size();
_vertex = new Vec2r[_nbVertices];
_curvature = new real[_nbVertices];
_normal = new Vec2r[_nbVertices];
StrokeInternal::StrokeVertexIterator v, vend;
int i = 0;
for (v = ioStroke.strokeVerticesBegin(), vend = ioStroke.strokeVerticesEnd(); v != vend; ++v, ++i) {
_vertex[i] = (v)->getPoint();
}
Vec2r vec_tmp(_vertex[0] - _vertex[_nbVertices - 1]);
_isClosedCurve = (vec_tmp.norm() < M_EPSILON);
_safeTest = (_nbVertices > 4);
2008-04-30 15:41:54 +00:00
}
Smoother::~Smoother()
{
delete[] _vertex;
delete[] _curvature;
delete[] _normal;
}
2008-04-30 15:41:54 +00:00
void Smoother::smooth(int nbIteration, real iFactorPoint, real ifactorCurvature, real iFactorCurvatureDifference,
real iAnisoPoint, real iAnisoNormal, real iAnisoCurvature, real iCarricatureFactor)
2008-04-30 15:41:54 +00:00
{
_factorCurvature = ifactorCurvature;
_factorCurvatureDifference = iFactorCurvatureDifference;
_anisoNormal = iAnisoNormal;
_anisoCurvature = iAnisoCurvature;
_carricatureFactor = iCarricatureFactor;
_factorPoint = iFactorPoint;
_anisoPoint = iAnisoPoint;
for (int i = 0; i < nbIteration; ++i)
iteration ();
copyVertices();
2008-04-30 15:41:54 +00:00
}
static real edgeStopping(real x, real sigma)
2008-04-30 15:41:54 +00:00
{
if (sigma == 0.0)
return 1.0;
return exp(-x * x / (sigma * sigma));
2008-04-30 15:41:54 +00:00
}
void Smoother::iteration()
2008-04-30 15:41:54 +00:00
{
computeCurvature();
for (int i = 1; i < (_nbVertices - 1); ++i) {
real motionNormal = _factorCurvature * _curvature[i] * edgeStopping(_curvature[i], _anisoNormal);
real diffC1 = _curvature[i] - _curvature[i - 1];
real diffC2 = _curvature[i] - _curvature[i + 1];
real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference;
motionCurvature *= _factorCurvatureDifference;
//motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
if (_safeTest)
_vertex[i] = Vec2r(_vertex[i] + (motionNormal + motionCurvature) * _normal[i]);
Vec2r v1(_vertex[i - 1] - _vertex[i]);
Vec2r v2(_vertex[i + 1] - _vertex[i]);
real d1 = v1.norm();
real d2 = v2.norm();
_vertex[i] = Vec2r(_vertex[i] +
_factorPoint * edgeStopping(d2, _anisoPoint) * (_vertex[i - 1] - _vertex[i]) +
_factorPoint * edgeStopping(d1, _anisoPoint) * (_vertex[i + 1] - _vertex[i]));
}
if (_isClosedCurve) {
real motionNormal = _factorCurvature * _curvature[0] * edgeStopping(_curvature[0], _anisoNormal);
real diffC1 = _curvature[0] - _curvature[_nbVertices - 2];
real diffC2 = _curvature[0] - _curvature[1];
real motionCurvature = edgeStopping(diffC1, _anisoCurvature) * diffC1 +
edgeStopping(diffC2, _anisoCurvature) * diffC2; //_factorCurvatureDifference;
motionCurvature *= _factorCurvatureDifference;
//motionCurvature = _factorCurvatureDifference * (diffC1 + diffC2);
_vertex[0] = Vec2r(_vertex[0] + (motionNormal + motionCurvature) * _normal[0]);
_vertex[_nbVertices - 1] = _vertex[0];
}
2008-04-30 15:41:54 +00:00
}
void Smoother::computeCurvature()
2008-04-30 15:41:54 +00:00
{
int i;
Vec2r BA, BC, normalCurvature;
for (i = 1; i < (_nbVertices - 1); ++i) {
BA = _vertex[i - 1] - _vertex[i];
BC = _vertex[i + 1] - _vertex[i];
real lba = BA.norm(), lbc = BC.norm();
BA.normalizeSafe();
BC.normalizeSafe();
normalCurvature = BA + BC;
_normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
_normal[i].normalizeSafe();
_curvature[i] = normalCurvature * _normal[i];
if (lba + lbc > M_EPSILON)
2014-04-15 19:21:29 +10:00
_curvature[i] /= (0.5 * lba + lbc);
}
_curvature[0] = _curvature[1];
_curvature[_nbVertices - 1] = _curvature[_nbVertices - 2];
Vec2r di(_vertex[1] - _vertex[0]);
_normal[0] = Vec2r(-di[1], di[0]);
_normal[0].normalizeSafe();
di = _vertex[_nbVertices - 1] - _vertex[_nbVertices - 2];
_normal[_nbVertices - 1] = Vec2r(-di[1], di[0]);
_normal[_nbVertices - 1].normalizeSafe();
if (_isClosedCurve) {
BA = _vertex[_nbVertices - 2] - _vertex[0];
BC = _vertex[1] - _vertex[0];
real lba = BA.norm(), lbc = BC.norm();
BA.normalizeSafe();
BC.normalizeSafe();
normalCurvature = BA + BC;
_normal[i] = Vec2r(-(BC - BA)[1], (BC - BA)[0]);
_normal[i].normalizeSafe();
_curvature[i] = normalCurvature * _normal[i];
if (lba + lbc > M_EPSILON)
2014-04-15 19:21:29 +10:00
_curvature[i] /= (0.5 * lba + lbc);
_normal[_nbVertices - 1] = _normal[0];
_curvature[_nbVertices - 1] = _curvature[0];
}
2008-04-30 15:41:54 +00:00
}
void Smoother::copyVertices()
2008-04-30 15:41:54 +00:00
{
int i = 0;
StrokeInternal::StrokeVertexIterator v, vend;
for (v = _stroke->strokeVerticesBegin(), vend = _stroke->strokeVerticesEnd(); v != vend; ++v) {
const Vec2r p0((v)->getPoint());
const Vec2r p1(_vertex[i]);
Vec2r p(p0 + _carricatureFactor * (p1 - p0));
(v)->setPoint(p[0], p[1]);
++i;
}
_stroke->UpdateLength();
2008-04-30 15:41:54 +00:00
}
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
} /* namespace Freestyle */