Welcome to mirror list, hosted at ThFree Co, Russian Federation.

git.blender.org/blender.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-12-22 22:25:01 +0400
committerTamito Kajiyama <rd6t-kjym@asahi-net.or.jp>2012-12-22 22:25:01 +0400
commitfa0211df269a3398dd70467982f9e129c79e501b (patch)
tree404ee267890602b49470cb640986b50d2c2055c1 /source/blender/freestyle/intern/geometry
parent8b57a67f3eb57366c2b3abcb8f3b04403d339e1a (diff)
Another "insanely" big code clean-up patch by Bastien Montagne, many thanks!
Diffstat (limited to 'source/blender/freestyle/intern/geometry')
-rw-r--r--source/blender/freestyle/intern/geometry/BBox.h265
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.cpp171
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.h125
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.cpp119
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.h145
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.cpp763
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.h188
-rw-r--r--source/blender/freestyle/intern/geometry/Geom.h132
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.cpp419
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.h408
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.cpp1488
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.h563
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.cpp712
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h657
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.cpp87
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.h172
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.cpp74
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.h197
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp407
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.h128
-rw-r--r--source/blender/freestyle/intern/geometry/Polygon.h393
-rw-r--r--source/blender/freestyle/intern/geometry/SweepLine.h587
-rw-r--r--source/blender/freestyle/intern/geometry/VecMat.h1843
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.cpp497
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.h105
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.cpp169
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.h210
27 files changed, 5649 insertions, 5375 deletions
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
index 9c46d7918e2..b13960a4d2e 100644
--- a/source/blender/freestyle/intern/geometry/BBox.h
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -1,141 +1,154 @@
-//
-// Filename : BBox.h
-// Author(s) : Stephane Grabli
-// Purpose : A class to hold a bounding box
-// Date of creation : 22/05/2003
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-//
-// 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 BBOX_H
-# define BBOX_H
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BBOX_H__
+#define __BBOX_H__
+
+/** \file blender/freestyle/intern/geometry/BBox.h
+ * \ingroup freestyle
+ * \brief A class to hold a bounding box
+ * \author Stephane Grabli
+ * \date 22/05/2003
+ */
template <class Point>
class BBox
{
- public:
-
- inline BBox() {
- _empty = true;
- }
-
- template <class T>
- inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in) {
- _empty = false;
- }
-
- template <class T>
- inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax()) {
- _empty = false;
- }
-
- template <class T>
- inline void extendToContain(const T& p) {
- if (_empty) {
- _min = p;
- _max = p;
- _empty = false;
- return;
- }
- for (unsigned i = 0; i < Point::dim(); i++) {
- if (p[i] < _min[i])
- _min[i] = p[i];
- else if (p[i] > _max[i])
- _max[i] = p[i];
- }
- _empty = false;
- }
-
- inline void clear() {
- _empty = true;
- }
-
- inline bool empty() const {
- return _empty;
- }
-
- inline const Point& getMin() const {
- return _min;
- }
-
- inline const Point& getMax() const {
- return _max;
- }
-
- inline BBox<Point>& operator=(const BBox<Point>& b) {
- _min = b.getMin();
- _max = b.getMax();
- _empty = false;
- return *this;
- }
-
- inline BBox<Point>& operator+=(const BBox<Point>& b) {
- if (_empty) {
- _min = b.getMin();
- _max = b.getMax();
- _empty = false;
- }
- else {
- for (unsigned i = 0; i < Point::dim(); i++) {
- if (b.getMin()[i] < _min[i])
- _min[i] = b.getMin()[i];
- if (b.getMax()[i] > _max[i])
- _max[i] = b.getMax()[i];
- }
- }
- return *this;
- }
-
- inline bool inside(const Point& p){
- if(empty())
- return false;
- for (unsigned i = 0; i < Point::dim(); i++) {
- if((_min[i]>p[i]) || (_max[i]<p[i]))
- return false;
- }
- return true;
-
- }
+public:
+ inline BBox()
+ {
+ _empty = true;
+ }
+
+ template <class T>
+ inline BBox(const T& min_in, const T& max_in) : _min(min_in), _max(max_in)
+ {
+ _empty = false;
+ }
+
+ template <class T>
+ inline BBox(const BBox<T>& b) : _min(b.getMin()), _max(b.getMax())
+ {
+ _empty = false;
+ }
+
+ template <class T>
+ inline void extendToContain(const T& p)
+ {
+ if (_empty) {
+ _min = p;
+ _max = p;
+ _empty = false;
+ return;
+ }
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if (p[i] < _min[i])
+ _min[i] = p[i];
+ else if (p[i] > _max[i])
+ _max[i] = p[i];
+ }
+ _empty = false;
+ }
+
+ inline void clear()
+ {
+ _empty = true;
+ }
+
+ inline bool empty() const
+ {
+ return _empty;
+ }
+
+ inline const Point& getMin() const
+ {
+ return _min;
+ }
+
+ inline const Point& getMax() const
+ {
+ return _max;
+ }
+
+ inline BBox<Point>& operator=(const BBox<Point>& b)
+ {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ return *this;
+ }
+
+ inline BBox<Point>& operator+=(const BBox<Point>& b)
+ {
+ if (_empty) {
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ }
+ else {
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if (b.getMin()[i] < _min[i])
+ _min[i] = b.getMin()[i];
+ if (b.getMax()[i] > _max[i])
+ _max[i] = b.getMax()[i];
+ }
+ }
+ return *this;
+ }
+
+ inline bool inside(const Point& p)
+ {
+ if (empty())
+ return false;
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if ((_min[i]>p[i]) || (_max[i]<p[i]))
+ return false;
+ }
+ return true;
+ }
private:
-
- Point _min;
- Point _max;
- bool _empty;
+ Point _min;
+ Point _max;
+ bool _empty;
};
template <class Point>
BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
{
- Point new_min;
- Point new_max;
+ Point new_min;
+ Point new_max;
- for (unsigned i = 0; i < Point::dim(); i++) {
- new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
- new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
- }
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ new_min[i] = b1.getMin()[i] < b2.getMin()[i] ? b1.getMin()[i] : b2.getMin()[i];
+ new_max[i] = b1.getMax()[i] > b2.getMax()[i] ? b1.getMax()[i] : b2.getMax()[i];
+ }
- return BBox<Point>(new_min, new_max);
+ return BBox<Point>(new_min, new_max);
}
-#endif // BBOX_H
+#endif // __BBOX_H__
diff --git a/source/blender/freestyle/intern/geometry/Bezier.cpp b/source/blender/freestyle/intern/geometry/Bezier.cpp
index 8f9771f29d3..9140f1f947d 100644
--- a/source/blender/freestyle/intern/geometry/Bezier.cpp
+++ b/source/blender/freestyle/intern/geometry/Bezier.cpp
@@ -1,23 +1,36 @@
-
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Bezier.cpp
+ * \ingroup freestyle
+ * \brief Class to define a Bezier curve of order 4.
+ * \author Stephane Grabli
+ * \date 04/06/2003
+ */
#include "Bezier.h"
#include "FitCurve.h"
@@ -34,85 +47,81 @@ BezierCurveSegment::~BezierCurveSegment()
void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
{
- _ControlPolygon.push_back(iPoint);
- if(_ControlPolygon.size() == 4)
- Build();
+ _ControlPolygon.push_back(iPoint);
+ if (_ControlPolygon.size() == 4)
+ Build();
}
void BezierCurveSegment::Build()
{
- if(_ControlPolygon.size() != 4)
- return;
-
- // Compute the rightmost part of the matrix:
- vector<Vec2d>::const_iterator p0,p1,p2,p3;
- p0 = _ControlPolygon.begin();
- p1 = p0;++p1;
- p2 = p1;++p2;
- p3 = p2;++p3;
- float x[4], y[4];
-
- x[0] = -p0->x()+3*p1->x()-3*p2->x()+p3->x();
- x[1] = 3*p0->x()-6*p1->x()+3*p2->x();
- x[2] = -3*p0->x()+3*p1->x();
- x[3] = p0->x();
-
- y[0] = -p0->y()+3*p1->y()-3*p2->y()+p3->y();
- y[1] = 3*p0->y()-6*p1->y()+3*p2->y();
- y[2] = -3*p0->y()+3*p1->y();
- y[3] = p0->y();
-
- int nvertices = 12;
- float increment = 1.0/(float)nvertices;
- float t = 0.f;
- for(int i=0; i<=nvertices; ++i)
- {
- _Vertices.push_back(Vec2d((x[3] + t*(x[2] + t*(x[1] + t*x[0]))),
- (y[3] + t*(y[2] + t*(y[1] + t*y[0])))));
- t+=increment;
- }
+ if (_ControlPolygon.size() != 4)
+ return;
+
+ // Compute the rightmost part of the matrix:
+ vector<Vec2d>::const_iterator p0,p1,p2,p3;
+ p0 = _ControlPolygon.begin();
+ p1 = p0;
+ ++p1;
+ p2 = p1;
+ ++p2;
+ p3 = p2;
+ ++p3;
+ float x[4], y[4];
+
+ x[0] = -p0->x() + 3 * p1->x() - 3 * p2->x() + p3->x();
+ x[1] = 3 * p0->x() - 6 * p1->x() + 3 * p2->x();
+ x[2] = -3 * p0->x() + 3 * p1->x();
+ x[3] = p0->x();
+
+ y[0] = -p0->y() + 3 * p1->y() - 3 * p2->y() + p3->y();
+ y[1] = 3 * p0->y() - 6 * p1->y() + 3 * p2->y();
+ y[2] = -3 * p0->y() + 3 * p1->y();
+ y[3] = p0->y();
+
+ int nvertices = 12;
+ float increment = 1.0 / (float)nvertices;
+ float t = 0.0f;
+ for (int i = 0; i <= nvertices; ++i) {
+ _Vertices.push_back(Vec2d((x[3] + t * (x[2] + t * (x[1] + t * x[0]))),
+ (y[3] + t * (y[2] + t * (y[1] + t * y[0])))));
+ t += increment;
+ }
}
BezierCurve::BezierCurve()
{
- _currentSegment = new BezierCurveSegment;
+ _currentSegment = new BezierCurveSegment;
}
BezierCurve::BezierCurve(vector<Vec2d>& iPoints, double error)
{
- FitCurveWrapper fitcurve;
- _currentSegment = new BezierCurveSegment;
- vector<Vec2d> curve;
-
- fitcurve.FitCurve(iPoints, curve, error);
- int i=0;
- vector<Vec2d>::iterator v,vend;
- for(v=curve.begin(),vend=curve.end();
- v!=vend;
- ++v)
- {
- if((i == 0) || (i%4 != 0))
- AddControlPoint(*v);
- ++i;
- }
+ FitCurveWrapper fitcurve;
+ _currentSegment = new BezierCurveSegment;
+ vector<Vec2d> curve;
+
+ fitcurve.FitCurve(iPoints, curve, error);
+ int i = 0;
+ vector<Vec2d>::iterator v,vend;
+ for (v = curve.begin(), vend = curve.end(); v != vend; ++v) {
+ if ((i == 0) || (i % 4 != 0))
+ AddControlPoint(*v);
+ ++i;
+ }
}
BezierCurve::~BezierCurve()
{
- if(_currentSegment)
- delete _currentSegment;
+ if(_currentSegment)
+ delete _currentSegment;
}
void BezierCurve::AddControlPoint(const Vec2d& iPoint)
{
- _ControlPolygon.push_back(iPoint);
- _currentSegment->AddControlPoint(iPoint);
- if(_currentSegment->size() == 4)
- {
- _Segments.push_back(_currentSegment);
- _currentSegment = new BezierCurveSegment;
- _currentSegment->AddControlPoint(iPoint);
- }
+ _ControlPolygon.push_back(iPoint);
+ _currentSegment->AddControlPoint(iPoint);
+ if (_currentSegment->size() == 4) {
+ _Segments.push_back(_currentSegment);
+ _currentSegment = new BezierCurveSegment;
+ _currentSegment->AddControlPoint(iPoint);
+ }
}
-
-
diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h
index acae71bbb2c..51f32e9e0b3 100644
--- a/source/blender/freestyle/intern/geometry/Bezier.h
+++ b/source/blender/freestyle/intern/geometry/Bezier.h
@@ -1,73 +1,96 @@
-//
-// Filename : Bezier.h
-// Author(s) : Stephane Grabli
-// Purpose : Class to define a Bezier curve of order 4.
-// Date of creation : 04/06/2003
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-//
-// 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 BEZIER_H
-# define BEZIER_H
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __BEZIER_H__
+#define __BEZIER_H__
+
+/** \file blender/freestyle/intern/geometry/Bezier.h
+ * \ingroup freestyle
+ * \brief Class to define a Bezier curve of order 4.
+ * \author Stephane Grabli
+ * \date 04/06/2003
+ */
#include <vector>
-#include "../system/FreestyleConfig.h"
+
#include "Geom.h"
+#include "../system/FreestyleConfig.h"
+
using namespace Geometry;
-class LIB_GEOMETRY_EXPORT BezierCurveSegment
+class LIB_GEOMETRY_EXPORT BezierCurveSegment
{
private:
- std::vector<Vec2d> _ControlPolygon;
- std::vector<Vec2d> _Vertices;
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<Vec2d> _Vertices;
public:
- BezierCurveSegment();
- virtual ~BezierCurveSegment();
+ BezierCurveSegment();
+ virtual ~BezierCurveSegment();
+
+ void AddControlPoint(const Vec2d& iPoint);
+ void Build();
+
+ inline int size() const
+ {
+ return _ControlPolygon.size();
+ }
- void AddControlPoint(const Vec2d& iPoint);
- void Build();
- inline int size() const {return _ControlPolygon.size();}
- inline std::vector<Vec2d>& vertices() {return _Vertices;}
+ inline std::vector<Vec2d>& vertices()
+ {
+ return _Vertices;
+ }
};
class LIB_GEOMETRY_EXPORT BezierCurve
{
private:
- std::vector<Vec2d> _ControlPolygon;
- std::vector<BezierCurveSegment*> _Segments;
- BezierCurveSegment *_currentSegment;
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<BezierCurveSegment*> _Segments;
+ BezierCurveSegment *_currentSegment;
public:
- BezierCurve();
- BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
- virtual ~BezierCurve();
+ BezierCurve();
+ BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
+ virtual ~BezierCurve();
+
+ void AddControlPoint(const Vec2d& iPoint);
+
+ std::vector<Vec2d>& controlPolygon()
+ {
+ return _ControlPolygon;
+ }
- void AddControlPoint(const Vec2d& iPoint);
- std::vector<Vec2d>& controlPolygon() {return _ControlPolygon;}
- std::vector<BezierCurveSegment*>& segments() {return _Segments;}
+ std::vector<BezierCurveSegment*>& segments()
+ {
+ return _Segments;
+ }
};
-#endif // BEZIER_H
+#endif // __BEZIER_H__
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.cpp b/source/blender/freestyle/intern/geometry/FastGrid.cpp
index 325126b4b96..f5f9bc1079e 100644
--- a/source/blender/freestyle/intern/geometry/FastGrid.cpp
+++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp
@@ -1,62 +1,83 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/FastGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
#include "FastGrid.h"
-void FastGrid::clear() {
- if(!_cells)
- return;
+void FastGrid::clear()
+{
+ if (!_cells)
+ return;
- for(unsigned i = 0; i < _cells_size; i++)
- if (_cells[i])
- delete _cells[i];
- delete[] _cells;
- _cells = NULL;
- _cells_size = 0;
+ for (unsigned int i = 0; i < _cells_size; i++) {
+ if (_cells[i])
+ delete _cells[i];
+ }
+ delete[] _cells;
+ _cells = NULL;
+ _cells_size = 0;
- Grid::clear();
+ Grid::clear();
}
-void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
- Grid::configure(orig, size, nb);
- _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
- _cells = new Cell*[_cells_size];
- memset(_cells, 0, _cells_size * sizeof(*_cells));
+void FastGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ Grid::configure(orig, size, nb);
+ _cells_size = _cells_nb[0] * _cells_nb[1] * _cells_nb[2];
+ _cells = new Cell*[_cells_size];
+ memset(_cells, 0, _cells_size * sizeof(*_cells));
}
-Cell* FastGrid::getCell(const Vec3u& p) {
- //cout << _cells<< " "<< p << " " <<_cells_nb[0]<<"-"<< _cells_nb[1]<<"-"<< _cells_nb[2]<< " "<<_cells_size<< endl;
- assert(_cells||("_cells is a null pointer"));
- assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
- assert(p[0]<_cells_nb[0]);
- assert(p[1]<_cells_nb[1]);
- assert(p[2]<_cells_nb[2]);
- return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
+Cell *FastGrid::getCell(const Vec3u& p)
+{
+#if 0
+ cout << _cells << " " << p << " " << _cells_nb[0] << "-" << _cells_nb[1] << "-" << _cells_nb[2]
+ << " " << _cells_size << endl;
+#endif
+ assert(_cells || ("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ assert(p[0] < _cells_nb[0]);
+ assert(p[1] < _cells_nb[1]);
+ assert(p[2] < _cells_nb[2]);
+ return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
}
-void FastGrid::fillCell(const Vec3u& p, Cell& cell) {
- assert(_cells||("_cells is a null pointer"));
- assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0])<_cells_size);
- assert(p[0]<_cells_nb[0]);
- assert(p[1]<_cells_nb[1]);
- assert(p[2]<_cells_nb[2]);
- _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
+void FastGrid::fillCell(const Vec3u& p, Cell& cell)
+{
+ assert(_cells || ("_cells is a null pointer"));
+ assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ assert(p[0] < _cells_nb[0]);
+ assert(p[1] < _cells_nb[1]);
+ assert(p[2] < _cells_nb[2]);
+ _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
}
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h
index e620ff24385..3a2ed392533 100644
--- a/source/blender/freestyle/intern/geometry/FastGrid.h
+++ b/source/blender/freestyle/intern/geometry/FastGrid.h
@@ -1,85 +1,86 @@
-//
-// Filename : FastGrid.h
-// Author(s) : Stephane Grabli
-// Purpose : Class to define a cell grid surrounding the
-// bounding box of the scene
-// Date of creation : 30/07/2002
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FASTGRID_H__
+#define __FASTGRID_H__
+/** \file blender/freestyle/intern/geometry/FastGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/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.
-//
-///////////////////////////////////////////////////////////////////////////////
+#include <cassert>
-#ifndef FASTGRID_H
-# define FASTGRID_H
+#include "Grid.h"
-# include "Grid.h"
-# include <cassert>
-/*! Class to define a regular grid used for ray
- * casting computations
- * We don't use a hashtable here. The grid is
- * explicitly stored for faster computations.
- * However, this might result in significant
- * increase in memory usage (compared to the regular grid)
+/*! Class to define a regular grid used for ray casting computations
+ * We don't use a hashtable here. The grid is explicitly stored for faster computations.
+ * However, this might result in significant increase in memory usage (compared to the regular grid)
*/
-
class LIB_GEOMETRY_EXPORT FastGrid : public Grid
{
- public:
+public:
+ FastGrid() : Grid()
+ {
+ _cells = NULL;
+ _cells_size = 0;
+ }
- FastGrid() : Grid() {
- _cells = NULL;
- _cells_size = 0;
- }
-
- virtual ~FastGrid() {
- clear();
- }
+ virtual ~FastGrid()
+ {
+ clear();
+ }
- /*! clears the grid
- * Deletes all the cells, clears the hashtable,
- * resets size, size of cell, number of cells.
- */
- virtual void clear();
-
- /*! Sets the different parameters of the grid
- * orig
- * The grid origin
- * size
- * The grid's dimensions
- * nb
- * The number of cells of the grid
- */
- virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
-
- /*! returns the cell whose coordinates are pased as argument */
- Cell* getCell(const Vec3u& p) ;
-
- /*! Fills the case p with the cell iCell */
- virtual void fillCell(const Vec3u& p, Cell& cell);
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
-protected:
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ Cell* getCell(const Vec3u& p);
- Cell** _cells;
- unsigned _cells_size;
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell);
+
+protected:
+ Cell **_cells;
+ unsigned _cells_size;
};
-#endif // FASTGRID_H
+#endif // __FASTGRID_H__
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.cpp b/source/blender/freestyle/intern/geometry/FitCurve.cpp
index f71af130d7f..4eae543c9f9 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.cpp
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -1,33 +1,49 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/FitCurve.cpp
+ * \ingroup freestyle
+ * \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
+ * \brief from "Graphics Gems", Academic Press, 1990
+ * \author Stephane Grabli
+ * \date 06/06/2003
+ */
#include <cstdlib> // for malloc and free
#include <stdio.h>
#include <math.h>
+
#include "FitCurve.h"
using namespace std;
typedef Vector2 *BezierCurve;
+// XXX Do we need "#ifdef __cplusplus" at all here???
#ifdef __cplusplus
extern "C"
{
@@ -46,379 +62,367 @@ static Vector2 ComputeLeftTangent(Vector2 *d, int end);
static Vector2 ComputeLeftTangent(Vector2 *d, int end);
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
static double *ChordLengthParameterize(Vector2 *d, int first, int last);
-static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
+static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2);
static Vector2 V2AddII(Vector2 a, Vector2 b);
static Vector2 V2ScaleIII(Vector2 v, double s);
static Vector2 V2SubII(Vector2 a, Vector2 b);
+#define MAXPOINTS 1000 /* The most points you can have */
-#define MAXPOINTS 1000 /* The most points you can have */
-
-/* returns squared length of input vector */
-static double V2SquaredLength(Vector2 *a)
-{ return(((*a)[0] * (*a)[0])+((*a)[1] * (*a)[1]));
+/* returns squared length of input vector */
+static double V2SquaredLength(Vector2 *a)
+{
+ return (((*a)[0] * (*a)[0]) + ((*a)[1] * (*a)[1]));
}
-
+
/* returns length of input vector */
static double V2Length(Vector2 *a)
{
- return(sqrt(V2SquaredLength(a)));
+ return (sqrt(V2SquaredLength(a)));
}
-static Vector2 *V2Scale(Vector2 *v, double newlen)
+static Vector2 *V2Scale(Vector2 *v, double newlen)
{
- double len = V2Length(v);
- if (len != 0.0) { (*v)[0] *= newlen/len; (*v)[1] *= newlen/len; }
- return(v);
+ double len = V2Length(v);
+ if (len != 0.0) {
+ (*v)[0] *= newlen / len;
+ (*v)[1] *= newlen / len;
+ }
+ return v;
}
/* return the dot product of vectors a and b */
-static double V2Dot(Vector2 *a, Vector2 *b)
+static double V2Dot(Vector2 *a, Vector2 *b)
{
- return(((*a)[0]*(*b)[0])+((*a)[1]*(*b)[1]));
+ return (((*a)[0] * (*b)[0]) + ((*a)[1] * (*b)[1]));
}
/* return the distance between two points */
static double V2DistanceBetween2Points(Vector2 *a, Vector2 *b)
{
-double dx = (*a)[0] - (*b)[0];
-double dy = (*a)[1] - (*b)[1];
- return(sqrt((dx*dx)+(dy*dy)));
+ double dx = (*a)[0] - (*b)[0];
+ double dy = (*a)[1] - (*b)[1];
+ return (sqrt((dx * dx) + (dy * dy)));
}
/* return vector sum c = a+b */
static Vector2 *V2Add(Vector2 *a, Vector2 *b, Vector2 *c)
{
- (*c)[0] = (*a)[0]+(*b)[0]; (*c)[1] = (*a)[1]+(*b)[1];
- return(c);
+ (*c)[0] = (*a)[0] + (*b)[0];
+ (*c)[1] = (*a)[1] + (*b)[1];
+ return c;
}
/* normalizes the input vector and returns it */
-static Vector2 *V2Normalize(Vector2 *v)
+static Vector2 *V2Normalize(Vector2 *v)
{
-double len = V2Length(v);
- if (len != 0.0) { (*v)[0] /= len; (*v)[1] /= len; }
- return(v);
+ double len = V2Length(v);
+ if (len != 0.0) {
+ (*v)[0] /= len;
+ (*v)[1] /= len;
+ }
+ return v;
}
/* negates the input vector and returns it */
-static Vector2 *V2Negate(Vector2 *v)
+static Vector2 *V2Negate(Vector2 *v)
{
- (*v)[0] = -(*v)[0]; (*v)[1] = -(*v)[1];
- return(v);
+ (*v)[0] = -(*v)[0];
+ (*v)[1] = -(*v)[1];
+ return v;
}
-
-/*
- * GenerateBezier :
+/* GenerateBezier:
* Use least-squares method to find Bezier control points for region.
- *
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * double *uPrime; Parameter values for region
+ * Vector2 tHat1, tHat2; Unit tangents at endpoints
*/
static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
-// Vector2 *d; /* Array of digitized points */
-// int first, last; /* Indices defining region */
-// double *uPrime; /* Parameter values for region */
-// Vector2 tHat1, tHat2; /* Unit tangents at endpoints */
{
- int i;
- Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
- int nPts; /* Number of pts in sub-curve */
- double C[2][2]; /* Matrix C */
- double X[2]; /* Matrix X */
- double det_C0_C1, /* Determinants of matrices */
- det_C0_X,
- det_X_C1;
- double alpha_l, /* Alpha values, left and right */
- alpha_r;
- Vector2 tmp; /* Utility variable */
- BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
-
- bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
- nPts = last - first + 1;
-
-
- /* Compute the A's */
- for (i = 0; i < nPts; i++) {
- Vector2 v1, v2;
+ int i;
+ Vector2 A[MAXPOINTS][2]; /* Precomputed rhs for eqn */
+ int nPts; /* Number of pts in sub-curve */
+ double C[2][2]; /* Matrix C */
+ double X[2]; /* Matrix X */
+ double det_C0_C1; /* Determinants of matrices */
+ double det_C0_X;
+ double det_X_C1;
+ double alpha_l; /* Alpha values, left and right */
+ double alpha_r;
+ Vector2 tmp; /* Utility variable */
+ BezierCurve bezCurve; /* RETURN bezier curve ctl pts */
+
+ bezCurve = (Vector2*)malloc(4 * sizeof(Vector2));
+ nPts = last - first + 1;
+
+ /* Compute the A's */
+ for (i = 0; i < nPts; i++) {
+ Vector2 v1, v2;
v1 = tHat1;
v2 = tHat2;
V2Scale(&v1, B1(uPrime[i]));
V2Scale(&v2, B2(uPrime[i]));
A[i][0] = v1;
A[i][1] = v2;
- }
-
- /* Create the C and X matrices */
- C[0][0] = 0.0;
- C[0][1] = 0.0;
- C[1][0] = 0.0;
- C[1][1] = 0.0;
- X[0] = 0.0;
- X[1] = 0.0;
-
- for (i = 0; i < nPts; i++) {
- C[0][0] += V2Dot(&A[i][0], &A[i][0]);
+ }
+
+ /* Create the C and X matrices */
+ C[0][0] = 0.0;
+ C[0][1] = 0.0;
+ C[1][0] = 0.0;
+ C[1][1] = 0.0;
+ X[0] = 0.0;
+ X[1] = 0.0;
+ for (i = 0; i < nPts; i++) {
+ C[0][0] += V2Dot(&A[i][0], &A[i][0]);
C[0][1] += V2Dot(&A[i][0], &A[i][1]);
-/* C[1][0] += V2Dot(&A[i][0], &A[i][1]);*/
+// C[1][0] += V2Dot(&A[i][0], &A[i][1]);
C[1][0] = C[0][1];
C[1][1] += V2Dot(&A[i][1], &A[i][1]);
tmp = V2SubII(d[first + i],
- V2AddII(
- V2ScaleIII(d[first], B0(uPrime[i])),
- V2AddII(
- V2ScaleIII(d[first], B1(uPrime[i])),
- V2AddII(
- V2ScaleIII(d[last], B2(uPrime[i])),
- V2ScaleIII(d[last], B3(uPrime[i]))))));
-
-
- X[0] += V2Dot(&((A[i])[0]), &tmp);
- X[1] += V2Dot(&((A[i])[1]), &tmp);
- }
-
- /* Compute the determinants of C and X */
- det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
- det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
- det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
-
- /* Finally, derive alpha values */
- if (det_C0_C1 == 0.0) {
- det_C0_C1 = (C[0][0] * C[1][1]) * 10e-12;
- }
- alpha_l = det_X_C1 / det_C0_C1;
- alpha_r = det_C0_X / det_C0_C1;
-
-
- /* If alpha negative, use the Wu/Barsky heuristic (see text) */
- /* (if alpha is 0, you get coincident control points that lead to
- * divide by zero in any subsequent NewtonRaphsonRootFind() call. */
- if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
- double dist = V2DistanceBetween2Points(&d[last], &d[first]) /
- 3.0;
+ V2AddII(V2ScaleIII(d[first], B0(uPrime[i])),
+ V2AddII(V2ScaleIII(d[first], B1(uPrime[i])),
+ V2AddII(V2ScaleIII(d[last], B2(uPrime[i])),
+ V2ScaleIII(d[last], B3(uPrime[i]))
+ )
+ )
+ )
+ );
+
+ X[0] += V2Dot(&((A[i])[0]), &tmp);
+ X[1] += V2Dot(&((A[i])[1]), &tmp);
+ }
+
+ /* Compute the determinants of C and X */
+ det_C0_C1 = C[0][0] * C[1][1] - C[1][0] * C[0][1];
+ det_C0_X = C[0][0] * X[1] - C[0][1] * X[0];
+ det_X_C1 = X[0] * C[1][1] - X[1] * C[0][1];
+
+ /* Finally, derive alpha values */
+ if (det_C0_C1 == 0.0) {
+ det_C0_C1 = (C[0][0] * C[1][1]) * 10.0e-12;
+ }
+ alpha_l = det_X_C1 / det_C0_C1;
+ alpha_r = det_C0_X / det_C0_C1;
+
+
+ /* If alpha negative, use the Wu/Barsky heuristic (see text) (if alpha is 0, you get coincident control points
+ * that lead to divide by zero in any subsequent NewtonRaphsonRootFind() call).
+ */
+ if (alpha_l < 1.0e-6 || alpha_r < 1.0e-6) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
bezCurve[0] = d[first];
bezCurve[3] = d[last];
V2Add(&(bezCurve[0]), V2Scale(&(tHat1), dist), &(bezCurve[1]));
V2Add(&(bezCurve[3]), V2Scale(&(tHat2), dist), &(bezCurve[2]));
- return (bezCurve);
- }
-
- /* First and last control points of the Bezier curve are */
- /* positioned exactly at the first and last data points */
- /* Control points 1 and 2 are positioned an alpha distance out */
- /* on the tangent vectors, left and right, respectively */
- bezCurve[0] = d[first];
- bezCurve[3] = d[last];
- V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
- V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
- return (bezCurve);
-}
+ return bezCurve;
+ }
+ /* First and last control points of the Bezier curve are positioned exactly at the first and last data points
+ * Control points 1 and 2 are positioned an alpha distance out on the tangent vectors, left and right, respectively
+ */
+ bezCurve[0] = d[first];
+ bezCurve[3] = d[last];
+ V2Add(&bezCurve[0], V2Scale(&tHat1, alpha_l), &bezCurve[1]);
+ V2Add(&bezCurve[3], V2Scale(&tHat2, alpha_r), &bezCurve[2]);
+ return (bezCurve);
+}
/*
* Reparameterize:
- * Given set of points and their parameterization, try to find
- * a better parameterization.
- *
+ * Given set of points and their parameterization, try to find a better parameterization.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * double *u; Current parameter values
+ * BezierCurve bezCurve; Current fitted curve
*/
static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
-// Vector2 *d; /* Array of digitized points */
-// int first, last; /* Indices defining region */
-// double *u; /* Current parameter values */
-// BezierCurve bezCurve; /* Current fitted curve */
{
- int nPts = last-first+1;
- int i;
- double *uPrime; /* New parameter values */
-
- uPrime = (double *)malloc(nPts * sizeof(double));
- for (i = first; i <= last; i++) {
- uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i-
- first]);
- }
- return (uPrime);
-}
-
+ int nPts = last - first + 1;
+ int i;
+ double *uPrime; /* New parameter values */
+ uPrime = (double*)malloc(nPts * sizeof(double));
+ for (i = first; i <= last; i++) {
+ uPrime[i-first] = NewtonRaphsonRootFind(bezCurve, d[i], u[i - first]);
+ }
+ return (uPrime);
+}
/*
- * NewtonRaphsonRootFind :
- * Use Newton-Raphson iteration to find better root.
+ * NewtonRaphsonRootFind:
+ * Use Newton-Raphson iteration to find better root.
+ * BezierCurve Q; Current fitted curve
+ * Vector2 P; Digitized point
+ * double u; Parameter value for "P"
*/
static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
-// BezierCurve Q; /* Current fitted curve */
-// Vector2 P; /* Digitized point */
-// double u; /* Parameter value for "P" */
{
- double numerator, denominator;
- Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
- Vector2 Q_u, Q1_u, Q2_u; /*u evaluated at Q, Q', & Q'' */
- double uPrime; /* Improved u */
- int i;
-
- /* Compute Q(u) */
- Q_u = BezierII(3, Q, u);
-
- /* Generate control vertices for Q' */
- for (i = 0; i <= 2; i++) {
- Q1[i][0] = (Q[i+1][0] - Q[i][0]) * 3.0;
- Q1[i][1] = (Q[i+1][1] - Q[i][1]) * 3.0;
- }
-
- /* Generate control vertices for Q'' */
- for (i = 0; i <= 1; i++) {
- Q2[i][0] = (Q1[i+1][0] - Q1[i][0]) * 2.0;
- Q2[i][1] = (Q1[i+1][1] - Q1[i][1]) * 2.0;
- }
-
- /* Compute Q'(u) and Q''(u) */
- Q1_u = BezierII(2, Q1, u);
- Q2_u = BezierII(1, Q2, u);
-
- /* Compute f(u)/f'(u) */
- numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
- denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
- (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
-
- /* u = u - f(u)/f'(u) */
- if(denominator == 0) // FIXME
- return u;
- uPrime = u - (numerator/denominator);
- return (uPrime);
+ double numerator, denominator;
+ Vector2 Q1[3], Q2[2]; /* Q' and Q'' */
+ Vector2 Q_u, Q1_u, Q2_u; /* u evaluated at Q, Q', & Q'' */
+ double uPrime; /* Improved u */
+ int i;
+
+ /* Compute Q(u) */
+ Q_u = BezierII(3, Q, u);
+
+ /* Generate control vertices for Q' */
+ for (i = 0; i <= 2; i++) {
+ Q1[i][0] = (Q[i + 1][0] - Q[i][0]) * 3.0;
+ Q1[i][1] = (Q[i + 1][1] - Q[i][1]) * 3.0;
+ }
+
+ /* Generate control vertices for Q'' */
+ for (i = 0; i <= 1; i++) {
+ Q2[i][0] = (Q1[i + 1][0] - Q1[i][0]) * 2.0;
+ Q2[i][1] = (Q1[i + 1][1] - Q1[i][1]) * 2.0;
+ }
+
+ /* Compute Q'(u) and Q''(u) */
+ Q1_u = BezierII(2, Q1, u);
+ Q2_u = BezierII(1, Q2, u);
+
+ /* Compute f(u)/f'(u) */
+ numerator = (Q_u[0] - P[0]) * (Q1_u[0]) + (Q_u[1] - P[1]) * (Q1_u[1]);
+ denominator = (Q1_u[0]) * (Q1_u[0]) + (Q1_u[1]) * (Q1_u[1]) +
+ (Q_u[0] - P[0]) * (Q2_u[0]) + (Q_u[1] - P[1]) * (Q2_u[1]);
+
+ /* u = u - f(u)/f'(u) */
+ if (denominator == 0) // FIXME
+ return u;
+ uPrime = u - (numerator / denominator);
+ return uPrime;
}
-
-
/*
- * Bezier :
- * Evaluate a Bezier curve at a particular parameter value
- *
+ * Bezier:
+ * Evaluate a Bezier curve at a particular parameter value
+ * int degree; The degree of the bezier curve
+ * Vector2 *V; Array of control points
+ * double t; Parametric value to find point for
*/
static Vector2 BezierII(int degree, Vector2 *V, double t)
-// int degree; /* The degree of the bezier curve */
-// Vector2 *V; /* Array of control points */
-// double t; /* Parametric value to find point for */
{
- int i, j;
- Vector2 Q; /* Point on curve at parameter t */
- Vector2 *Vtemp; /* Local copy of control points */
-
- /* Copy array */
- Vtemp = (Vector2 *)malloc((unsigned)((degree+1)
- * sizeof (Vector2)));
- for (i = 0; i <= degree; i++) {
+ int i, j;
+ Vector2 Q; /* Point on curve at parameter t */
+ Vector2 *Vtemp; /* Local copy of control points */
+
+ /* Copy array */
+ Vtemp = (Vector2*)malloc((unsigned)((degree + 1) * sizeof (Vector2)));
+ for (i = 0; i <= degree; i++) {
Vtemp[i] = V[i];
- }
+ }
- /* Triangle computation */
- for (i = 1; i <= degree; i++) {
+ /* Triangle computation */
+ for (i = 1; i <= degree; i++) {
for (j = 0; j <= degree-i; j++) {
- Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j+1][0];
- Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j+1][1];
+ Vtemp[j][0] = (1.0 - t) * Vtemp[j][0] + t * Vtemp[j + 1][0];
+ Vtemp[j][1] = (1.0 - t) * Vtemp[j][1] + t * Vtemp[j + 1][1];
}
- }
+ }
- Q = Vtemp[0];
- free((void *)Vtemp);
- return Q;
+ Q = Vtemp[0];
+ free((void*)Vtemp);
+ return Q;
}
-
/*
- * B0, B1, B2, B3 :
- * Bezier multipliers
+ * B0, B1, B2, B3:
+ * Bezier multipliers
*/
static double B0(double u)
{
- double tmp = 1.0 - u;
- return (tmp * tmp * tmp);
+ double tmp = 1.0 - u;
+ return (tmp * tmp * tmp);
}
static double B1(double u)
{
- double tmp = 1.0 - u;
- return (3 * u * (tmp * tmp));
+ double tmp = 1.0 - u;
+ return (3 * u * (tmp * tmp));
}
static double B2(double u)
{
- double tmp = 1.0 - u;
- return (3 * u * u * tmp);
+ double tmp = 1.0 - u;
+ return (3 * u * u * tmp);
}
static double B3(double u)
{
- return (u * u * u);
+ return (u * u * u);
}
-
-
/*
- * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent :
- *Approximate unit tangents at endpoints and "center" of digitized curve
+ * ComputeLeftTangent, ComputeRightTangent, ComputeCenterTangent:
+ * Approximate unit tangents at endpoints and "center" of digitized curve
+ */
+/* Vector2 *d; Digitized points
+ * int end; Index to "left" end of region
*/
static Vector2 ComputeLeftTangent(Vector2 *d, int end)
-// Vector2 *d; /* Digitized points*/
-// int end; /* Index to "left" end of region */
{
- Vector2 tHat1;
- tHat1 = V2SubII(d[end+1], d[end]);
- tHat1 = *V2Normalize(&tHat1);
- return tHat1;
+ Vector2 tHat1;
+ tHat1 = V2SubII(d[end + 1], d[end]);
+ tHat1 = *V2Normalize(&tHat1);
+ return tHat1;
}
+/* Vector2 *d; Digitized points
+ * int end; Index to "right" end of region
+ */
static Vector2 ComputeRightTangent(Vector2 *d, int end)
-// Vector2 *d; /* Digitized points */
-// int end; /* Index to "right" end of region */
{
- Vector2 tHat2;
- tHat2 = V2SubII(d[end-1], d[end]);
- tHat2 = *V2Normalize(&tHat2);
- return tHat2;
+ Vector2 tHat2;
+ tHat2 = V2SubII(d[end - 1], d[end]);
+ tHat2 = *V2Normalize(&tHat2);
+ return tHat2;
}
+/* Vector2 *d; Digitized points
+ * int end; Index to point inside region
+ */
static Vector2 ComputeCenterTangent(Vector2 *d, int center)
-// Vector2 *d; /* Digitized points */
-// int center; /* Index to point inside region */
{
- Vector2 V1, V2, tHatCenter;
-
- V1 = V2SubII(d[center-1], d[center]);
- V2 = V2SubII(d[center], d[center+1]);
- tHatCenter[0] = (V1[0] + V2[0])/2.0;
- tHatCenter[1] = (V1[1] + V2[1])/2.0;
- tHatCenter = *V2Normalize(&tHatCenter);
- return tHatCenter;
+ Vector2 V1, V2, tHatCenter;
+
+ V1 = V2SubII(d[center - 1], d[center]);
+ V2 = V2SubII(d[center], d[center + 1]);
+ tHatCenter[0] = (V1[0] + V2[0]) / 2.0;
+ tHatCenter[1] = (V1[1] + V2[1]) / 2.0;
+ tHatCenter = *V2Normalize(&tHatCenter);
+ return tHatCenter;
}
-
/*
- * ChordLengthParameterize :
- * Assign parameter values to digitized points
- * using relative distances between points.
+ * ChordLengthParameterize:
+ * Assign parameter values to digitized points using relative distances between points.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
*/
static double *ChordLengthParameterize(Vector2 *d, int first, int last)
-// Vector2 *d; /* Array of digitized points */
-// int first, last; /* Indices defining region */
{
- int i;
- double *u; /* Parameterization */
+ int i;
+ double *u; /* Parameterization */
- u = (double *)malloc((unsigned)(last-first+1) * sizeof(double));
+ u = (double*)malloc((unsigned)(last - first + 1) * sizeof(double));
- u[0] = 0.0;
- for (i = first+1; i <= last; i++) {
- u[i-first] = u[i-first-1] +
- V2DistanceBetween2Points(&d[i], &d[i-1]);
- }
+ u[0] = 0.0;
+ for (i = first + 1; i <= last; i++) {
+ u[i - first] = u[i - first - 1] + V2DistanceBetween2Points(&d[i], &d[i - 1]);
+ }
- for (i = first + 1; i <= last; i++) {
- u[i-first] = u[i-first] / u[last-first];
- }
+ for (i = first + 1; i <= last; i++) {
+ u[i - first] = u[i - first] / u[last - first];
+ }
- return(u);
+ return u;
}
@@ -426,53 +430,57 @@ static double *ChordLengthParameterize(Vector2 *d, int first, int last)
/*
* ComputeMaxError :
- * Find the maximum squared distance of digitized points
- * to fitted curve.
-*/
+ * Find the maximum squared distance of digitized points to fitted curve.
+ * Vector2 *d; Array of digitized points
+ * int first, last; Indices defining region
+ * BezierCurve bezCurve; Fitted Bezier curve
+ * double *u; Parameterization of points
+ * int *splitPoint; Point of maximum error
+ */
static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
-// Vector2 *d; /* Array of digitized points */
-// int first, last; /* Indices defining region */
-// BezierCurve bezCurve; /* Fitted Bezier curve */
-// double *u; /* Parameterization of points */
-// int *splitPoint; /* Point of maximum error */
{
- int i;
- double maxDist; /* Maximum error */
- double dist; /* Current error */
- Vector2 P; /* Point on curve */
- Vector2 v; /* Vector from point to curve */
-
- *splitPoint = (last - first + 1)/2;
- maxDist = 0.0;
- for (i = first + 1; i < last; i++) {
- P = BezierII(3, bezCurve, u[i-first]);
+ int i;
+ double maxDist; /* Maximum error */
+ double dist; /* Current error */
+ Vector2 P; /* Point on curve */
+ Vector2 v; /* Vector from point to curve */
+
+ *splitPoint = (last - first + 1) / 2;
+ maxDist = 0.0;
+ for (i = first + 1; i < last; i++) {
+ P = BezierII(3, bezCurve, u[i - first]);
v = V2SubII(P, d[i]);
dist = V2SquaredLength(&v);
if (dist >= maxDist) {
- maxDist = dist;
- *splitPoint = i;
+ maxDist = dist;
+ *splitPoint = i;
}
- }
- return (maxDist);
+ }
+ return maxDist;
}
+
static Vector2 V2AddII(Vector2 a, Vector2 b)
{
- Vector2 c;
- c[0] = a[0] + b[0]; c[1] = a[1] + b[1];
- return (c);
+ Vector2 c;
+ c[0] = a[0] + b[0];
+ c[1] = a[1] + b[1];
+ return c;
}
+
static Vector2 V2ScaleIII(Vector2 v, double s)
{
- Vector2 result;
- result[0] = v[0] * s; result[1] = v[1] * s;
- return (result);
+ Vector2 result;
+ result[0] = v[0] * s;
+ result[1] = v[1] * s;
+ return result;
}
static Vector2 V2SubII(Vector2 a, Vector2 b)
{
- Vector2 c;
- c[0] = a[0] - b[0]; c[1] = a[1] - b[1];
- return (c);
+ Vector2 c;
+ c[0] = a[0] - b[0];
+ c[1] = a[1] - b[1];
+ return c;
}
#ifdef __cplusplus
@@ -488,116 +496,107 @@ FitCurveWrapper::FitCurveWrapper()
FitCurveWrapper::~FitCurveWrapper()
{
- _vertices.clear();
+ _vertices.clear();
}
-void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve )
+void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve)
{
- for(int i=0; i<n+1; ++i)
- _vertices.push_back(curve[i]);
+ for (int i = 0; i < n + 1; ++i)
+ _vertices.push_back(curve[i]);
}
void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
{
- int size = data.size();
- Vector2 *d = new Vector2[size];
- for(int i=0; i<size; ++i)
- {
- d[i][0] = data[i][0];
- d[i][1] = data[i][1];
- }
-
- FitCurve(d,size,error);
-
- // copy results
- for(vector<Vector2>::iterator v=_vertices.begin(), vend=_vertices.end();
- v!=vend;
- ++v)
- {
- oCurve.push_back(Vec2d(v->x(), v->y())) ;
- }
-
+ int size = data.size();
+ Vector2 *d = new Vector2[size];
+ for (int i = 0; i < size; ++i) {
+ d[i][0] = data[i][0];
+ d[i][1] = data[i][1];
+ }
+
+ FitCurve(d, size, error);
+
+ // copy results
+ for (vector<Vector2>::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
+ oCurve.push_back(Vec2d(v->x(), v->y())) ;
+ }
}
void FitCurveWrapper::FitCurve(Vector2 *d, int nPts, double error)
{
- Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
+ Vector2 tHat1, tHat2; /* Unit tangent vectors at endpoints */
- tHat1 = ComputeLeftTangent(d, 0);
- tHat2 = ComputeRightTangent(d, nPts - 1);
- FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
+ tHat1 = ComputeLeftTangent(d, 0);
+ tHat2 = ComputeRightTangent(d, nPts - 1);
+ FitCubic(d, 0, nPts - 1, tHat1, tHat2, error);
}
void FitCurveWrapper::FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error)
{
- BezierCurve bezCurve; /*Control points of fitted Bezier curve*/
- double *u; /* Parameter values for point */
- double *uPrime; /* Improved parameter values */
- double maxError; /* Maximum fitting error */
- int splitPoint; /* Point to split point set at */
- int nPts; /* Number of points in subset */
- double iterationError; /*Error below which you try iterating */
- int maxIterations = 4; /* Max times to try iterating */
- Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
- int i;
-
- iterationError = error * error;
- nPts = last - first + 1;
-
- /* Use heuristic if region only has two points in it */
- if (nPts == 2) {
- double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
-
- bezCurve = (Vector2 *)malloc(4 * sizeof(Vector2));
+ BezierCurve bezCurve; /* Control points of fitted Bezier curve */
+ double *u; /* Parameter values for point */
+ double *uPrime; /* Improved parameter values */
+ double maxError; /* Maximum fitting error */
+ int splitPoint; /* Point to split point set at */
+ int nPts; /* Number of points in subset */
+ double iterationError; /* Error below which you try iterating */
+ int maxIterations = 4; /* Max times to try iterating */
+ Vector2 tHatCenter; /* Unit tangent vector at splitPoint */
+ int i;
+
+ iterationError = error * error;
+ nPts = last - first + 1;
+
+ /* Use heuristic if region only has two points in it */
+ if (nPts == 2) {
+ double dist = V2DistanceBetween2Points(&d[last], &d[first]) / 3.0;
+
+ bezCurve = (Vector2*)malloc(4 * sizeof(Vector2));
bezCurve[0] = d[first];
bezCurve[3] = d[last];
V2Add(&bezCurve[0], V2Scale(&tHat1, dist), &bezCurve[1]);
V2Add(&bezCurve[3], V2Scale(&tHat2, dist), &bezCurve[2]);
DrawBezierCurve(3, bezCurve);
- free((void *)bezCurve);
+ free((void*)bezCurve);
return;
- }
+ }
- /* Parameterize points, and attempt to fit curve */
- u = ChordLengthParameterize(d, first, last);
- bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
+ /* Parameterize points, and attempt to fit curve */
+ u = ChordLengthParameterize(d, first, last);
+ bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
- /* Find max deviation of points to fitted curve */
- maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
- if (maxError < error) {
+ /* Find max deviation of points to fitted curve */
+ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
+ if (maxError < error) {
DrawBezierCurve(3, bezCurve);
- free((void *)u);
- free((void *)bezCurve);
+ free((void*)u);
+ free((void*)bezCurve);
return;
- }
-
+ }
- /* If error not too large, try some reparameterization */
- /* and iteration */
- if (maxError < iterationError) {
+ /* If error not too large, try some reparameterization and iteration */
+ if (maxError < iterationError) {
for (i = 0; i < maxIterations; i++) {
- uPrime = Reparameterize(d, first, last, u, bezCurve);
- bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
- maxError = ComputeMaxError(d, first, last,
- bezCurve, uPrime, &splitPoint);
- if (maxError < error) {
- DrawBezierCurve(3, bezCurve);
- free((void *)u);
- free((void *)bezCurve);
- return;
- }
- free((void *)u);
- u = uPrime;
+ uPrime = Reparameterize(d, first, last, u, bezCurve);
+ bezCurve = GenerateBezier(d, first, last, uPrime, tHat1, tHat2);
+ maxError = ComputeMaxError(d, first, last,
+ bezCurve, uPrime, &splitPoint);
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void*)u);
+ free((void*)bezCurve);
+ return;
+ }
+ free((void*)u);
+ u = uPrime;
+ }
}
- }
-
- /* Fitting failed -- split at max error point and fit recursively */
- free((void *)u);
- free((void *)bezCurve);
- tHatCenter = ComputeCenterTangent(d, splitPoint);
- FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
- V2Negate(&tHatCenter);
- FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
+ /* Fitting failed -- split at max error point and fit recursively */
+ free((void*)u);
+ free((void*)bezCurve);
+ tHatCenter = ComputeCenterTangent(d, splitPoint);
+ FitCubic(d, first, splitPoint, tHat1, tHatCenter, error);
+ V2Negate(&tHatCenter);
+ FitCubic(d, splitPoint, last, tHatCenter, tHat2, error);
}
-
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h
index ed7cbe34780..0a80c2f28f9 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.h
+++ b/source/blender/freestyle/intern/geometry/FitCurve.h
@@ -1,101 +1,125 @@
-//
-// Filename : FitCurve.h
-// Author(s) : Stephane Grabli
-// Purpose : An Algorithm for Automatically Fitting Digitized Curves
-// by Philip J. Schneider
-// from "Graphics Gems", Academic Press, 1990
-// Date of creation : 06/06/2003
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-//
-// 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 FITCURVE_H
-# define FITCURVE_H
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __FITCURVE_H__
+#define __FITCURVE_H__
+
+/** \file blender/freestyle/intern/geometry/FitCurve.h
+ * \ingroup freestyle
+ * \brief An Algorithm for Automatically Fitting Digitized Curves by Philip J. Schneider,
+ * \brief from "Graphics Gems", Academic Press, 1990
+ * \author Stephane Grabli
+ * \date 06/06/2003
+ */
#include <vector>
-#include "../system/FreestyleConfig.h"
+
#include "Geom.h"
+#include "../system/FreestyleConfig.h"
+
using namespace Geometry;
-typedef struct Point2Struct { /* 2d point */
+/* 2d point */
+typedef struct Point2Struct
+{
double coordinates[2];
- Point2Struct() {coordinates[0]=0;coordinates[1]=0;}
- inline double operator[](const int i) const
- {
- return coordinates[i];
- }
- inline double& operator[](const int i)
- {
- return coordinates[i];
- }
- inline double x() const {return coordinates[0];}
- inline double y() const {return coordinates[1];}
- } Point2;
-typedef Point2 Vector2;
+ Point2Struct()
+ {
+ coordinates[0] = 0;
+ coordinates[1] = 0;
+ }
+
+ inline double operator[](const int i) const
+ {
+ return coordinates[i];
+ }
+ inline double& operator[](const int i)
+ {
+ return coordinates[i];
+ }
+
+ inline double x() const
+ {
+ return coordinates[0];
+ }
+
+ inline double y() const
+ {
+ return coordinates[1];
+ }
+} Point2;
+
+typedef Point2 Vector2;
class LIB_GEOMETRY_EXPORT FitCurveWrapper
{
private:
- std::vector<Vector2> _vertices;
+ std::vector<Vector2> _vertices;
public:
- FitCurveWrapper();
- ~FitCurveWrapper();
-
- /*! Fits a set of 2D data points to a set of Bezier Curve segments
- * data
- * Input data points
- * oCurve
- * Control points of the sets of bezier curve segments.
- * Each segment is made of 4 points (polynomial degree of curve = 3)
- * error
- * max error tolerance between resulting curve and input data
- */
- void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
+ FitCurveWrapper();
+ ~FitCurveWrapper();
+
+ /*! Fits a set of 2D data points to a set of Bezier Curve segments
+ * data
+ * Input data points
+ * oCurve
+ * Control points of the sets of bezier curve segments.
+ * Each segment is made of 4 points (polynomial degree of curve = 3)
+ * error
+ * max error tolerance between resulting curve and input data
+ */
+ void FitCurve(std::vector<Vec2d>& data, std::vector<Vec2d>& oCurve, double error);
+
protected:
- /* Vec2d *d; Array of digitized points */
- /* int nPts; Number of digitized points */
- /* double error; User-defined error squared */
- void FitCurve(Vector2 *d, int nPts, double error);
-
- /*! Draws a Bezier curve segment
- * n
- * degree of curve (=3)
- * curve
- * bezier segments control points
- */
- void DrawBezierCurve(int n, Vector2 *curve);
-
- /* Vec2d *d; Array of digitized points */
- /* int first, last; Indices of first and last pts in region */
- /* Vec2d tHat1, tHat2; Unit tangent vectors at endpoints */
- /* double error; User-defined error squared */
- void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
-
+ /* Vec2d *d; Array of digitized points
+ * int nPts; Number of digitized points
+ * double error; User-defined error squared
+ */
+ void FitCurve(Vector2 *d, int nPts, double error);
+
+ /*! Draws a Bezier curve segment
+ * n
+ * degree of curve (=3)
+ * curve
+ * bezier segments control points
+ */
+ void DrawBezierCurve(int n, Vector2 *curve);
+
+ /* Vec2d *d; Array of digitized points
+ * int first, last; Indices of first and last pts in region
+ * Vec2d tHat1, tHat2; Unit tangent vectors at endpoints
+ * double error; User-defined error squared
+ */
+ void FitCubic(Vector2 *d, int first, int last, Vector2 tHat1, Vector2 tHat2, double error);
};
-#endif // FITCURVE_H
+#endif // __FITCURVE_H__
diff --git a/source/blender/freestyle/intern/geometry/Geom.h b/source/blender/freestyle/intern/geometry/Geom.h
index ac94213fe98..f241346ec85 100644
--- a/source/blender/freestyle/intern/geometry/Geom.h
+++ b/source/blender/freestyle/intern/geometry/Geom.h
@@ -1,78 +1,84 @@
-//
-// Filename : Geom.h
-// Author(s) : Sylvain Paris
-// Emmanuel Turquin
-// Stephane Grabli
-// Purpose : Vectors and Matrices (useful type definitions)
-// Date of creation : 20/05/2003
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __GEOM_H__
+#define __GEOM_H__
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/Geom.h
+ * \ingroup freestyle
+ * \brief Vectors and Matrices (useful type definitions)
+ * \author Sylvain Paris
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 20/05/2003
+ */
-#ifndef GEOM_H
-# define GEOM_H
+#include "VecMat.h"
-# include "VecMat.h"
-# include "../system/Precision.h"
+#include "../system/Precision.h"
namespace Geometry {
- typedef VecMat::Vec2<unsigned> Vec2u;
- typedef VecMat::Vec2<int> Vec2i;
- typedef VecMat::Vec2<float> Vec2f;
- typedef VecMat::Vec2<double> Vec2d;
- typedef VecMat::Vec2<real> Vec2r;
+typedef VecMat::Vec2<unsigned> Vec2u;
+typedef VecMat::Vec2<int> Vec2i;
+typedef VecMat::Vec2<float> Vec2f;
+typedef VecMat::Vec2<double> Vec2d;
+typedef VecMat::Vec2<real> Vec2r;
- typedef VecMat::Vec3<unsigned> Vec3u;
- typedef VecMat::Vec3<int> Vec3i;
- typedef VecMat::Vec3<float> Vec3f;
- typedef VecMat::Vec3<double> Vec3d;
- typedef VecMat::Vec3<real> Vec3r;
+typedef VecMat::Vec3<unsigned> Vec3u;
+typedef VecMat::Vec3<int> Vec3i;
+typedef VecMat::Vec3<float> Vec3f;
+typedef VecMat::Vec3<double> Vec3d;
+typedef VecMat::Vec3<real> Vec3r;
- typedef VecMat::HVec3<unsigned> HVec3u;
- typedef VecMat::HVec3<int> HVec3i;
- typedef VecMat::HVec3<float> HVec3f;
- typedef VecMat::HVec3<double> HVec3d;
- typedef VecMat::HVec3<real> HVec3r;
+typedef VecMat::HVec3<unsigned> HVec3u;
+typedef VecMat::HVec3<int> HVec3i;
+typedef VecMat::HVec3<float> HVec3f;
+typedef VecMat::HVec3<double> HVec3d;
+typedef VecMat::HVec3<real> HVec3r;
- typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
- typedef VecMat::SquareMatrix<int, 2> Matrix22i;
- typedef VecMat::SquareMatrix<float, 2> Matrix22f;
- typedef VecMat::SquareMatrix<double, 2> Matrix22d;
- typedef VecMat::SquareMatrix<real, 2> Matrix22r;
+typedef VecMat::SquareMatrix<unsigned, 2> Matrix22u;
+typedef VecMat::SquareMatrix<int, 2> Matrix22i;
+typedef VecMat::SquareMatrix<float, 2> Matrix22f;
+typedef VecMat::SquareMatrix<double, 2> Matrix22d;
+typedef VecMat::SquareMatrix<real, 2> Matrix22r;
- typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
- typedef VecMat::SquareMatrix<int, 3> Matrix33i;
- typedef VecMat::SquareMatrix<float, 3> Matrix33f;
- typedef VecMat::SquareMatrix<double, 3> Matrix33d;
- typedef VecMat::SquareMatrix<real, 3> Matrix33r;
+typedef VecMat::SquareMatrix<unsigned, 3> Matrix33u;
+typedef VecMat::SquareMatrix<int, 3> Matrix33i;
+typedef VecMat::SquareMatrix<float, 3> Matrix33f;
+typedef VecMat::SquareMatrix<double, 3> Matrix33d;
+typedef VecMat::SquareMatrix<real, 3> Matrix33r;
- typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
- typedef VecMat::SquareMatrix<int, 4> Matrix44i;
- typedef VecMat::SquareMatrix<float, 4> Matrix44f;
- typedef VecMat::SquareMatrix<double, 4> Matrix44d;
- typedef VecMat::SquareMatrix<real, 4> Matrix44r;
+typedef VecMat::SquareMatrix<unsigned, 4> Matrix44u;
+typedef VecMat::SquareMatrix<int, 4> Matrix44i;
+typedef VecMat::SquareMatrix<float, 4> Matrix44f;
+typedef VecMat::SquareMatrix<double, 4> Matrix44d;
+typedef VecMat::SquareMatrix<real, 4> Matrix44r;
} // end of namespace Geometry
-#endif // GEOM_H
+#endif // __GEOM_H__
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
index c148c521a46..aba845a2faf 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -1,240 +1,233 @@
-
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-//#if defined(__GNUC__) && (__GNUC__ >= 3)
-//// hash_map is not part of the C++ standard anymore;
-//// hash_map.h has been kept though for backward compatibility
-//# include <hash_map.h>
-//#else
-//# include <hash_map>
-//#endif
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/GeomCleaner.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cleaner of geometry providing a set of useful tools
+ * \author Stephane Grabli
+ * \date 04/03/2002
+ */
+
+#if 0
+#if defined(__GNUC__) && (__GNUC__ >= 3)
+// hash_map is not part of the C++ standard anymore;
+// hash_map.h has been kept though for backward compatibility
+# include <hash_map.h>
+#else
+# include <hash_map>
+#endif
+#endif
#include <stdio.h>
#include <list>
#include <map>
-#include "../system/TimeUtils.h"
+
#include "GeomCleaner.h"
+#include "../system/TimeUtils.h"
+
using namespace std;
-void GeomCleaner::SortIndexedVertexArray( const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices,
- unsigned **oIndices)
+void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned **oIndices)
{
- // First, we build a list of IndexVertex:
- list<IndexedVertex> indexedVertices;
- unsigned i;
- for(i=0; i<iVSize; i+= 3)
- {
- indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]), i/3));
- }
-
- // q-sort
- indexedVertices.sort();
-
- // build the indices mapping array:
- unsigned *mapIndices = new unsigned[iVSize/3];
- *oVertices = new real[iVSize];
- list<IndexedVertex>::iterator iv;
- unsigned newIndex = 0;
- unsigned vIndex = 0;
- for(iv=indexedVertices.begin(); iv!=indexedVertices.end(); iv++)
- {
- // Build the final results:
- (*oVertices)[vIndex] = iv->x();
- (*oVertices)[vIndex+1] = iv->y();
- (*oVertices)[vIndex+2] = iv->z();
-
- mapIndices[iv->index()] = newIndex;
- newIndex++;
- vIndex+=3;
- }
-
-
- // Build the final index array:
- *oIndices = new unsigned[iISize];
- for(i=0; i<iISize; i++)
- {
- (*oIndices)[i] = 3*mapIndices[iIndices[i]/3];
- }
-
- delete [] mapIndices;
+ // First, we build a list of IndexVertex:
+ list<IndexedVertex> indexedVertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3) {
+ indexedVertices.push_back(IndexedVertex(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]), i / 3));
+ }
+
+ // q-sort
+ indexedVertices.sort();
+
+ // build the indices mapping array:
+ unsigned *mapIndices = new unsigned[iVSize / 3];
+ *oVertices = new real[iVSize];
+ list<IndexedVertex>::iterator iv;
+ unsigned newIndex = 0;
+ unsigned vIndex = 0;
+ for (iv = indexedVertices.begin(); iv != indexedVertices.end(); iv++) {
+ // Build the final results:
+ (*oVertices)[vIndex] = iv->x();
+ (*oVertices)[vIndex + 1] = iv->y();
+ (*oVertices)[vIndex + 2] = iv->z();
+
+ mapIndices[iv->index()] = newIndex;
+ newIndex++;
+ vIndex += 3;
+ }
+
+ // Build the final index array:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++) {
+ (*oIndices)[i] = 3 * mapIndices[iIndices[i] / 3];
+ }
+
+ delete [] mapIndices;
}
-void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
- unsigned **oIndices)
+void GeomCleaner::CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
{
- // First, we build a list of IndexVertex:
- vector<Vec3r> vertices;
- unsigned i;
- for(i=0; i<iVSize; i+= 3)
- {
- vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
- }
-
- unsigned *mapVertex = new unsigned[iVSize];
- vector<Vec3r>::iterator v = vertices.begin();
-
- vector<Vec3r> compressedVertices;
- Vec3r previous = *v;
- mapVertex[0] = 0;
- compressedVertices.push_back(vertices.front());
-
- v++;
- Vec3r current;
- i=1;
- for(; v!=vertices.end(); v++)
- {
- current = *v;
- if(current == previous)
- mapVertex[i] = compressedVertices.size()-1;
- else
- {
- compressedVertices.push_back(current);
- mapVertex[i] = compressedVertices.size()-1;
- }
- previous = current;
- i++;
- }
-
- // Builds the resulting vertex array:
- *oVSize = 3*compressedVertices.size();
- *oVertices = new real [*oVSize];
- i=0;
- for(v=compressedVertices.begin(); v!=compressedVertices.end(); v++)
- {
- (*oVertices)[i] = (*v)[0];
- (*oVertices)[i+1] = (*v)[1];
- (*oVertices)[i+2] = (*v)[2];
- i += 3;
- }
-
- // Map the index array:
- *oIndices = new unsigned[iISize];
- for(i=0; i<iISize; i++)
- {
- (*oIndices)[i] = 3*mapVertex[iIndices[i]/3];
- }
-
- delete [] mapVertex;
+ // First, we build a list of IndexVertex:
+ vector<Vec3r> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3) {
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+ }
+
+ unsigned *mapVertex = new unsigned[iVSize];
+ vector<Vec3r>::iterator v = vertices.begin();
+
+ vector<Vec3r> compressedVertices;
+ Vec3r previous = *v;
+ mapVertex[0] = 0;
+ compressedVertices.push_back(vertices.front());
+
+ v++;
+ Vec3r current;
+ i = 1;
+ for (; v != vertices.end(); v++) {
+ current = *v;
+ if (current == previous)
+ mapVertex[i] = compressedVertices.size() - 1;
+ else {
+ compressedVertices.push_back(current);
+ mapVertex[i] = compressedVertices.size() - 1;
+ }
+ previous = current;
+ i++;
+ }
+
+ // Builds the resulting vertex array:
+ *oVSize = 3 * compressedVertices.size();
+ *oVertices = new real[*oVSize];
+ i = 0;
+ for (v = compressedVertices.begin(); v != compressedVertices.end(); v++) {
+ (*oVertices)[i] = (*v)[0];
+ (*oVertices)[i + 1] = (*v)[1];
+ (*oVertices)[i + 2] = (*v)[2];
+ i += 3;
+ }
+
+ // Map the index array:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++) {
+ (*oIndices)[i] = 3 * mapVertex[iIndices[i] / 3];
+ }
+
+ delete [] mapVertex;
}
-void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
+void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize,
unsigned **oIndices)
{
-
- // tmp arrays used to store the sorted data:
- real *tmpVertices;
- unsigned *tmpIndices;
-
- Chronometer chrono;
- // Sort data
- chrono.start();
- GeomCleaner::SortIndexedVertexArray(iVertices, iVSize,
- iIndices, iISize,
- &tmpVertices, &tmpIndices
- );
- printf("Sorting: %lf\n", chrono.stop());
-
- // compress data
- chrono.start();
- GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize,
- tmpIndices, iISize,
- oVertices, oVSize,
- oIndices);
- printf("Merging: %lf\n", chrono.stop());
-
- // deallocates memory:
- delete [] tmpVertices;
- delete [] tmpIndices;
+ // tmp arrays used to store the sorted data:
+ real *tmpVertices;
+ unsigned *tmpIndices;
+
+ Chronometer chrono;
+ // Sort data
+ chrono.start();
+ GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
+ printf("Sorting: %lf\n", chrono.stop());
+
+ // compress data
+ chrono.start();
+ GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
+ printf("Merging: %lf\n", chrono.stop());
+
+ // deallocates memory:
+ delete [] tmpVertices;
+ delete [] tmpIndices;
}
/*! Defines a hash table used for searching the Cells */
struct GeomCleanerHasher{
#define _MUL 950706376UL
#define _MOD 2147483647UL
- inline size_t operator() (const Vec3r& p) const {
- size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
- res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
- return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
- }
+ inline size_t operator() (const Vec3r& p) const
+ {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+#undef _MUL
+#undef _MOD
};
-void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
- unsigned **oIndices)
+void GeomCleaner::CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices)
{
- typedef map<Vec3r, unsigned> cleanHashTable;
- vector<Vec3r> vertices;
- unsigned i;
- for(i=0; i<iVSize; i+= 3)
- vertices.push_back(Vec3r(iVertices[i], iVertices[i+1], iVertices[i+2]));
-
- cleanHashTable ht;
- vector<unsigned> newIndices;
- vector<Vec3r> newVertices;
-
- // elimination of needless points
- unsigned currentIndex = 0;
- vector<Vec3r>::const_iterator v = vertices.begin();
- vector<Vec3r>::const_iterator end = vertices.end();
- cleanHashTable::const_iterator found;
- for(; v!=end; v++)
- {
- found = ht.find(*v);
- if(found != ht.end())
- {
- // The vertex is already in the new array.
- newIndices.push_back((*found).second);
- }
- else
- {
- newVertices.push_back(*v);
- newIndices.push_back(currentIndex);
- ht[*v] = currentIndex;
- currentIndex++;
- }
- }
-
- // creation of oVertices array:
- *oVSize = 3*newVertices.size();
- *oVertices = new real[*oVSize];
- currentIndex = 0;
- end = newVertices.end();
- for(v=newVertices.begin(); v!=end ; v++)
- {
- (*oVertices)[currentIndex++] = (*v)[0];
- (*oVertices)[currentIndex++] = (*v)[1];
- (*oVertices)[currentIndex++] = (*v)[2];
- }
-
- // map new indices:
- *oIndices = new unsigned[iISize];
- for(i=0; i<iISize; i++)
- (*oIndices)[i] = 3*newIndices[iIndices[i]/3];
+ typedef map<Vec3r, unsigned> cleanHashTable;
+ vector<Vec3r> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3)
+ vertices.push_back(Vec3r(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+
+ cleanHashTable ht;
+ vector<unsigned> newIndices;
+ vector<Vec3r> newVertices;
+
+ // elimination of needless points
+ unsigned currentIndex = 0;
+ vector<Vec3r>::const_iterator v = vertices.begin();
+ vector<Vec3r>::const_iterator end = vertices.end();
+ cleanHashTable::const_iterator found;
+ for (; v != end; v++) {
+ found = ht.find(*v);
+ if (found != ht.end()) {
+ // The vertex is already in the new array.
+ newIndices.push_back((*found).second);
+ }
+ else {
+ newVertices.push_back(*v);
+ newIndices.push_back(currentIndex);
+ ht[*v] = currentIndex;
+ currentIndex++;
+ }
+ }
+
+ // creation of oVertices array:
+ *oVSize = 3 * newVertices.size();
+ *oVertices = new real[*oVSize];
+ currentIndex = 0;
+ end = newVertices.end();
+ for (v = newVertices.begin(); v != end ; v++) {
+ (*oVertices)[currentIndex++] = (*v)[0];
+ (*oVertices)[currentIndex++] = (*v)[1];
+ (*oVertices)[currentIndex++] = (*v)[2];
+ }
+
+ // map new indices:
+ *oIndices = new unsigned[iISize];
+ for (i = 0; i < iISize; i++)
+ (*oIndices)[i] = 3 * newIndices[iIndices[i] / 3];
}
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
index 5fdfda0162a..334145f3bcd 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.h
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -1,219 +1,227 @@
-//
-// Filename : GeomCleaner.h
-// Author : Stephane Grabli
-// Purpose : Class to define a cleaner of geometry providing
-// a set of useful tools
-// Date of creation : 04/03/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 GEOMCLEANER_H
-# define GEOMCLEANER_H
-
-# include "../system/FreestyleConfig.h"
-# include "Geom.h"
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GEOMCLEANER_H__
+#define __GEOMCLEANER_H__
+
+/** \file blender/freestyle/intern/geometry/GeomCleaner.h
+ * \ingroup freestyle
+ * \brief Class to define a cleaner of geometry providing a set of useful tools
+ * \author Stephane Grabli
+ * \date 04/03/2002
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
using namespace Geometry;
class LIB_GEOMETRY_EXPORT GeomCleaner
{
public:
-
- inline GeomCleaner() {}
- inline ~GeomCleaner() {}
-
- /*! Sorts an array of Indexed vertices
- * iVertices
- * Array of vertices to sort. It is organized as a
- * float series of vertex coordinates: XYZXYZXYZ...
- * iVSize
- * The size of iVertices array.
- * iIndices
- * The array containing the vertex indices (used to refer
- * to the vertex coordinates in an indexed face). Each
- * element is an unsignedeger multiple of 3.
- * iISize
- * The size of iIndices array
- * oVertices
- * Output of sorted vertices. A vertex v1 precedes another one
- * v2 in this array if v1.x<v2.x, or v1.x=v2.x && v1.y < v2.y
- * or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
- * The array is organized as a 3-float serie giving
- * the vertices coordinates: XYZXYZXYZ...
- * oIndices
- * Output corresponding to the iIndices array but
- * reorganized in order to match the sorted vertex array.
- */
-
- static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices,
- unsigned **oIndices);
-
- /*! Compress a SORTED indexed vertex array by eliminating
- * multiple appearing occurences of a single vertex.
- * iVertices
- * The SORTED vertex array to compress. It is organized as a
- * float series of vertex coordinates: XYZXYZXYZ...
- * iVSize
- * The size of iVertices array.
- * iIndices
- * The array containing the vertex indices (used to refer
- * to the vertex coordinates in an indexed face). Each
- * element is an unsignedeger multiple of 3.
- * iISize
- * The size of iIndices array
- * oVertices
- * The vertex array, result of the compression.
- * The array is organized as a 3-float serie giving
- * the vertices coordinates: XYZXYZXYZ...
- * oVSize
- * The size of oVertices.
- * oIndices
- * The indices array, reorganized to match the compressed
- * oVertices array.
- */
-
- static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
- unsigned **oIndices);
-
- /*! Sorts and compress an array of indexed vertices.
- * iVertices
- * The vertex array to sort then compress. It is organized as a
- * float series of vertex coordinates: XYZXYZXYZ...
- * iVSize
- * The size of iVertices array.
- * iIndices
- * The array containing the vertex indices (used to refer
- * to the vertex coordinates in an indexed face). Each
- * element is an unsignedeger multiple of 3.
- * iISize
- * The size of iIndices array
- * oVertices
- * The vertex array, result of the sorting-compression.
- * The array is organized as a 3-float serie giving
- * the vertices coordinates: XYZXYZXYZ...
- * oVSize
- * The size of oVertices.
- * oIndices
- * The indices array, reorganized to match the sorted and compressed
- * oVertices array.
- */
-
- static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
- unsigned **oIndices);
-
- /*! Cleans an indexed vertex array. (Identical to
- * SortAndCompress except that we use here a hash
- * table to create the new array.)
- * iVertices
- * The vertex array to sort then compress. It is organized as a
- * float series of vertex coordinates: XYZXYZXYZ...
- * iVSize
- * The size of iVertices array.
- * iIndices
- * The array containing the vertex indices (used to refer
- * to the vertex coordinates in an indexed face). Each
- * element is an unsignedeger multiple of 3.
- * iISize
- * The size of iIndices array
- * oVertices
- * The vertex array, result of the sorting-compression.
- * The array is organized as a 3-float serie giving
- * the vertices coordinates: XYZXYZXYZ...
- * oVSize
- * The size of oVertices.
- * oIndices
- * The indices array, reorganized to match the sorted and compressed
- * oVertices array.
- */
-
- static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize,
- const unsigned *iIndices, unsigned iISize,
- real **oVertices, unsigned *oVSize,
- unsigned **oIndices);
+ inline GeomCleaner() {}
+ inline ~GeomCleaner() {}
+
+ /*! Sorts an array of Indexed vertices
+ * iVertices
+ * Array of vertices to sort. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face). Each
+ * element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * Output of sorted vertices. A vertex v1 precedes another one v2 in this array if v1.x<v2.x,
+ * or v1.x=v2.x && v1.y < v2.y or v1.x=v2.y && v1.y=v2.y && v1.z < v2.z.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oIndices
+ * Output corresponding to the iIndices array but reorganized in order to match the sorted vertex array.
+ */
+ static void SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned **oIndices);
+
+ /*! Compress a SORTED indexed vertex array by eliminating multiple appearing occurences of a single vertex.
+ * iVertices
+ * The SORTED vertex array to compress. It is organized as a float series of vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the compressed oVertices array.
+ */
+ static void CompressIndexedVertexArray(const real *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
+
+ /*! Sorts and compress an array of indexed vertices.
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a float series of
+ * vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed oVertices array.
+ */
+ static void SortAndCompressIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize,
+ unsigned **oIndices);
+
+ /*! Cleans an indexed vertex array. (Identical to SortAndCompress except that we use here a hash table
+ * to create the new array.)
+ * iVertices
+ * The vertex array to sort then compress. It is organized as a float series of
+ * vertex coordinates: XYZXYZXYZ...
+ * iVSize
+ * The size of iVertices array.
+ * iIndices
+ * The array containing the vertex indices (used to refer to the vertex coordinates in an indexed face).
+ * Each element is an unsignedeger multiple of 3.
+ * iISize
+ * The size of iIndices array
+ * oVertices
+ * The vertex array, result of the sorting-compression.
+ * The array is organized as a 3-float serie giving the vertices coordinates: XYZXYZXYZ...
+ * oVSize
+ * The size of oVertices.
+ * oIndices
+ * The indices array, reorganized to match the sorted and compressed oVertices array.
+ */
+ static void CleanIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
+ unsigned iISize, real **oVertices, unsigned *oVSize, unsigned **oIndices);
};
/*! Binary operators */
//inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
-/*! Class Indexed Vertex. Used to represent
- * an indexed vertex by storing the vertex
- * coordinates as well as its index
- */
+/*! Class Indexed Vertex. Used to represent an indexed vertex by storing the vertex coordinates as well as its index */
class IndexedVertex
{
-public:
-
private:
- Vec3r _Vector;
- unsigned _index;
+ Vec3r _Vector;
+ unsigned _index;
+
public:
- inline IndexedVertex() {}
- inline IndexedVertex(Vec3r iVector, unsigned iIndex)
- {
- _Vector = iVector;
- _index = iIndex;
- }
- /*! accessors */
- inline const Vec3r& vector() const {return _Vector;}
- inline unsigned index() {return _index;}
- inline real x() {return _Vector[0];}
- inline real y() {return _Vector[1];}
- inline real z() {return _Vector[2];}
-
- /*! modifiers */
- inline void setVector(const Vec3r& iVector) {_Vector = iVector;}
- inline void setIndex(unsigned iIndex) {_index = iIndex;}
-
- /*! operators */
- IndexedVertex& operator=(const IndexedVertex& iv)
- {
- _Vector = iv._Vector;
- _index = iv._index;
- return *this;
- }
- inline real operator[](const unsigned i) {return _Vector[i];}
- //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
- inline bool operator<(const IndexedVertex& v) const
- {
- return (_Vector < v._Vector);
- }
- inline bool operator==(const IndexedVertex& v)
- {
- return (_Vector == v._Vector);
- }
+ inline IndexedVertex() {}
+
+ inline IndexedVertex(Vec3r iVector, unsigned iIndex)
+ {
+ _Vector = iVector;
+ _index = iIndex;
+ }
+
+ /*! accessors */
+ inline const Vec3r& vector() const
+ {
+ return _Vector;
+ }
+
+ inline unsigned index()
+ {
+ return _index;
+ }
+
+ inline real x()
+ {
+ return _Vector[0];
+ }
+
+ inline real y()
+ {
+ return _Vector[1];
+ }
+
+ inline real z()
+ {
+ return _Vector[2];
+ }
+
+ /*! modifiers */
+ inline void setVector(const Vec3r& iVector)
+ {
+ _Vector = iVector;
+ }
+
+ inline void setIndex(unsigned iIndex)
+ {
+ _index = iIndex;
+ }
+
+ /*! operators */
+ IndexedVertex& operator=(const IndexedVertex& iv)
+ {
+ _Vector = iv._Vector;
+ _index = iv._index;
+ return *this;
+ }
+
+ inline real operator[](const unsigned i)
+ {
+ return _Vector[i];
+ }
+
+ //friend inline bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2);
+ inline bool operator<(const IndexedVertex& v) const
+ {
+ return (_Vector < v._Vector);
+ }
+
+ inline bool operator==(const IndexedVertex& v)
+ {
+ return (_Vector == v._Vector);
+ }
};
-//bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
-//{
-// return iv1.operator<(iv2);
-//}
+#if 0
+bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
+{
+ return iv1.operator<(iv2);
+}
+#endif
-#endif // GEOMCLEANER_H
+#endif // __GEOMCLEANER_H__
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.cpp b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
index 61c306e46ee..9d449305466 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -1,753 +1,781 @@
-
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/GeomUtils.cpp
+ * \ingroup freestyle
+ * \brief Various tools for geometry
+ * \author Stephane Grabli
+ * \date 12/04/2002
+ */
#include "GeomUtils.h"
namespace GeomUtils {
- // This internal procedure is defined below.
- bool intersect2dSegPoly(Vec2r* seg,
- Vec2r* poly,
- unsigned n);
-
- bool intersect2dSeg2dArea(const Vec2r& min,
- const Vec2r& max,
- const Vec2r& A,
- const Vec2r& B) {
- Vec2r seg[2];
- seg[0] = A;
- seg[1] = B;
-
- Vec2r poly[5];
- poly[0][0] = min[0];
- poly[0][1] = min[1];
- poly[1][0] = max[0];
- poly[1][1] = min[1];
- poly[2][0] = max[0];
- poly[2][1] = max[1];
- poly[3][0] = min[0];
- poly[3][1] = max[1];
- poly[4][0] = min[0];
- poly[4][1] = min[1];
-
- return intersect2dSegPoly(seg, poly, 4);
- }
-
- bool include2dSeg2dArea(const Vec2r& min,
- const Vec2r& max,
- const Vec2r& A,
- const Vec2r& B) {
- if((((max[0] > A[0])&&(A[0] > min[0]))&&((max[0] > B[0])&&(B[0] > min[0])))
- && (((max[1] > A[1])&&(A[1] > min[1]))&&((max[1] > B[1])&&(B[1] > min[1]))))
- return true;
- return false;
- }
-
- intersection_test intersect2dSeg2dSeg(const Vec2r& p1,
- const Vec2r& p2,
- const Vec2r& p3,
- const Vec2r& p4,
- Vec2r& res) {
- real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
- real r1, r2, r3, r4; // 'Sign' values
- real denom, num; // Intermediate values
-
- // Compute a1, b1, c1, where line joining points p1 and p2
- // is "a1 x + b1 y + c1 = 0".
- a1 = p2[1] - p1[1];
- b1 = p1[0] - p2[0];
- c1 = p2[0] * p1[1] - p1[0] * p2[1];
-
- // Compute r3 and r4.
- r3 = a1 * p3[0] + b1 * p3[1] + c1;
- r4 = a1 * p4[0] + b1 * p4[1] + c1;
-
- // Check signs of r3 and r4. If both point 3 and point 4 lie on
- // same side of line 1, the line segments do not intersect.
- if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
- return (DONT_INTERSECT);
-
- // Compute a2, b2, c2
- a2 = p4[1] - p3[1];
- b2 = p3[0] - p4[0];
- c2 = p4[0] * p3[1] - p3[0] * p4[1];
-
- // Compute r1 and r2
- r1 = a2 * p1[0] + b2 * p1[1] + c2;
- r2 = a2 * p2[0] + b2 * p2[1] + c2;
-
- // Check signs of r1 and r2. If both point 1 and point 2 lie
- // on same side of second line segment, the line segments do
- // not intersect.
- if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
- return (DONT_INTERSECT);
-
- // Line segments intersect: compute intersection point.
- denom = a1 * b2 - a2 * b1;
- if (fabs(denom) < M_EPSILON)
- return (COLINEAR);
-
- num = b1 * c2 - b2 * c1;
- res[0] = num / denom;
-
- num = a2 * c1 - a1 * c2;
- res[1] = num / denom;
-
- return (DO_INTERSECT);
- }
-
- intersection_test intersect2dLine2dLine(const Vec2r& p1,
- const Vec2r& p2,
- const Vec2r& p3,
- const Vec2r& p4,
- Vec2r& res) {
- real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
- real denom, num; // Intermediate values
-
- // Compute a1, b1, c1, where line joining points p1 and p2
- // is "a1 x + b1 y + c1 = 0".
- a1 = p2[1] - p1[1];
- b1 = p1[0] - p2[0];
- c1 = p2[0] * p1[1] - p1[0] * p2[1];
-
- // Compute a2, b2, c2
- a2 = p4[1] - p3[1];
- b2 = p3[0] - p4[0];
- c2 = p4[0] * p3[1] - p3[0] * p4[1];
-
- // Line segments intersect: compute intersection point.
- denom = a1 * b2 - a2 * b1;
- if (fabs(denom) < M_EPSILON)
- return (COLINEAR);
-
- num = b1 * c2 - b2 * c1;
- res[0] = num / denom;
-
- num = a2 * c1 - a1 * c2;
- res[1] = num / denom;
-
- return (DO_INTERSECT);
- }
-
- intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1,
- const Vec2r& p2,
- const Vec2r& p3,
- const Vec2r& p4,
- real& t,
- real& u,
- real epsilon) {
- real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
- real r1, r2, r3, r4; // 'Sign' values
- real denom, num; // Intermediate values
-
- // Compute a1, b1, c1, where line joining points p1 and p2
- // is "a1 x + b1 y + c1 = 0".
- a1 = p2[1] - p1[1];
- b1 = p1[0] - p2[0];
- c1 = p2[0] * p1[1] - p1[0] * p2[1];
-
- // Compute r3 and r4.
- r3 = a1 * p3[0] + b1 * p3[1] + c1;
- r4 = a1 * p4[0] + b1 * p4[1] + c1;
-
- // Check signs of r3 and r4. If both point 3 and point 4 lie on
- // same side of line 1, the line segments do not intersect.
- if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
- return (DONT_INTERSECT);
-
- // Compute a2, b2, c2
- a2 = p4[1] - p3[1];
- b2 = p3[0] - p4[0];
- c2 = p4[0] * p3[1] - p3[0] * p4[1];
-
- // Compute r1 and r2
- r1 = a2 * p1[0] + b2 * p1[1] + c2;
- r2 = a2 * p2[0] + b2 * p2[1] + c2;
-
- // Check signs of r1 and r2. If both point 1 and point 2 lie
- // on same side of second line segment, the line segments do
- // not intersect.
- if ( r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
- return (DONT_INTERSECT);
-
- // Line segments intersect: compute intersection point.
- denom = a1 * b2 - a2 * b1;
- if (fabs(denom) < epsilon)
- return (COLINEAR);
-
- real d1, d2, e1;
-
- d1 = p1[1] - p3[1];
- d2 = p2[1] - p1[1];
- e1 = p1[0] - p3[0];
-
- num = -b2 * d1 - a2 * e1;
- t = num / denom;
-
- num = -b1 * d1 - a1 * e1;
- u = num / denom;
-
- return (DO_INTERSECT);
- }
-
- // AABB-triangle overlap test code
- // by Tomas Akenine-Möller
- // Function: int triBoxOverlap(real boxcenter[3],
- // real boxhalfsize[3],real triverts[3][3]);
- // History:
- // 2001-03-05: released the code in its first version
- // 2001-06-18: changed the order of the tests, faster
- //
- // Acknowledgement: Many thanks to Pierre Terdiman for
- // suggestions and discussions on how to optimize code.
- // Thanks to David Hunt for finding a ">="-bug!
+// This internal procedure is defined below.
+bool intersect2dSegPoly(Vec2r* seg, Vec2r* poly, unsigned n);
+
+bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B)
+{
+ Vec2r seg[2];
+ seg[0] = A;
+ seg[1] = B;
+
+ Vec2r poly[5];
+ poly[0][0] = min[0];
+ poly[0][1] = min[1];
+ poly[1][0] = max[0];
+ poly[1][1] = min[1];
+ poly[2][0] = max[0];
+ poly[2][1] = max[1];
+ poly[3][0] = min[0];
+ poly[3][1] = max[1];
+ poly[4][0] = min[0];
+ poly[4][1] = min[1];
+
+ return intersect2dSegPoly(seg, poly, 4);
+}
+
+bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B)
+{
+ if ((((max[0] > A[0]) && (A[0] > min[0])) && ((max[0] > B[0]) && (B[0] > min[0]))) &&
+ (((max[1] > A[1]) && (A[1] > min[1])) && ((max[1] > B[1]) && (B[1] > min[1]))))
+ return true;
+ return false;
+}
+
+intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4, Vec2r& res)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
+ // the line segments do not intersect.
+ if ( r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line segment,
+ // the line segments do not intersect.
+ if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4, Vec2r& res)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < M_EPSILON)
+ return (COLINEAR);
+
+ num = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
+
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4,
+ real& t, real& u, real epsilon)
+{
+ real a1, a2, b1, b2, c1, c2; // Coefficients of line eqns
+ real r1, r2, r3, r4; // 'Sign' values
+ real denom, num; // Intermediate values
+
+ // Compute a1, b1, c1, where line joining points p1 and p2 is "a1 x + b1 y + c1 = 0".
+ a1 = p2[1] - p1[1];
+ b1 = p1[0] - p2[0];
+ c1 = p2[0] * p1[1] - p1[0] * p2[1];
+
+ // Compute r3 and r4.
+ r3 = a1 * p3[0] + b1 * p3[1] + c1;
+ r4 = a1 * p4[0] + b1 * p4[1] + c1;
+
+ // Check signs of r3 and r4. If both point 3 and point 4 lie on same side of line 1,
+ // the line segments do not intersect.
+ if (r3 != 0 && r4 != 0 && r3 * r4 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Compute a2, b2, c2
+ a2 = p4[1] - p3[1];
+ b2 = p3[0] - p4[0];
+ c2 = p4[0] * p3[1] - p3[0] * p4[1];
+
+ // Compute r1 and r2
+ r1 = a2 * p1[0] + b2 * p1[1] + c2;
+ r2 = a2 * p2[0] + b2 * p2[1] + c2;
+
+ // Check signs of r1 and r2. If both point 1 and point 2 lie on same side of second line segment,
+ // the line segments do not intersect.
+ if (r1 != 0 && r2 != 0 && r1 * r2 > 0.0)
+ return (DONT_INTERSECT);
+
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < epsilon)
+ return (COLINEAR);
+
+ real d1, d2, e1;
+
+ d1 = p1[1] - p3[1];
+ d2 = p2[1] - p1[1];
+ e1 = p1[0] - p3[0];
+
+ num = -b2 * d1 - a2 * e1;
+ t = num / denom;
+
+ num = -b1 * d1 - a1 * e1;
+ u = num / denom;
+
+ return (DO_INTERSECT);
+}
+
+// AABB-triangle overlap test code by Tomas Akenine-Möller
+// Function: int triBoxOverlap(real boxcenter[3], real boxhalfsize[3],real triverts[3][3]);
+// History:
+// 2001-03-05: released the code in its first version
+// 2001-06-18: changed the order of the tests, faster
+//
+// Acknowledgement: Many thanks to Pierre Terdiman for suggestions and discussions on how to optimize code.
+// Thanks to David Hunt for finding a ">="-bug!
#define X 0
#define Y 1
#define Z 2
#define FINDMINMAX(x0, x1, x2, min, max) \
- min = max = x0; \
- if(x1<min) min=x1; \
- if(x1>max) max=x1; \
- if(x2<min) min=x2; \
- if(x2>max) max=x2;
-
- //======================== X-tests ========================//
-#define AXISTEST_X01(a, b, fa, fb) \
- p0 = a*v0[Y] - b*v0[Z]; \
- p2 = a*v2[Y] - b*v2[Z]; \
- if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
- rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return 0;
-
-#define AXISTEST_X2(a, b, fa, fb) \
- p0 = a*v0[Y] - b*v0[Z]; \
- p1 = a*v1[Y] - b*v1[Z]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return 0;
-
- //======================== Y-tests ========================//
-#define AXISTEST_Y02(a, b, fa, fb) \
- p0 = -a*v0[X] + b*v0[Z]; \
- p2 = -a*v2[X] + b*v2[Z]; \
- if(p0<p2) {min=p0; max=p2;} else {min=p2; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return 0;
-
-#define AXISTEST_Y1(a, b, fa, fb) \
- p0 = -a*v0[X] + b*v0[Z]; \
- p1 = -a*v1[X] + b*v1[Z]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
- if(min>rad || max<-rad) return 0;
-
- //======================== Z-tests ========================//
-#define AXISTEST_Z12(a, b, fa, fb) \
- p1 = a*v1[X] - b*v1[Y]; \
- p2 = a*v2[X] - b*v2[Y]; \
- if(p2<p1) {min=p2; max=p1;} else {min=p1; max=p2;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
- if(min>rad || max<-rad) return 0;
-
-#define AXISTEST_Z0(a, b, fa, fb) \
- p0 = a*v0[X] - b*v0[Y]; \
- p1 = a*v1[X] - b*v1[Y]; \
- if(p0<p1) {min=p0; max=p1;} else {min=p1; max=p0;} \
- rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
- if(min>rad || max<-rad) return 0;
-
- // This internal procedure is defined below.
- bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
-
- // Use separating axis theorem to test overlap between triangle and box
- // need to test for overlap in these directions:
- // 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle
- // we do not even need to test these)
- // 2) normal of the triangle
- // 3) crossproduct(edge from tri, {x,y,z}-directin)
- // this gives 3x3=9 more tests
- bool overlapTriangleBox(Vec3r& boxcenter,
- Vec3r& boxhalfsize,
- Vec3r triverts[3]) {
- Vec3r v0, v1, v2, normal, e0, e1, e2;
- real min, max, d, p0, p1, p2, rad, fex, fey, fez;
-
- // This is the fastest branch on Sun
- // move everything so that the boxcenter is in (0, 0, 0)
- v0 = triverts[0] - boxcenter;
- v1 = triverts[1] - boxcenter;
- v2 = triverts[2] - boxcenter;
-
- // compute triangle edges
- e0 = v1 - v0;
- e1 = v2 - v1;
- e2 = v0 - v2;
-
- // Bullet 3:
- // Do the 9 tests first (this was faster)
- fex = fabs(e0[X]);
- fey = fabs(e0[Y]);
- fez = fabs(e0[Z]);
- AXISTEST_X01(e0[Z], e0[Y], fez, fey);
- AXISTEST_Y02(e0[Z], e0[X], fez, fex);
- AXISTEST_Z12(e0[Y], e0[X], fey, fex);
-
- fex = fabs(e1[X]);
- fey = fabs(e1[Y]);
- fez = fabs(e1[Z]);
- AXISTEST_X01(e1[Z], e1[Y], fez, fey);
- AXISTEST_Y02(e1[Z], e1[X], fez, fex);
- AXISTEST_Z0(e1[Y], e1[X], fey, fex);
-
- fex = fabs(e2[X]);
- fey = fabs(e2[Y]);
- fez = fabs(e2[Z]);
- AXISTEST_X2(e2[Z], e2[Y], fez, fey);
- AXISTEST_Y1(e2[Z], e2[X], fez, fex);
- AXISTEST_Z12(e2[Y], e2[X], fey, fex);
-
- // Bullet 1:
- // first test overlap in the {x,y,z}-directions
- // find min, max of the triangle each direction, and test for overlap in
- // that direction -- this is equivalent to testing a minimal AABB around
- // the triangle against the AABB
-
- // test in X-direction
- FINDMINMAX(v0[X], v1[X], v2[X], min, max);
- if (min > boxhalfsize[X] || max < -boxhalfsize[X])
- return false;
-
- // test in Y-direction
- FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
- if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
- return false;
-
- // test in Z-direction
- FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
- if(min > boxhalfsize[Z] || max < -boxhalfsize[Z])
- return false;
-
- // Bullet 2:
- // test if the box intersects the plane of the triangle
- // compute plane equation of triangle: normal * x + d = 0
- normal = e0 ^ e1;
- d = -(normal * v0); // plane eq: normal.x + d = 0
- if (!overlapPlaneBox(normal, d, boxhalfsize))
- return false;
-
- return true; // box and triangle overlaps
- }
-
- // Fast, Minimum Storage Ray-Triangle Intersection
- //
- // Tomas Möller
- // Prosolvia Clarus AB
- // Sweden
- // tompa@clarus.se
- //
- // Ben Trumbore
- // Cornell University
- // Ithaca, New York
- // wbt@graphics.cornell.edu
-
- bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
- const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
- real& t, real& u, real& v, const real epsilon) {
- Vec3r edge1, edge2, tvec, pvec, qvec;
- real det, inv_det;
-
- // find vectors for two edges sharing v0
- edge1 = v1 - v0;
- edge2 = v2 - v0;
-
- // begin calculating determinant - also used to calculate U parameter
- pvec = dir ^ edge2;
-
- // if determinant is near zero, ray lies in plane of triangle
- det = edge1 * pvec;
-
- // calculate distance from v0 to ray origin
- tvec = orig - v0;
- inv_det = 1.0 / det;
-
- qvec = tvec ^ edge1;
-
- if (det > epsilon) {
- u = tvec * pvec;
- if (u < 0.0 || u > det)
- return false;
-
- // calculate V parameter and test bounds
- v = dir * qvec;
- if (v < 0.0 || u + v > det)
- return false;
- }
- else if(det < -epsilon) {
- // calculate U parameter and test bounds
- u = tvec * pvec;
- if (u > 0.0 || u < det)
- return false;
-
- // calculate V parameter and test bounds
- v = dir * qvec;
- if (v > 0.0 || u + v < det)
- return false;
- }
- else
- return false; // ray is parallell to the plane of the triangle
-
- u *= inv_det;
- v *= inv_det;
- t = (edge2 * qvec) * inv_det;
-
- return true;
- }
-
- // Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
- intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir,
- const Vec3r& norm, const real d,
- real& t,
- const real epsilon) {
- real denom = norm * dir;
-
- if(fabs(denom) <= epsilon) { // plane and ray are parallel
- if(fabs((norm * orig) + d) <= epsilon)
- return COINCIDENT; // plane and ray are coincident
- else
- return COLINEAR;
- }
-
- t = -(d + (norm * orig)) / denom;
-
- if (t < 0.0f)
- return DONT_INTERSECT;
-
- return DO_INTERSECT;
- }
-
- bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
- const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
- real t0, real t1,
- real& tmin, real& tmax, // I0=orig+tmin*dir is the first intersection, I1=orig+tmax*dir is the second intersection
- real epsilon){
-
- float tymin, tymax, tzmin, tzmax;
- Vec3r inv_direction(1.0/dir[0], 1.0/dir[1], 1.0/dir[2]);
- int sign[3];
- sign[0] = (inv_direction.x() < 0);
- sign[1] = (inv_direction.y() < 0);
- sign[2] = (inv_direction.z() < 0);
-
- Vec3r bounds[2];
- bounds[0] = boxMin;
- bounds[1] = boxMax;
-
- tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
- tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
- tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
- tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
- if ( (tmin > tymax) || (tymin > tmax) )
- return false;
- if (tymin > tmin)
- tmin = tymin;
- if (tymax < tmax)
- tmax = tymax;
- tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
- tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
- if ( (tmin > tzmax) || (tzmin > tmax) )
- return false;
- if (tzmin > tmin)
- tmin = tzmin;
- if (tzmax < tmax)
- tmax = tzmax;
- return ( (tmin < t1) && (tmax > t0) );
- }
-
- // Checks whether 3D points p lies inside or outside of the triangle ABC
- bool includePointTriangle(const Vec3r& P,
- const Vec3r& A,
- const Vec3r& B,
- const Vec3r& C) {
- Vec3r AB(B - A);
- Vec3r BC(C - B);
- Vec3r CA(A - C);
- Vec3r AP(P - A);
- Vec3r BP(P - B);
- Vec3r CP(P - C);
-
- Vec3r N(AB ^ BC); // triangle's normal
-
- N.normalize();
-
- Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
- J.normalize();
- K.normalize();
- L.normalize();
-
- if(J * N < 0)
- return false; // on the right of AB
-
- if(K * N < 0)
- return false; // on the right of BC
-
- if(L * N < 0)
- return false; // on the right of CA
-
- return true;
- }
-
- void transformVertex(const Vec3r& vert,
- const Matrix44r& matrix,
- Vec3r& res) {
- HVec3r hvert(vert), res_tmp;
- real scale;
- for (unsigned j = 0; j < 4; j++) {
- scale = hvert[j];
- for (unsigned i = 0; i < 4; i++)
- res_tmp[i] += matrix(i, j) * scale;
- }
-
- res[0] = res_tmp.x();
- res[1] = res_tmp.y();
- res[2] = res_tmp.z();
- }
-
- void transformVertices(const vector<Vec3r>& vertices,
- const Matrix44r& trans,
- vector<Vec3r>& res) {
- for (vector<Vec3r>::const_iterator v = vertices.begin();
- v != vertices.end();
- v++) {
- Vec3r *res_tmp = new Vec3r;
- transformVertex(*v, trans, *res_tmp);
- res.push_back(*res_tmp);
- }
- }
-
- Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
- Vec3r res;
- for (unsigned i = 0; i < 3; i++) {
- res[i] = 0;
- for (unsigned j = 0; j < 3; j++)
- res[i] += mat(i, j) * v[j];
- }
- res.normalize();
- return res;
- }
-
- // This internal procedure is defined below.
- void fromCoordAToCoordB(const Vec3r& p,
- Vec3r& q,
- const real transform[4][4]);
-
- void fromWorldToCamera(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4]) {
- fromCoordAToCoordB(p, q, model_view_matrix);
- }
-
- void fromCameraToRetina(const Vec3r& p,
- Vec3r& q,
- const real projection_matrix[4][4]) {
- fromCoordAToCoordB(p, q, projection_matrix);
- }
-
- void fromRetinaToImage(const Vec3r& p,
- Vec3r& q,
- const int viewport[4]) {
- // winX:
- q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
-
- // winY:
- q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
-
- // winZ:
- q[2] = (p[2] + 1.0) / 2.0;
- }
-
- void fromWorldToImage(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4],
- const real projection_matrix[4][4],
- const int viewport[4]) {
- Vec3r p1, p2;
- fromWorldToCamera(p, p1, model_view_matrix);
- fromCameraToRetina(p1, p2, projection_matrix);
- fromRetinaToImage(p2, q, viewport);
- q[2] = p1[2];
- }
-
- void fromWorldToImage(const Vec3r& p,
- Vec3r& q,
- const real transform[4][4],
- const int viewport[4]) {
- fromCoordAToCoordB(p, q, transform);
-
- // winX:
- q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
-
- //winY:
- q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
- }
-
- void fromImageToRetina(const Vec3r& p,
- Vec3r& q,
- const int viewport[4]) {
- q = p;
- q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1;
- q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1;
- }
-
- void fromRetinaToCamera(const Vec3r& p,
- Vec3r& q,
- real focal,
- const real projection_matrix[4][4]) {
-
- if( projection_matrix[3][3] == 0.0 ) // perspective
- {
- q[0] = (-p[0] * focal) / projection_matrix[0][0];
- q[1] = (-p[1] * focal) / projection_matrix[1][1];
- q[2] = focal;
+ { \
+ min = max = x0; \
+ if (x1 < min) \
+ min = x1; \
+ if (x1 > max) \
+ max = x1; \
+ if (x2 < min) \
+ min = x2; \
+ if (x2 > max) \
+ max = x2; \
+ } (void)0
+
+//======================== X-tests ========================//
+#define AXISTEST_X01(a, b, fa, fb) \
+ { \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p2 = a * v2[Y] - b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_X2(a, b, fa, fb) \
+ { \
+ p0 = a * v0[Y] - b * v0[Z]; \
+ p1 = a * v1[Y] - b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[Y] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+//======================== Y-tests ========================//
+#define AXISTEST_Y02(a, b, fa, fb) \
+ { \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p2 = -a * v2[X] + b * v2[Z]; \
+ if (p0 < p2) { \
+ min = p0; \
+ max = p2; \
+ } \
+ else { \
+ min = p2; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_Y1(a, b, fa, fb) \
+ { \
+ p0 = -a * v0[X] + b * v0[Z]; \
+ p1 = -a * v1[X] + b * v1[Z]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Z]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+//======================== Z-tests ========================//
+#define AXISTEST_Z12(a, b, fa, fb) \
+ { \
+ p1 = a * v1[X] - b * v1[Y]; \
+ p2 = a * v2[X] - b * v2[Y]; \
+ if (p2 < p1) { \
+ min = p2; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p2; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+#define AXISTEST_Z0(a, b, fa, fb) \
+ { \
+ p0 = a * v0[X] - b * v0[Y]; \
+ p1 = a * v1[X] - b * v1[Y]; \
+ if (p0 < p1) { \
+ min = p0; \
+ max = p1; \
+ } \
+ else { \
+ min = p1; \
+ max = p0; \
+ } \
+ rad = fa * boxhalfsize[X] + fb * boxhalfsize[Y]; \
+ if (min > rad || max < -rad) \
+ return 0; \
+ } (void)0
+
+// This internal procedure is defined below.
+bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox);
+
+// Use separating axis theorem to test overlap between triangle and box need to test for overlap in these directions:
+// 1) the {x,y,z}-directions (actually, since we use the AABB of the triangle we do not even need to test these)
+// 2) normal of the triangle
+// 3) crossproduct(edge from tri, {x,y,z}-directin) this gives 3x3=9 more tests
+bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3])
+{
+ Vec3r v0, v1, v2, normal, e0, e1, e2;
+ real min, max, d, p0, p1, p2, rad, fex, fey, fez;
+
+ // This is the fastest branch on Sun
+ // move everything so that the boxcenter is in (0, 0, 0)
+ v0 = triverts[0] - boxcenter;
+ v1 = triverts[1] - boxcenter;
+ v2 = triverts[2] - boxcenter;
+
+ // compute triangle edges
+ e0 = v1 - v0;
+ e1 = v2 - v1;
+ e2 = v0 - v2;
+
+ // Bullet 3:
+ // Do the 9 tests first (this was faster)
+ fex = fabs(e0[X]);
+ fey = fabs(e0[Y]);
+ fez = fabs(e0[Z]);
+ AXISTEST_X01(e0[Z], e0[Y], fez, fey);
+ AXISTEST_Y02(e0[Z], e0[X], fez, fex);
+ AXISTEST_Z12(e0[Y], e0[X], fey, fex);
+
+ fex = fabs(e1[X]);
+ fey = fabs(e1[Y]);
+ fez = fabs(e1[Z]);
+ AXISTEST_X01(e1[Z], e1[Y], fez, fey);
+ AXISTEST_Y02(e1[Z], e1[X], fez, fex);
+ AXISTEST_Z0(e1[Y], e1[X], fey, fex);
+
+ fex = fabs(e2[X]);
+ fey = fabs(e2[Y]);
+ fez = fabs(e2[Z]);
+ AXISTEST_X2(e2[Z], e2[Y], fez, fey);
+ AXISTEST_Y1(e2[Z], e2[X], fez, fex);
+ AXISTEST_Z12(e2[Y], e2[X], fey, fex);
+
+ // Bullet 1:
+ // first test overlap in the {x,y,z}-directions
+ // find min, max of the triangle each direction, and test for overlap in that direction -- this is equivalent
+ // to testing a minimal AABB around the triangle against the AABB
+
+ // test in X-direction
+ FINDMINMAX(v0[X], v1[X], v2[X], min, max);
+ if (min > boxhalfsize[X] || max < -boxhalfsize[X])
+ return false;
+
+ // test in Y-direction
+ FINDMINMAX(v0[Y], v1[Y], v2[Y], min, max);
+ if (min > boxhalfsize[Y] || max < -boxhalfsize[Y])
+ return false;
+
+ // test in Z-direction
+ FINDMINMAX(v0[Z], v1[Z], v2[Z], min, max);
+ if (min > boxhalfsize[Z] || max < -boxhalfsize[Z])
+ return false;
+
+ // Bullet 2:
+ // test if the box intersects the plane of the triangle
+ // compute plane equation of triangle: normal * x + d = 0
+ normal = e0 ^ e1;
+ d = -(normal * v0); // plane eq: normal.x + d = 0
+ if (!overlapPlaneBox(normal, d, boxhalfsize))
+ return false;
+
+ return true; // box and triangle overlaps
+}
+
+// Fast, Minimum Storage Ray-Triangle Intersection
+//
+// Tomas Möller
+// Prosolvia Clarus AB
+// Sweden
+// tompa@clarus.se
+//
+// Ben Trumbore
+// Cornell University
+// Ithaca, New York
+// wbt@graphics.cornell.edu
+bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, real& u, real& v, const real epsilon)
+{
+ Vec3r edge1, edge2, tvec, pvec, qvec;
+ real det, inv_det;
+
+ // find vectors for two edges sharing v0
+ edge1 = v1 - v0;
+ edge2 = v2 - v0;
+
+ // begin calculating determinant - also used to calculate U parameter
+ pvec = dir ^ edge2;
+
+ // if determinant is near zero, ray lies in plane of triangle
+ det = edge1 * pvec;
+
+ // calculate distance from v0 to ray origin
+ tvec = orig - v0;
+ inv_det = 1.0 / det;
+
+ qvec = tvec ^ edge1;
+
+ if (det > epsilon) {
+ u = tvec * pvec;
+ if (u < 0.0 || u > det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v < 0.0 || u + v > det)
+ return false;
+ }
+ else if (det < -epsilon) {
+ // calculate U parameter and test bounds
+ u = tvec * pvec;
+ if (u > 0.0 || u < det)
+ return false;
+
+ // calculate V parameter and test bounds
+ v = dir * qvec;
+ if (v > 0.0 || u + v < det)
+ return false;
}
- else // orthogonal
- {
+ else {
+ return false; // ray is parallell to the plane of the triangle
+ }
+
+ u *= inv_det;
+ v *= inv_det;
+ t = (edge2 * qvec) * inv_det;
+
+ return true;
+}
+
+// Intersection between plane and ray, adapted from Graphics Gems, Didier Badouel
+intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, const Vec3r& norm, const real d,
+ real& t, const real epsilon)
+{
+ real denom = norm * dir;
+
+ if (fabs(denom) <= epsilon) { // plane and ray are parallel
+ if (fabs((norm * orig) + d) <= epsilon)
+ return COINCIDENT; // plane and ray are coincident
+ else
+ return COLINEAR;
+ }
+
+ t = -(d + (norm * orig)) / denom;
+
+ if (t < 0.0f)
+ return DONT_INTERSECT;
+
+ return DO_INTERSECT;
+}
+
+bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ real t0, real t1,
+ real& tmin, // I0 = orig + tmin * dir is the first intersection
+ real& tmax, // I1 = orig + tmax * dir is the second intersection
+ real epsilon)
+{
+ float tymin, tymax, tzmin, tzmax;
+ Vec3r inv_direction(1.0 / dir[0], 1.0 / dir[1], 1.0 / dir[2]);
+ int sign[3];
+ sign[0] = (inv_direction.x() < 0);
+ sign[1] = (inv_direction.y() < 0);
+ sign[2] = (inv_direction.z() < 0);
+
+ Vec3r bounds[2];
+ bounds[0] = boxMin;
+ bounds[1] = boxMax;
+
+ tmin = (bounds[sign[0]].x() - orig.x()) * inv_direction.x();
+ tmax = (bounds[1-sign[0]].x() - orig.x()) * inv_direction.x();
+ tymin = (bounds[sign[1]].y() - orig.y()) * inv_direction.y();
+ tymax = (bounds[1-sign[1]].y() - orig.y()) * inv_direction.y();
+ if ((tmin > tymax) || (tymin > tmax))
+ return false;
+ if (tymin > tmin)
+ tmin = tymin;
+ if (tymax < tmax)
+ tmax = tymax;
+ tzmin = (bounds[sign[2]].z() - orig.z()) * inv_direction.z();
+ tzmax = (bounds[1-sign[2]].z() - orig.z()) * inv_direction.z();
+ if ((tmin > tzmax) || (tzmin > tmax))
+ return false;
+ if (tzmin > tmin)
+ tmin = tzmin;
+ if (tzmax < tmax)
+ tmax = tzmax;
+ return ((tmin < t1) && (tmax > t0));
+}
+
+// Checks whether 3D points p lies inside or outside of the triangle ABC
+bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C)
+{
+ Vec3r AB(B - A);
+ Vec3r BC(C - B);
+ Vec3r CA(A - C);
+ Vec3r AP(P - A);
+ Vec3r BP(P - B);
+ Vec3r CP(P - C);
+
+ Vec3r N(AB ^ BC); // triangle's normal
+
+ N.normalize();
+
+ Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
+ J.normalize();
+ K.normalize();
+ L.normalize();
+
+ if (J * N < 0)
+ return false; // on the right of AB
+
+ if (K * N < 0)
+ return false; // on the right of BC
+
+ if (L * N < 0)
+ return false; // on the right of CA
+
+ return true;
+}
+
+void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res)
+{
+ HVec3r hvert(vert), res_tmp;
+ real scale;
+ for (unsigned int j = 0; j < 4; j++) {
+ scale = hvert[j];
+ for (unsigned int i = 0; i < 4; i++)
+ res_tmp[i] += matrix(i, j) * scale;
+ }
+
+ res[0] = res_tmp.x();
+ res[1] = res_tmp.y();
+ res[2] = res_tmp.z();
+}
+
+void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res)
+{
+ for (vector<Vec3r>::const_iterator v = vertices.begin(); v != vertices.end(); v++) {
+ Vec3r *res_tmp = new Vec3r;
+ transformVertex(*v, trans, *res_tmp);
+ res.push_back(*res_tmp);
+ }
+}
+
+Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v) {
+ Vec3r res;
+ for (unsigned int i = 0; i < 3; i++) {
+ res[i] = 0;
+ for (unsigned int j = 0; j < 3; j++)
+ res[i] += mat(i, j) * v[j];
+ }
+ res.normalize();
+ return res;
+}
+
+// This internal procedure is defined below.
+void fromCoordAToCoordB(const Vec3r& p, Vec3r& q, const real transform[4][4]);
+
+void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4])
+{
+ fromCoordAToCoordB(p, q, model_view_matrix);
+}
+
+void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4])
+{
+ fromCoordAToCoordB(p, q, projection_matrix);
+}
+
+void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4])
+{
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
+
+ // winY:
+ q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
+
+ // winZ:
+ q[2] = (p[2] + 1.0) / 2.0;
+}
+
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4],
+ const real projection_matrix[4][4], const int viewport[4])
+{
+ Vec3r p1, p2;
+ fromWorldToCamera(p, p1, model_view_matrix);
+ fromCameraToRetina(p1, p2, projection_matrix);
+ fromRetinaToImage(p2, q, viewport);
+ q[2] = p1[2];
+}
+
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4])
+{
+ fromCoordAToCoordB(p, q, transform);
+
+ // winX:
+ q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
+
+ //winY:
+ q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
+}
+
+void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4])
+{
+ q = p;
+ q[0] = 2.0 * (q[0] - viewport[0]) / viewport[2] - 1.0;
+ q[1] = 2.0 * (q[1] - viewport[1]) / viewport[3] - 1.0;
+}
+
+void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real focal, const real projection_matrix[4][4])
+{
+ if (projection_matrix[3][3] == 0.0) { // perspective
+ q[0] = (-p[0] * focal) / projection_matrix[0][0];
+ q[1] = (-p[1] * focal) / projection_matrix[1][1];
+ q[2] = focal;
+ }
+ else { // orthogonal
q[0] = p[0] / projection_matrix[0][0];
- q[1] = p[1] / projection_matrix[1][1];
- q[2] = focal;
+ q[1] = p[1] / projection_matrix[1][1];
+ q[2] = focal;
}
- }
-
- void fromCameraToWorld(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4]) {
-
- real translation[3] = { model_view_matrix[0][3],
- model_view_matrix[1][3],
- model_view_matrix[2][3] };
- for (unsigned i = 0; i < 3; i++) {
- q[i] = 0.0;
- for (unsigned short j = 0; j < 3; j++)
- q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
- }
- }
-
-
- //
- // Internal code
- //
- /////////////////////////////////////////////////////////////////////////////
-
- // Copyright 2001, softSurfer (www.softsurfer.com)
- // This code may be freely used and modified for any purpose
- // providing that this copyright notice is included with it.
- // SoftSurfer makes no warranty for this code, and cannot be held
- // liable for any real or imagined damage resulting from its use.
- // Users of this code must verify correctness for their application.
-
-#define perp(u,v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
-
- inline bool intersect2dSegPoly(Vec2r* seg,
- Vec2r* poly,
- unsigned n) {
- if (seg[0] == seg[1])
- return false;
-
- real tE = 0; // the maximum entering segment parameter
- real tL = 1; // the minimum leaving segment parameter
- real t, N, D; // intersect parameter t = N / D
- Vec2r dseg; // the segment direction vector
- dseg = seg[1] - seg[0];
- Vec2r e; // edge vector
-
- for (unsigned i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
- e = poly[i+1] - poly[i];
- N = perp(e, seg[0] - poly[i]);
- D = -perp(e, dseg);
- if (fabs(D) < M_EPSILON) {
- if (N < 0)
- return false;
- else
- continue;
- }
-
- t = N / D;
- if (D < 0) { // segment seg is entering across this edge
- if (t > tE) { // new max tE
- tE = t;
- if (tE > tL) // seg enters after leaving polygon
- return false;
+}
+
+void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4])
+{
+ real translation[3] = {
+ model_view_matrix[0][3],
+ model_view_matrix[1][3],
+ model_view_matrix[2][3]
+ };
+ for (unsigned short i = 0; i < 3; i++) {
+ q[i] = 0.0;
+ for (unsigned short j = 0; j < 3; j++)
+ q[i] += model_view_matrix[j][i] * (p[j] - translation[j]);
}
- }
- else { // segment seg is leaving across this edge
- if (t < tL) { // new min tL
- tL = t;
- if (tL < tE) // seg leaves before entering polygon
- return false;
+}
+
+
+//
+// Internal code
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Copyright 2001, softSurfer (www.softsurfer.com)
+// This code may be freely used and modified for any purpose providing that this copyright notice is included with it.
+// SoftSurfer makes no warranty for this code, and cannot be held liable for any real or imagined damage resulting
+// from its use.
+// Users of this code must verify correctness for their application.
+
+#define PERP(u, v) ((u)[0] * (v)[1] - (u)[1] * (v)[0]) // 2D perp product
+
+inline bool intersect2dSegPoly(Vec2r* seg, Vec2r* poly, unsigned n)
+{
+ if (seg[0] == seg[1])
+ return false;
+
+ real tE = 0; // the maximum entering segment parameter
+ real tL = 1; // the minimum leaving segment parameter
+ real t, N, D; // intersect parameter t = N / D
+ Vec2r dseg = seg[1] - seg[0]; // the segment direction vector
+ Vec2r e; // edge vector
+
+ for (unsigned int i = 0; i < n; i++) { // process polygon edge poly[i]poly[i+1]
+ e = poly[i+1] - poly[i];
+ N = PERP(e, seg[0] - poly[i]);
+ D = -PERP(e, dseg);
+ if (fabs(D) < M_EPSILON) {
+ if (N < 0)
+ return false;
+ else
+ continue;
+ }
+
+ t = N / D;
+ if (D < 0) { // segment seg is entering across this edge
+ if (t > tE) { // new max tE
+ tE = t;
+ if (tE > tL) // seg enters after leaving polygon
+ return false;
+ }
+ }
+ else { // segment seg is leaving across this edge
+ if (t < tL) { // new min tL
+ tL = t;
+ if (tL < tE) // seg leaves before entering polygon
+ return false;
+ }
+ }
}
- }
- }
- // tE <= tL implies that there is a valid intersection subsegment
- return true;
- }
+ // tE <= tL implies that there is a valid intersection subsegment
+ return true;
+}
+
+inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox)
+{
+ Vec3r vmin, vmax;
+
+ for (unsigned int q = X; q <= Z; q++) {
+ if (normal[q] > 0.0f) {
+ vmin[q] = -maxbox[q];
+ vmax[q] = maxbox[q];
+ }
+ else {
+ vmin[q] = maxbox[q];
+ vmax[q] = -maxbox[q];
+ }
+ }
+ if ((normal * vmin) + d > 0.0f)
+ return false;
+ if ((normal * vmax) + d >= 0.0f)
+ return true;
+ return false;
+}
- inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox) {
- Vec3r vmin, vmax;
+inline void fromCoordAToCoordB(const Vec3r&p, Vec3r& q, const real transform[4][4])
+{
+ HVec3r hp(p);
+ HVec3r hq(0, 0, 0, 0);
- for(unsigned q = X; q <= Z; q++) {
- if(normal[q] > 0.0f) {
- vmin[q] = -maxbox[q];
- vmax[q] = maxbox[q];
+ for (unsigned int i = 0; i < 4; i++) {
+ for (unsigned int j = 0; j < 4; j++) {
+ hq[i] += transform[i][j] * hp[j];
+ }
}
- else {
- vmin[q] = maxbox[q];
- vmax[q] = -maxbox[q];
+
+ if (hq[3] == 0) {
+ q = p;
+ return;
}
- }
- if((normal * vmin) + d > 0.0f)
- return false;
- if((normal * vmax) + d >= 0.0f)
- return true;
- return false;
- }
-
- inline void fromCoordAToCoordB(const Vec3r&p,
- Vec3r& q,
- const real transform[4][4]) {
- HVec3r hp(p);
- HVec3r hq(0, 0, 0, 0);
-
- for (unsigned i = 0; i < 4; i++)
- for (unsigned j = 0; j < 4; j++)
- hq[i] += transform[i][j] * hp[j];
-
- if(hq[3] == 0) {
- q = p;
- return;
- }
-
- for (unsigned k = 0; k < 3; k++)
- q[k] = hq[k] / hq[3];
- }
+
+ for (unsigned int k = 0; k < 3; k++)
+ q[k] = hq[k] / hq[3];
+}
} // end of namespace GeomUtils
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
index 7fd6fe3cdb9..1b90f99c2ed 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.h
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -1,310 +1,277 @@
-//
-// Filename : GeomUtils.h
-// Author(s) : Stephane Grabli
-// Purpose : Various tools for geometry
-// Date of creation : 12/04/2002
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GEOMUTILS_H__
+#define __GEOMUTILS_H__
+
+/** \file blender/freestyle/intern/geometry/GeomUtils.h
+ * \ingroup freestyle
+ * \brief Various tools for geometry
+ * \author Stephane Grabli
+ * \date 12/04/2002
+ */
+
+#include <vector>
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+using namespace std;
+using namespace Geometry;
+
+namespace GeomUtils {
//
-// 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.
+// Templated procedures
//
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
-#ifndef GEOMUTILS_H
-# define GEOMUTILS_H
+/*! Computes the distance from a point P to a segment AB */
+template<class T>
+real distPointSegment( const T& P, const T& A , const T& B)
+{
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
-# include <vector>
-# include "../system/FreestyleConfig.h"
-# include "Geom.h"
+ real c1(AB * AP);
+ if (c1 <= 0)
+ return AP.norm();
-using namespace std;
-using namespace Geometry;
+ real c2(AB * AB);
+ if (c2 <= c1)
+ return BP.norm();
-namespace GeomUtils {
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
- //
- // Templated procedures
- //
- /////////////////////////////////////////////////////////////////////////////
-
- /*! Computes the distance from a point P to a segment AB */
- template<class T>
- real distPointSegment( const T& P, const T& A , const T& B) {
- T AB, AP, BP;
- AB = B - A;
- AP = P - A;
- BP = P - B;
-
- real c1(AB * AP);
- if (c1 <= 0)
- return AP.norm();
-
- real c2(AB * AB);
- if (c2 <= c1)
- return BP.norm();
-
- real b = c1 / c2;
- T Pb, PPb;
- Pb = A + b * AB;
- PPb = P - Pb;
-
- return PPb.norm();
- }
-
- //
- // Non-templated procedures
- //
- /////////////////////////////////////////////////////////////////////////////
-
- typedef enum {
- DONT_INTERSECT,
- DO_INTERSECT,
- COLINEAR,
- COINCIDENT
- } intersection_test;
-
- LIB_GEOMETRY_EXPORT
- intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
- const Vec2r& p3, const Vec2r& p4, // second segment
- Vec2r& res); // found intersection point
-
- LIB_GEOMETRY_EXPORT
- intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
- const Vec2r& p3, const Vec2r& p4, // second segment
- Vec2r& res); // found intersection point
-
- LIB_GEOMETRY_EXPORT
- intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
- const Vec2r& p3, const Vec2r& p4, // second segment
- real& t, // I = P1 + t * P1P2)
- real& u, // I = P3 + u * P3P4
- real epsilon = M_EPSILON);
-
- /*! check whether a 2D segment intersect a 2D region or not */
- LIB_GEOMETRY_EXPORT
- bool intersect2dSeg2dArea(const Vec2r& min,
- const Vec2r& max,
- const Vec2r& A,
- const Vec2r& B);
-
- /*! check whether a 2D segment is included in a 2D region or not */
- LIB_GEOMETRY_EXPORT
- bool include2dSeg2dArea(const Vec2r& min,
- const Vec2r& max,
- const Vec2r& A,
- const Vec2r& B);
-
- /*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
- LIB_GEOMETRY_EXPORT
- bool overlapTriangleBox(Vec3r& boxcenter,
- Vec3r& boxhalfsize,
- Vec3r triverts[3]);
-
- /*! Fast, Minimum Storage Ray-Triangle Intersection,
- * adapted from Tomas Möller and Ben Trumbore code.
- */
- LIB_GEOMETRY_EXPORT
- bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir,
- const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
- real& t, // I = orig + t * dir
- real& u, real& v, // I = (1-u-v)*v0+u*v1+v*v2
- const real epsilon = M_EPSILON); // the epsilon to use
-
- /*! Intersection between plane and ray
- * adapted from Graphics Gems, Didier Badouel
- */
- LIB_GEOMETRY_EXPORT
- intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
- const Vec3r& norm, const real d, // plane's normal and offset (plane = { P / P.N + d = 0 })
- real& t, // I = orig + t * dir
- const real epsilon = M_EPSILON); // the epsilon to use
-
- /*! Intersection Ray-Bounding box (axis aligned).
- * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm",
- * JGT 10:1 (2005), pp. 49-54.
- * Returns
- */
- LIB_GEOMETRY_EXPORT
- bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
- const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
- real t0, real t1, // the interval in which at least on of the intersections must happen
- real& tmin, real& tmax, // Imin=orig+tmin*dir is the first intersection, Imax=orig+tmax*dir is the second intersection
- real epsilon = M_EPSILON); // the epsilon to use
-
-
- /*! Checks whether 3D point P lies inside or outside of the triangle ABC */
- LIB_GEOMETRY_EXPORT
- bool includePointTriangle(const Vec3r& P,
- const Vec3r& A,
- const Vec3r& B,
- const Vec3r& C);
-
- LIB_GEOMETRY_EXPORT
- void transformVertex(const Vec3r& vert,
- const Matrix44r& matrix,
- Vec3r& res);
-
- LIB_GEOMETRY_EXPORT
- void transformVertices(const vector<Vec3r>& vertices,
- const Matrix44r& trans,
- vector<Vec3r>& res);
-
- LIB_GEOMETRY_EXPORT
- Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
-
- //
- // Coordinates systems changing procedures
- //
- /////////////////////////////////////////////////////////////////////////////
-
- /*! From world to image
- * p
- * point's coordinates expressed in world coordinates system
- * q
- * vector in which the result will be stored
- * model_view_matrix
- * The model view matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
- * projection_matrix
- * The projection matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
- * viewport
- * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
- */
- LIB_GEOMETRY_EXPORT
- void fromWorldToImage(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4],
- const real projection_matrix[4][4],
- const int viewport[4]);
-
- /*! From world to image
- * p
- * point's coordinates expressed in world coordinates system
- * q
- * vector in which the result will be stored
- * transform
- * The transformation matrix (gathering model view and projection),
- * expressed in line major order (OpenGL matrices are column major ordered)
- * viewport
- * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
- */
- LIB_GEOMETRY_EXPORT
- void fromWorldToImage(const Vec3r& p,
- Vec3r& q,
- const real transform[4][4],
- const int viewport[4]);
-
- /*! Projects from world coordinates to camera coordinates
- * Returns the point's coordinates expressed in the camera's
- * coordinates system.
- * p
- * point's coordinates expressed in world coordinates system
- * q
- * vector in which the result will be stored
- * model_view_matrix
- * The model view matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
- */
- LIB_GEOMETRY_EXPORT
- void fromWorldToCamera(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4]);
-
- /*! Projects from World Coordinates to retina coordinates
- * Returns the point's coordinates expressed in Retina system.
- * p
- * point's coordinates expressed in camera system
- * q
- * vector in which the result will be stored
- * projection_matrix
- * The projection matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
- */
- LIB_GEOMETRY_EXPORT
- void fromCameraToRetina(const Vec3r& p,
- Vec3r& q,
- const real projection_matrix[4][4]);
-
- /*! From retina to image.
- * Returns the coordinates expressed in Image coorinates system.
- * p
- * point's coordinates expressed in retina system
- * q
- * vector in which the result will be stored
- * viewport
- * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
- */
- LIB_GEOMETRY_EXPORT
- void fromRetinaToImage(const Vec3r& p,
- Vec3r& q,
- const int viewport[4]);
-
- /*! From image to retina
- * p
- * point's coordinates expressed in image system
- * q
- * vector in which the result will be stored
- * viewport
- * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
- */
- LIB_GEOMETRY_EXPORT
- void fromImageToRetina(const Vec3r& p,
- Vec3r& q,
- const int viewport[4]);
-
- /*! computes the coordinates of q in the camera coordinates system,
- * using the known z coordinates of the 3D point.
- * That means that this method does not inverse any matrices,
- * it only computes X and Y from x,y and Z)
- * p
- * point's coordinates expressed in retina system
- * q
- * vector in which the result will be stored
- * projection_matrix
- * The projection matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
-
- */
- LIB_GEOMETRY_EXPORT
- void fromRetinaToCamera(const Vec3r& p,
- Vec3r& q,
- real z,
- const real projection_matrix[4][4]);
-
- /*! Projects from camera coordinates to world coordinates
- * Returns the point's coordinates expressed in the world's
- * coordinates system.
- * p
- * point's coordinates expressed in the camera coordinates system
- * q
- * vector in which the result will be stored
- * model_view_matrix
- * The model view matrix expressed in line major order (OpenGL
- * matrices are column major ordered)
- */
- LIB_GEOMETRY_EXPORT
- void fromCameraToWorld(const Vec3r& p,
- Vec3r& q,
- const real model_view_matrix[4][4]);
+ return PPb.norm();
+}
+
+//
+// Non-templated procedures
+//
+/////////////////////////////////////////////////////////////////////////////
+typedef enum {
+ DONT_INTERSECT,
+ DO_INTERSECT,
+ COLINEAR,
+ COINCIDENT,
+} intersection_test;
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ Vec2r& res); // found intersection point
+
+LIB_GEOMETRY_EXPORT
+intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, // first segment
+ const Vec2r& p3, const Vec2r& p4, // second segment
+ real& t, // I = P1 + t * P1P2)
+ real& u, // I = P3 + u * P3P4
+ real epsilon = M_EPSILON);
+
+/*! check whether a 2D segment intersect a 2D region or not */
+LIB_GEOMETRY_EXPORT
+bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+
+/*! check whether a 2D segment is included in a 2D region or not */
+LIB_GEOMETRY_EXPORT
+bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+
+/*! Box-triangle overlap test, adapted from Tomas Akenine-Möller code */
+LIB_GEOMETRY_EXPORT
+bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3]);
+
+/*! Fast, Minimum Storage Ray-Triangle Intersection, adapted from Tomas Möller and Ben Trumbore code. */
+LIB_GEOMETRY_EXPORT
+bool intersectRayTriangle(const Vec3r& orig, const Vec3r& dir, const Vec3r& v0, const Vec3r& v1, const Vec3r& v2,
+ real& t, // I = orig + t * dir
+ real& u, real& v, // I = (1 - u - v) * v0 + u * v1 + v * v2
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Intersection between plane and ray adapted from Graphics Gems, Didier Badouel */
+LIB_GEOMETRY_EXPORT
+intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ // plane's normal and offset (plane = { P / P.N + d = 0 })
+ const Vec3r& norm, const real d,
+ real& t, // I = orig + t * dir
+ const real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Intersection Ray-Bounding box (axis aligned).
+ * Adapted from Williams et al, "An Efficient Robust Ray-Box Intersection Algorithm", JGT 10:1 (2005), pp. 49-54.
+ */
+LIB_GEOMETRY_EXPORT
+bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+ const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+ // the interval in which at least on of the intersections must happen
+ real t0, real t1,
+ real& tmin, // Imin = orig + tmin * dir is the first intersection
+ real& tmax, // Imax = orig + tmax * dir is the second intersection
+ real epsilon = M_EPSILON); // the epsilon to use
+
+/*! Checks whether 3D point P lies inside or outside of the triangle ABC */
+LIB_GEOMETRY_EXPORT
+bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C);
+
+LIB_GEOMETRY_EXPORT
+void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res);
+
+LIB_GEOMETRY_EXPORT
+void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res);
+
+LIB_GEOMETRY_EXPORT
+Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
+
+//
+// Coordinates systems changing procedures
+//
+/////////////////////////////////////////////////////////////////////////////
+
+/*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4], const real projection_matrix[4][4],
+ const int viewport[4]);
+
+/*! From world to image
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * transform
+ * The transformation matrix (gathering model view and projection),
+ * expressed in line major order (OpenGL matrices are column major ordered)
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4]);
+
+/*! Projects from world coordinates to camera coordinates
+ * Returns the point's coordinates expressed in the camera's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in world coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
+
+/*! Projects from World Coordinates to retina coordinates
+ * Returns the point's coordinates expressed in Retina system.
+ * p
+ * point's coordinates expressed in camera system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4]);
+
+/*! From retina to image.
+ * Returns the coordinates expressed in Image coorinates system.
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+LIB_GEOMETRY_EXPORT
+void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4]);
+
+/*! From image to retina
+ * p
+ * point's coordinates expressed in image system
+ * q
+ * vector in which the result will be stored
+ * viewport
+ * The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
+ */
+LIB_GEOMETRY_EXPORT
+void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4]);
+
+/*! computes the coordinates of q in the camera coordinates system,
+ * using the known z coordinates of the 3D point.
+ * That means that this method does not inverse any matrices,
+ * it only computes X and Y from x,y and Z)
+ * p
+ * point's coordinates expressed in retina system
+ * q
+ * vector in which the result will be stored
+ * projection_matrix
+ * The projection matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real z, const real projection_matrix[4][4]);
+
+/*! Projects from camera coordinates to world coordinates
+ * Returns the point's coordinates expressed in the world's
+ * coordinates system.
+ * p
+ * point's coordinates expressed in the camera coordinates system
+ * q
+ * vector in which the result will be stored
+ * model_view_matrix
+ * The model view matrix expressed in line major order (OpenGL
+ * matrices are column major ordered)
+ */
+LIB_GEOMETRY_EXPORT
+void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
} // end of namespace GeomUtils
-#endif // GEOMUTILS_H
+#endif // __GEOMUTILS_H__
diff --git a/source/blender/freestyle/intern/geometry/Grid.cpp b/source/blender/freestyle/intern/geometry/Grid.cpp
index bb0b3d80c30..11c4f11b281 100644
--- a/source/blender/freestyle/intern/geometry/Grid.cpp
+++ b/source/blender/freestyle/intern/geometry/Grid.cpp
@@ -1,392 +1,390 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Grid.cpp
+ * \ingroup freestyle
+ * \brief Base class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/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.
-//
-///////////////////////////////////////////////////////////////////////////////
-
-#include "Grid.h"
-#include "BBox.h"
#include <cassert>
#include <stdexcept>
+#include "BBox.h"
+#include "Grid.h"
+
// Grid Visitors
/////////////////
-void allOccludersGridVisitor::examineOccluder(Polygon3r *occ){
- occluders_.push_back(occ);
+void allOccludersGridVisitor::examineOccluder(Polygon3r *occ)
+{
+ occluders_.push_back(occ);
}
-static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max){
- if(((inter.x()>=box_min.x()) && (inter.x() <box_max.x()))
- && ((inter.y()>=box_min.y()) && (inter.y() <box_max.y()))
- && ((inter.z()>=box_min.z()) && (inter.z() <box_max.z()))
- ){
- return true;
- }
- return false;
+static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max)
+{
+ if (((inter.x() >= box_min.x()) && (inter.x() < box_max.x())) &&
+ ((inter.y() >= box_min.y()) && (inter.y() < box_max.y())) &&
+ ((inter.z() >= box_min.z()) && (inter.z() < box_max.z())))
+ {
+ return true;
+ }
+ return false;
}
-void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ){
-
- // check whether the edge and the polygon plane are coincident:
- //-------------------------------------------------------------
- //first let us compute the plane equation.
- Vec3r v1(((occ)->getVertices())[0]);
- Vec3d normal((occ)->getNormal());
- //soc unused - double d = -(v1 * normal);
-
- double tmp_u, tmp_v, tmp_t;
- if((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)){
- if (fabs(ray_dir_ * normal) > 0.0001){
- // Check whether the intersection is in the cell:
- if(inBox(ray_org_+tmp_t*ray_dir_/ray_dir_.norm(), current_cell_->getOrigin(), current_cell_->getOrigin()+cell_size_)){
-
- //Vec3d bboxdiag(_scene3d->bbox().getMax()-_scene3d->bbox().getMin());
- //if ((t>1.0E-06*(min(min(bboxdiag.x(),bboxdiag.y()),bboxdiag.z()))) && (t<raylength)){
- if(tmp_t < t_){
- occluder_ = occ;
- u_ = tmp_u;
- v_ = tmp_v;
- t_ = tmp_t;
- }
- }else{
- occ->userdata2 = 0;
- }
- }
- }
+
+void firstIntersectionGridVisitor::examineOccluder(Polygon3r *occ)
+{
+ // check whether the edge and the polygon plane are coincident:
+ //-------------------------------------------------------------
+ //first let us compute the plane equation.
+ Vec3r v1(((occ)->getVertices())[0]);
+ Vec3d normal((occ)->getNormal());
+ //soc unused - double d = -(v1 * normal);
+
+ double tmp_u, tmp_v, tmp_t;
+ if ((occ)->rayIntersect(ray_org_, ray_dir_, tmp_t, tmp_u, tmp_v)) {
+ if (fabs(ray_dir_ * normal) > 0.0001) {
+ // Check whether the intersection is in the cell:
+ if (inBox(ray_org_ + tmp_t * ray_dir_ / ray_dir_.norm(), current_cell_->getOrigin(),
+ current_cell_->getOrigin() + cell_size_))
+ {
+#if 0
+ Vec3d bboxdiag(_scene3d->bbox().getMax() - _scene3d->bbox().getMin());
+ if ((t > 1.0e-06 * (min(min(bboxdiag.x(), bboxdiag.y()), bboxdiag.z()))) && (t < raylength)) {
+#else
+ if (tmp_t < t_) {
+#endif
+ occluder_ = occ;
+ u_ = tmp_u;
+ v_ = tmp_v;
+ t_ = tmp_t;
+ }
+ }
+ else {
+ occ->userdata2 = 0;
+ }
+ }
+ }
}
-bool firstIntersectionGridVisitor::stop(){
- if(occluder_)
- return true;
- return false;
+bool firstIntersectionGridVisitor::stop()
+{
+ if (occluder_)
+ return true;
+ return false;
}
// Grid
/////////////////
+void Grid::clear()
+{
+ if (_occluders.size() != 0) {
+ for (OccludersSet::iterator it = _occluders.begin(); it != _occluders.end(); it++) {
+ delete (*it);
+ }
+ _occluders.clear();
+ }
-void Grid::clear() {
- if (_occluders.size() != 0) {
- for(OccludersSet::iterator it = _occluders.begin();
- it != _occluders.end();
- it++) {
- delete (*it);
- }
- _occluders.clear();
- }
-
- _size = Vec3r(0, 0, 0);
- _cell_size = Vec3r(0, 0, 0);
- _orig = Vec3r(0, 0, 0);
- _cells_nb = Vec3u(0, 0, 0);
- //_ray_occluders.clear();
-}
-
-void Grid::configure(const Vec3r& orig,
- const Vec3r& size,
- unsigned nb) {
-
- _orig = orig;
- Vec3r tmpSize=size;
- // Compute the volume of the desired grid
- real grid_vol = size[0] * size[1] * size[2];
-
- if(grid_vol == 0){
- double min=DBL_MAX;
- int index=0;
- int nzeros=0;
- for(int i=0;i<3;++i){
- if(size[i] == 0){
- ++nzeros;
- index=i;
- }
- if((size[i]!=0) && (min>size[i])){
- min=size[i];
- }
- }
- if(nzeros>1){
- throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
- }
- tmpSize[index]=min;
- _orig[index] = _orig[index]-min/2;
- }
- // Compute the desired volume of a single cell
- real cell_vol = grid_vol / nb;
- // The edge of such a cubic cell is cubic root of cellVolume
- real edge = pow(cell_vol, 1.0 / 3.0);
-
- // We compute the number of cells par edge
- // such as we cover at least the whole box.
- unsigned i;
- for (i = 0; i < 3; i++)
- _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
-
- _size = tmpSize;
-
- for(i = 0; i < 3; i++)
- _cell_size[i] = _size[i] / _cells_nb[i];
+ _size = Vec3r(0, 0, 0);
+ _cell_size = Vec3r(0, 0, 0);
+ _orig = Vec3r(0, 0, 0);
+ _cells_nb = Vec3u(0, 0, 0);
+ //_ray_occluders.clear();
}
-void Grid::insertOccluder(Polygon3r* occluder) {
- const vector<Vec3r> vertices = occluder->getVertices();
- if (vertices.size() == 0)
- return;
-
- // add this occluder to the grid's occluders list
- addOccluder(occluder);
-
- // find the bbox associated to this polygon
- Vec3r min, max;
- occluder->getBBox(min, max);
-
- // Retrieve the cell x, y, z cordinates associated with these min and max
- Vec3u imax, imin;
- getCellCoordinates(max, imax);
- getCellCoordinates(min, imin);
-
- // We are now going to fill in the cells overlapping with the
- // polygon bbox.
- // If the polygon is a triangle (most of cases), we also
- // check for each of these cells if it is overlapping with
- // the triangle in order to only fill in the ones really overlapping
- // the triangle.
-
- unsigned i, x, y, z;
- vector<Vec3r>::const_iterator it;
- Vec3u coord;
-
- if (vertices.size() == 3) { // Triangle case
- Vec3r triverts[3];
- i = 0;
- for(it = vertices.begin();
- it != vertices.end();
- it++) {
- triverts[i] = Vec3r(*it);
- i++;
- }
-
- Vec3r boxmin, boxmax;
-
- for (z = imin[2]; z <= imax[2]; z++)
- for (y = imin[1]; y <= imax[1]; y++)
- for (x = imin[0]; x <= imax[0]; x++) {
- coord[0] = x;
- coord[1] = y;
- coord[2] = z;
- // We retrieve the box coordinates of the current cell
- getCellBox(coord, boxmin, boxmax);
- // We check whether the triangle and the box ovewrlap:
- Vec3r boxcenter((boxmin + boxmax) / 2.0);
- Vec3r boxhalfsize(_cell_size / 2.0);
- if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
- // We must then create the Cell and add it to the cells list
- // if it does not exist yet.
- // We must then add the occluder to the occluders list of this cell.
- Cell* cell = getCell(coord);
- if (!cell) {
- cell = new Cell(boxmin);
- fillCell(coord, *cell);
- }
- cell->addOccluder(occluder);
- }
+void Grid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ _orig = orig;
+ Vec3r tmpSize = size;
+ // Compute the volume of the desired grid
+ real grid_vol = size[0] * size[1] * size[2];
+
+ if (grid_vol == 0) {
+ double min = DBL_MAX;
+ int index = 0;
+ int nzeros = 0;
+ for (int i = 0; i < 3; ++i) {
+ if (size[i] == 0) {
+ ++nzeros;
+ index = i;
+ }
+ if ((size[i] != 0) && (min > size[i])) {
+ min = size[i];
+ }
+ }
+ if (nzeros > 1) {
+ throw std::runtime_error("Warning: the 3D grid has more than one null dimension");
+ }
+ tmpSize[index] = min;
+ _orig[index] = _orig[index] - min / 2;
}
- }
- else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
- for (z = imin[2]; z <= imax[2]; z++)
- for (y = imin[1]; y <= imax[1]; y++)
- for (x = imin[0]; x <= imax[0]; x++) {
- coord[0] = x;
- coord[1] = y;
- coord[2] = z;
- Cell* cell = getCell(coord);
- if (!cell) {
- Vec3r orig;
- getCellOrigin(coord, orig);
- cell = new Cell(orig);
- fillCell(coord, *cell);
- }
- cell->addOccluder(occluder);
+ // Compute the desired volume of a single cell
+ real cell_vol = grid_vol / nb;
+ // The edge of such a cubic cell is cubic root of cellVolume
+ real edge = pow(cell_vol, 1.0 / 3.0);
+
+ // We compute the number of cells par edge such as we cover at least the whole box.
+ unsigned i;
+ for (i = 0; i < 3; i++)
+ _cells_nb[i] = (unsigned)floor(tmpSize[i] / edge) + 1;
+
+ _size = tmpSize;
+
+ for (i = 0; i < 3; i++)
+ _cell_size[i] = _size[i] / _cells_nb[i];
+}
+
+void Grid::insertOccluder(Polygon3r* occluder)
+{
+ const vector<Vec3r> vertices = occluder->getVertices();
+ if (vertices.size() == 0)
+ return;
+
+ // add this occluder to the grid's occluders list
+ addOccluder(occluder);
+
+ // find the bbox associated to this polygon
+ Vec3r min, max;
+ occluder->getBBox(min, max);
+
+ // Retrieve the cell x, y, z cordinates associated with these min and max
+ Vec3u imax, imin;
+ getCellCoordinates(max, imax);
+ getCellCoordinates(min, imin);
+
+ // We are now going to fill in the cells overlapping with the polygon bbox.
+ // If the polygon is a triangle (most of cases), we also check for each of these cells if it is overlapping with
+ // the triangle in order to only fill in the ones really overlapping the triangle.
+
+ unsigned i, x, y, z;
+ vector<Vec3r>::const_iterator it;
+ Vec3u coord;
+
+ if (vertices.size() == 3) { // Triangle case
+ Vec3r triverts[3];
+ i = 0;
+ for (it = vertices.begin(); it != vertices.end(); it++) {
+ triverts[i] = Vec3r(*it);
+ i++;
+ }
+
+ Vec3r boxmin, boxmax;
+
+ for (z = imin[2]; z <= imax[2]; z++) {
+ for (y = imin[1]; y <= imax[1]; y++) {
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ // We retrieve the box coordinates of the current cell
+ getCellBox(coord, boxmin, boxmax);
+ // We check whether the triangle and the box ovewrlap:
+ Vec3r boxcenter((boxmin + boxmax) / 2.0);
+ Vec3r boxhalfsize(_cell_size / 2.0);
+ if (GeomUtils::overlapTriangleBox(boxcenter, boxhalfsize, triverts)) {
+ // We must then create the Cell and add it to the cells list if it does not exist yet.
+ // We must then add the occluder to the occluders list of this cell.
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ cell = new Cell(boxmin);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
+ }
+ }
+ else { // The polygon is not a triangle, we add all the cells overlapping the polygon bbox.
+ for (z = imin[2]; z <= imax[2]; z++) {
+ for (y = imin[1]; y <= imax[1]; y++) {
+ for (x = imin[0]; x <= imax[0]; x++) {
+ coord[0] = x;
+ coord[1] = y;
+ coord[2] = z;
+ Cell* cell = getCell(coord);
+ if (!cell) {
+ Vec3r orig;
+ getCellOrigin(coord, orig);
+ cell = new Cell(orig);
+ fillCell(coord, *cell);
+ }
+ cell->addOccluder(occluder);
+ }
+ }
+ }
}
- }
}
-bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell) {
- next_cell = current_cell;
- real t_min, t;
- unsigned i;
-
- t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
- unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
-
-
- // using a parametric equation of
- // a line : B = A + t u, we find
- // the tx, ty and tz respectively coresponding
- // to the intersections with the plans:
- // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
- for (i = 0; i < 3; i++) {
- if (_ray_dir[i] == 0)
- continue;
- if (_ray_dir[i] > 0)
- t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
- else
- t = -_pt[i] / _ray_dir[i];
- if (t < t_min) {
- t_min = t;
- coord = i;
- }
- }
-
- // We use the parametric line equation and
- // the found t (tamx) to compute the
- // B coordinates:
- Vec3r pt_tmp(_pt);
- _pt = pt_tmp + t_min * _ray_dir;
-
- // We express B coordinates in the next cell
- // coordinates system. We just have to
- // set the coordinate coord of B to 0
- // of _CellSize[coord] depending on the sign
- // of _u[coord]
- if (_ray_dir[coord] > 0) {
- next_cell[coord]++;
- _pt[coord] -= _cell_size[coord];
- // if we are out of the grid, we must stop
- if (next_cell[coord] >= _cells_nb[coord])
- return false;
- }
- else {
- int tmp = next_cell[coord] - 1;
- _pt[coord] = _cell_size[coord];
- if (tmp < 0)
- return false;
- next_cell[coord]--;
- }
-
- _t += t_min;
- if (_t >= _t_end)
- return false;
-
- return true;
+bool Grid::nextRayCell(Vec3u& current_cell, Vec3u& next_cell)
+{
+ next_cell = current_cell;
+ real t_min, t;
+ unsigned i;
+
+ t_min = FLT_MAX; // init tmin with handle of the case where one or 2 _u[i] = 0.
+ unsigned coord = 0; // predominant coord(0=x, 1=y, 2=z)
+
+
+ // using a parametric equation of a line : B = A + t u, we find the tx, ty and tz respectively coresponding
+ // to the intersections with the plans:
+ // x = _cell_size[0], y = _cell_size[1], z = _cell_size[2]
+ for (i = 0; i < 3; i++) {
+ if (_ray_dir[i] == 0)
+ continue;
+ if (_ray_dir[i] > 0)
+ t = (_cell_size[i] - _pt[i]) / _ray_dir[i];
+ else
+ t = -_pt[i] / _ray_dir[i];
+ if (t < t_min) {
+ t_min = t;
+ coord = i;
+ }
+ }
+
+ // We use the parametric line equation and the found t (tamx) to compute the B coordinates:
+ Vec3r pt_tmp(_pt);
+ _pt = pt_tmp + t_min * _ray_dir;
+
+ // We express B coordinates in the next cell coordinates system. We just have to
+ // set the coordinate coord of B to 0 of _CellSize[coord] depending on the sign of _u[coord]
+ if (_ray_dir[coord] > 0) {
+ next_cell[coord]++;
+ _pt[coord] -= _cell_size[coord];
+ // if we are out of the grid, we must stop
+ if (next_cell[coord] >= _cells_nb[coord])
+ return false;
+ }
+ else {
+ int tmp = next_cell[coord] - 1;
+ _pt[coord] = _cell_size[coord];
+ if (tmp < 0)
+ return false;
+ next_cell[coord]--;
+ }
+
+ _t += t_min;
+ if (_t >= _t_end)
+ return false;
+
+ return true;
}
-void Grid::castRay(const Vec3r& orig,
- const Vec3r& end,
- OccludersSet& occluders,
- unsigned timestamp) {
- initRay(orig, end, timestamp);
- allOccludersGridVisitor visitor(occluders);
- castRayInternal(visitor);
+void Grid::castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp)
+{
+ initRay(orig, end, timestamp);
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
}
-void Grid::castInfiniteRay(const Vec3r& orig,
- const Vec3r& dir,
- OccludersSet& occluders,
- unsigned timestamp) {
- Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
- bool inter = initInfiniteRay(orig, dir, timestamp);
- if(!inter)
- return;
- allOccludersGridVisitor visitor(occluders);
- castRayInternal(visitor);
+void Grid::castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp)
+{
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if (!inter)
+ return;
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
}
-
-Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig,
- const Vec3r& dir,
- double& t,
- double& u,
- double& v,
- unsigned timestamp){
- Polygon3r *occluder = 0;
- Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
- bool inter = initInfiniteRay(orig, dir, timestamp);
- if(!inter){
- return 0;
- }
- firstIntersectionGridVisitor visitor(orig,dir,_cell_size);
- castRayInternal(visitor);
+
+Polygon3r* Grid::castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
+ double& u, double& v, unsigned timestamp)
+{
+ Polygon3r *occluder = 0;
+ Vec3r end = Vec3r(orig + FLT_MAX * dir / dir.norm());
+ bool inter = initInfiniteRay(orig, dir, timestamp);
+ if (!inter) {
+ return 0;
+ }
+ firstIntersectionGridVisitor visitor(orig, dir, _cell_size);
+ castRayInternal(visitor);
// ARB: This doesn't work, because occluders are unordered within any cell
- // visitor.occluder() will be an occluder, but we have no guarantee
- // it will be the *first* occluder.
+ // visitor.occluder() will be an occluder, but we have no guarantee it will be the *first* occluder.
// I assume that is the reason this code is not actually used for FindOccludee.
- occluder = visitor.occluder();
- t = visitor.t_;
- u = visitor.u_;
- v = visitor.v_;
- return occluder;
+ occluder = visitor.occluder();
+ t = visitor.t_;
+ u = visitor.u_;
+ v = visitor.v_;
+ return occluder;
}
-void Grid::initRay (const Vec3r &orig,
- const Vec3r& end,
- unsigned timestamp) {
- _ray_dir = end - orig;
- _t_end = _ray_dir.norm();
- _t = 0;
- _ray_dir.normalize();
- _timestamp = timestamp;
-
- for(unsigned i = 0; i < 3; i++) {
- _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
- //soc unused - unsigned u = _current_cell[i];
- _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
- }
- //_ray_occluders.clear();
-
+void Grid::initRay (const Vec3r &orig, const Vec3r& end, unsigned timestamp)
+{
+ _ray_dir = end - orig;
+ _t_end = _ray_dir.norm();
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ for (unsigned i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ //_ray_occluders.clear();
}
-bool Grid::initInfiniteRay (const Vec3r &orig,
- const Vec3r& dir,
- unsigned timestamp) {
- _ray_dir = dir;
- _t_end = FLT_MAX;
- _t = 0;
- _ray_dir.normalize();
- _timestamp = timestamp;
-
- // check whether the origin is in or out the box:
- Vec3r boxMin(_orig);
- Vec3r boxMax(_orig+_size);
- BBox<Vec3r> box(boxMin, boxMax);
- if(box.inside(orig)){
- for(unsigned i = 0; i < 3; i++) {
- _current_cell[i] = (unsigned)floor((orig[i] - _orig[i]) / _cell_size[i]);
- //soc unused - unsigned u = _current_cell[i];
- _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
- }
- }else{
- // is the ray intersecting the box?
- real tmin(-1.0), tmax(-1.0);
- if(GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)){
- assert(tmin != -1.0);
- Vec3r newOrig = orig + tmin*_ray_dir;
- for(unsigned i = 0; i < 3; i++) {
- _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
- if(_current_cell[i] == _cells_nb[i])
- _current_cell[i] = _cells_nb[i] - 1;
- //soc unused - unsigned u = _current_cell[i];
- _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
- }
-
- }else{
- return false;
- }
- }
- //_ray_occluders.clear();
-
- return true;
+bool Grid::initInfiniteRay (const Vec3r &orig, const Vec3r& dir, unsigned timestamp) {
+ _ray_dir = dir;
+ _t_end = FLT_MAX;
+ _t = 0;
+ _ray_dir.normalize();
+ _timestamp = timestamp;
+
+ // check whether the origin is in or out the box:
+ Vec3r boxMin(_orig);
+ Vec3r boxMax(_orig + _size);
+ BBox<Vec3r> box(boxMin, boxMax);
+ if (box.inside(orig)) {
+ for (unsigned int i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned int)floor((orig[i] - _orig[i]) / _cell_size[i]);
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = orig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }
+ else {
+ // is the ray intersecting the box?
+ real tmin(-1.0), tmax(-1.0);
+ if (GeomUtils::intersectRayBBox(orig, _ray_dir, boxMin, boxMax, 0, _t_end, tmin, tmax)) {
+ assert(tmin != -1.0);
+ Vec3r newOrig = orig + tmin * _ray_dir;
+ for (unsigned int i = 0; i < 3; i++) {
+ _current_cell[i] = (unsigned)floor((newOrig[i] - _orig[i]) / _cell_size[i]);
+ if (_current_cell[i] == _cells_nb[i])
+ _current_cell[i] = _cells_nb[i] - 1;
+ //soc unused - unsigned u = _current_cell[i];
+ _pt[i] = newOrig[i] - _orig[i] - _current_cell[i] * _cell_size[i];
+ }
+ }
+ else {
+ return false;
+ }
+ }
+ //_ray_occluders.clear();
+ return true;
}
-
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
index a490646ff51..40bd0911c9c 100644
--- a/source/blender/freestyle/intern/geometry/Grid.h
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -1,49 +1,54 @@
-//
-// Filename : Grid.h
-// Author(s) : Stephane Grabli
-// Purpose : Base class to define a cell grid surrounding
-// the bounding box of the scene
-// Date of creation : 30/07/2002
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+#ifndef __GRID_H__
+#define __GRID_H__
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/Grid.h
+ * \ingroup freestyle
+ * \brief Base class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <cstring> // for memset
+#include <float.h>
+#include <vector>
-#ifndef GRID_H
-# define GRID_H
+#include "Geom.h"
+#include "GeomUtils.h"
+#include "Polygon.h"
-# include <cstring> // for memset
-# include <float.h>
-# include <vector>
-# include "../system/FreestyleConfig.h"
-# include "GeomUtils.h"
-# include "Geom.h"
-# include "Polygon.h"
+#include "../system/FreestyleConfig.h"
using namespace std;
using namespace Geometry;
-typedef vector<Polygon3r*> OccludersSet;
-
+typedef vector<Polygon3r*> OccludersSet;
//
// Class to define cells used by the regular grid
@@ -52,84 +57,102 @@ typedef vector<Polygon3r*> OccludersSet;
class LIB_GEOMETRY_EXPORT Cell
{
- public:
-
- Cell(Vec3r& orig) {
- _orig = orig;
- }
-
- virtual ~Cell() {}
-
- inline void addOccluder(Polygon3r* o) {
- if (o)
- _occluders.push_back(o);
- }
-
- inline const Vec3r& getOrigin() {
- return _orig;
- }
-
- inline OccludersSet& getOccluders() {
- return _occluders;
- }
-
- private:
-
- Vec3r _orig;
- OccludersSet _occluders;
+public:
+ Cell(Vec3r& orig) {
+ _orig = orig;
+ }
+
+ virtual ~Cell() {}
+
+ inline void addOccluder(Polygon3r* o) {
+ if (o)
+ _occluders.push_back(o);
+ }
+
+ inline const Vec3r& getOrigin() {
+ return _orig;
+ }
+
+ inline OccludersSet& getOccluders() {
+ return _occluders;
+ }
+
+private:
+ Vec3r _orig;
+ OccludersSet _occluders;
};
-class GridVisitor{
+class GridVisitor
+{
public:
virtual ~GridVisitor() {}; //soc
- virtual void discoverCell(Cell *cell) {}
- virtual void examineOccluder(Polygon3r *occ) {}
- virtual void finishCell(Cell *cell) {}
- virtual bool stop() {return false;}
+
+ virtual void discoverCell(Cell *cell) {}
+
+ virtual void examineOccluder(Polygon3r *occ) {}
+
+ virtual void finishCell(Cell *cell) {}
+
+ virtual bool stop() {
+ return false;
+ }
};
-/*! Gathers all the occluders belonging to the cells
- * traversed by the ray */
-class allOccludersGridVisitor : public GridVisitor{
+/*! Gathers all the occluders belonging to the cells traversed by the ray */
+class allOccludersGridVisitor : public GridVisitor
+{
public:
- allOccludersGridVisitor(OccludersSet& occluders)
- :GridVisitor(), occluders_(occluders){}
- virtual void examineOccluder(Polygon3r *occ);
+ allOccludersGridVisitor(OccludersSet& occluders) : GridVisitor(), occluders_(occluders) {}
+
+ virtual void examineOccluder(Polygon3r *occ);
+
+ OccludersSet& occluders() {
+ return occluders_;
+ }
- OccludersSet& occluders() {return occluders_;}
- void clear() {occluders_.clear();}
+ void clear() {
+ occluders_.clear();
+ }
private:
- OccludersSet& occluders_;
+ OccludersSet& occluders_;
};
-/*! Finds the first intersection and breaks. The occluder and
- * the intersection information are stored and accessible.
+/*! Finds the first intersection and breaks.
+ * The occluder and the intersection information are stored and accessible.
*/
-class firstIntersectionGridVisitor : public GridVisitor {
-
+class firstIntersectionGridVisitor : public GridVisitor
+{
//soc - changed order to remove warnings
public:
- double u_, v_, t_;
+ double u_, v_, t_;
+
private:
- Polygon3r *occluder_;
+ Polygon3r *occluder_;
Vec3r ray_org_, ray_dir_, cell_size_;
- Cell * current_cell_;
+ Cell *current_cell_;
public:
- firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
- GridVisitor(), u_(0),v_(0),t_(DBL_MAX),
- occluder_(0),
- ray_org_(ray_org), ray_dir_(ray_dir), cell_size_(cell_size),
- current_cell_(0) {}
- virtual ~firstIntersectionGridVisitor() {}
-
- virtual void discoverCell(Cell *cell) {current_cell_=cell;}
- virtual void examineOccluder(Polygon3r *occ);
- virtual bool stop();
-
- Polygon3r * occluder() {return occluder_;}
+ firstIntersectionGridVisitor(const Vec3r& ray_org, const Vec3r& ray_dir, const Vec3r& cell_size) :
+ GridVisitor(), u_(0),v_(0),t_(DBL_MAX), occluder_(0), ray_org_(ray_org), ray_dir_(ray_dir),
+ cell_size_(cell_size), current_cell_(0)
+ {
+ }
+
+ virtual ~firstIntersectionGridVisitor() {}
+
+ virtual void discoverCell(Cell *cell) {
+ current_cell_ = cell;
+ }
+
+ virtual void examineOccluder(Polygon3r *occ);
+
+ virtual bool stop();
+
+ Polygon3r *occluder() {
+ return occluder_;
+ }
};
//
@@ -140,236 +163,197 @@ public:
class LIB_GEOMETRY_EXPORT Grid
{
public:
-
- /*! Builds a Grid
- * Must be followed by a call to configure()
- */
- Grid() {}
-
- virtual ~Grid() {
- clear();
- }
-
- /*! clears the grid
- * Deletes all the cells, clears the hashtable,
- * resets size, size of cell, number of cells.
- */
- virtual void clear();
-
- /*! Sets the different parameters of the grid
- * orig
- * The grid origin
- * size
- * The grid's dimensions
- * nb
- * The number of cells of the grid
- */
- virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
-
- /*! returns a vector of integer containing the
- * coordinates of the cell containing the point
- * passed as argument
- * p
- * The point for which we're looking the cell
- */
- inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
- int tmp;
- for (int i = 0; i < 3; i++) {
- tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
- if (tmp < 0)
- res[i] = 0;
- else if ((unsigned)tmp >= _cells_nb[i])
- res[i] = _cells_nb[i] - 1;
- else
- res[i] = tmp;
- }
- }
-
- /*! Fills the case corresponding to coord with the cell */
- virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
-
- /*! returns the cell whose coordinates
- * are pased as argument
- */
- virtual Cell* getCell(const Vec3u& coord) = 0;
-
- /*! returns the cell containing the point
- * passed as argument. If the cell is empty
- * (contains no occluder), NULL is returned
- * p
- * The point for which we're looking the cell
- */
- inline Cell* getCell(const Vec3r& p) {
- Vec3u coord;
- getCellCoordinates(p, coord);
- return getCell(coord);
- }
-
- /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k)
- * is passed as argument
- * cell_coord
- * i,j,k integer coordinates for the cell
- * orig
- * x,y,x vector to be filled in with the cell origin's coordinates
- */
- inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
- for (unsigned i = 0; i < 3; i++)
- orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
- }
-
- /*! Retrieves the box corresponding to the cell whose coordinates
- * are passed as argument.
- * cell_coord
- * i,j,k integer coordinates for the cell
- * min_out
- * The min x,y,x vector of the box. Filled in by the method.
- * max_out
- * The max x,y,z coordinates of the box. Filled in by the method.
- */
- inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
- getCellOrigin(cell_coord, min_out);
- max_out = min_out + _cell_size;
- }
-
- /*! inserts a convex polygon occluder
- * This method is quite coarse insofar as it
- * adds all cells intersecting the polygon bounding box
- * convex_poly
- * The list of 3D points constituing a convex polygon
- */
- void insertOccluder(Polygon3r * convex_poly);
-
- /*! Adds an occluder to the list of occluders */
- void addOccluder(Polygon3r* occluder) {
- _occluders.push_back(occluder);
- }
-
- /*! Casts a ray between a starting point and an ending point
- * Returns the list of occluders contained
- * in the cells intersected by this ray
- * Starts with a call to InitRay.
- */
- void castRay(const Vec3r& orig,
- const Vec3r& end,
- OccludersSet& occluders,
- unsigned timestamp);
- // Prepares to cast ray without generating OccludersSet
- void initAcceleratedRay(const Vec3r& orig,
- const Vec3r& end,
- unsigned timestamp);
-
- /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
- * Returns the list of occluders contained
- * in the cells intersected by this ray
- * Starts with a call to InitRay.
- */
- void castInfiniteRay(const Vec3r& orig,
- const Vec3r& dir,
- OccludersSet& occluders,
- unsigned timestamp);
- // Prepares to cast ray without generating OccludersSet.
- bool initAcceleratedInfiniteRay(const Vec3r& orig,
- const Vec3r& dir,
- unsigned timestamp);
-
- /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
- * Returns the first intersection (occluder,t,u,v) or null.
- * Starts with a call to InitRay.
- */
- Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig,
- const Vec3r& dir,
- double& t,
- double& u,
- double& v,
- unsigned timestamp);
-
-
- /*! Init all structures and values for computing
- * the cells intersected by this new ray
- */
- void initRay (const Vec3r &orig,
- const Vec3r& end,
- unsigned timestamp);
-
- /*! Init all structures and values for computing
- * the cells intersected by this infinite ray.
- * Returns false if the ray doesn't intersect the
- * grid.
- */
- bool initInfiniteRay (const Vec3r &orig,
- const Vec3r& dir,
- unsigned timestamp);
-
-
- /*! Accessors */
- inline const Vec3r& getOrigin() const {
- return _orig;
- }
- inline Vec3r gridSize() const {
- return _size;
- }
- inline Vec3r getCellSize() const {
- return _cell_size;
- }
-//ARB profiling only:
- inline OccludersSet* getOccluders() {
- return &_occluders;
- }
-
- void displayDebug() {
- cerr << "Cells nb : " << _cells_nb << endl;
- cerr << "Cell size : " << _cell_size << endl;
- cerr << "Origin : " << _orig << endl;
- cerr << "Occluders nb : " << _occluders.size() << endl;
- }
-
- protected:
-
- /*! Core of castRay and castInfiniteRay, find occluders
- * along the given ray
- */
- inline void castRayInternal(GridVisitor& visitor) {
- Cell* current_cell = NULL;
- do {
- current_cell = getCell(_current_cell);
- if (current_cell){
- visitor.discoverCell(current_cell);
- OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
- for (OccludersSet::iterator it = occluders.begin();
- it != occluders.end();
- it++) {
- if ((unsigned long)(*it)->userdata2 != _timestamp) {
- (*it)->userdata2 = (void*)_timestamp;
- visitor.examineOccluder(*it);
- }
- }
- visitor.finishCell(current_cell);
- }
- } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
- }
-
-
- /*! returns the cell next to the cell
- * passed as argument.
- */
- bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
-
- unsigned _timestamp;
-
- Vec3u _cells_nb; // number of cells for x,y,z axis
- Vec3r _cell_size; // cell x,y,z dimensions
- Vec3r _size; // grid x,y,x dimensions
- Vec3r _orig; // grid origin
-
- Vec3r _ray_dir; // direction vector for the ray
- Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
- Vec3r _pt; // Points corresponding to the incoming and outgoing intersections
- // of one cell with the ray
- real _t_end; // To know when we are at the end of the ray
- real _t;
-
- //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
- OccludersSet _occluders; // List of all occluders inserted in the grid
+ /*! Builds a Grid. Must be followed by a call to configure() */
+ Grid() {}
+
+ virtual ~Grid() {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns a vector of integer containing the coordinates of the cell containing the point passed as argument
+ * p
+ * The point for which we're looking the cell
+ */
+ inline void getCellCoordinates(const Vec3r& p, Vec3u& res) {
+ int tmp;
+ for (int i = 0; i < 3; i++) {
+ tmp = (int)((p[i] - _orig[i]) / _cell_size[i]);
+ if (tmp < 0)
+ res[i] = 0;
+ else if ((unsigned int)tmp >= _cells_nb[i])
+ res[i] = _cells_nb[i] - 1;
+ else
+ res[i] = tmp;
+ }
+ }
+
+ /*! Fills the case corresponding to coord with the cell */
+ virtual void fillCell(const Vec3u& coord, Cell& cell) = 0;
+
+ /*! returns the cell whose coordinates are pased as argument */
+ virtual Cell* getCell(const Vec3u& coord) = 0;
+
+ /*! returns the cell containing the point passed as argument. If the cell is empty (contains no occluder),
+ * NULL is returned
+ * p
+ * The point for which we're looking the cell
+ */
+ inline Cell* getCell(const Vec3r& p) {
+ Vec3u coord;
+ getCellCoordinates(p, coord);
+ return getCell(coord);
+ }
+
+ /*! Retrieves the x,y,z coordinates of the origin of the cell whose coordinates (i,j,k) is passed as argument
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * orig
+ * x,y,x vector to be filled in with the cell origin's coordinates
+ */
+ inline void getCellOrigin(const Vec3u& cell_coord, Vec3r& orig) {
+ for (unsigned int i = 0; i < 3; i++)
+ orig[i] = _orig[i] + cell_coord[i] * _cell_size[i];
+ }
+
+ /*! Retrieves the box corresponding to the cell whose coordinates are passed as argument.
+ * cell_coord
+ * i,j,k integer coordinates for the cell
+ * min_out
+ * The min x,y,x vector of the box. Filled in by the method.
+ * max_out
+ * The max x,y,z coordinates of the box. Filled in by the method.
+ */
+ inline void getCellBox(const Vec3u& cell_coord, Vec3r& min_out, Vec3r& max_out) {
+ getCellOrigin(cell_coord, min_out);
+ max_out = min_out + _cell_size;
+ }
+
+ /*! inserts a convex polygon occluder
+ * This method is quite coarse insofar as it adds all cells intersecting the polygon bounding box
+ * convex_poly
+ * The list of 3D points constituing a convex polygon
+ */
+ void insertOccluder(Polygon3r * convex_poly);
+
+ /*! Adds an occluder to the list of occluders */
+ void addOccluder(Polygon3r* occluder) {
+ _occluders.push_back(occluder);
+ }
+
+ /*! Casts a ray between a starting point and an ending point
+ * Returns the list of occluders contained in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castRay(const Vec3r& orig, const Vec3r& end, OccludersSet& occluders, unsigned timestamp);
+
+ // Prepares to cast ray without generating OccludersSet
+ void initAcceleratedRay(const Vec3r& orig, const Vec3r& end, unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the list of occluders contained in the cells intersected by this ray
+ * Starts with a call to InitRay.
+ */
+ void castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp);
+
+ // Prepares to cast ray without generating OccludersSet.
+ bool initAcceleratedInfiniteRay(const Vec3r& orig, const Vec3r& dir, unsigned timestamp);
+
+ /*! Casts an infinite ray (still finishing at the end of the grid) from a starting point and in a given direction.
+ * Returns the first intersection (occluder,t,u,v) or null.
+ * Starts with a call to InitRay.
+ */
+ Polygon3r * castRayToFindFirstIntersection(const Vec3r& orig, const Vec3r& dir, double& t,
+ double& u, double& v, unsigned timestamp);
+
+
+ /*! Init all structures and values for computing the cells intersected by this new ray */
+ void initRay(const Vec3r &orig, const Vec3r& end, unsigned timestamp);
+
+ /*! Init all structures and values for computing the cells intersected by this infinite ray.
+ * Returns false if the ray doesn't intersect the grid.
+ */
+ bool initInfiniteRay(const Vec3r &orig, const Vec3r& dir, unsigned timestamp);
+
+
+ /*! Accessors */
+ inline const Vec3r& getOrigin() const {
+ return _orig;
+ }
+
+ inline Vec3r gridSize() const {
+ return _size;
+ }
+
+ inline Vec3r getCellSize() const {
+ return _cell_size;
+ }
+
+ //ARB profiling only:
+ inline OccludersSet* getOccluders() {
+ return &_occluders;
+ }
+
+ void displayDebug() {
+ cerr << "Cells nb : " << _cells_nb << endl;
+ cerr << "Cell size : " << _cell_size << endl;
+ cerr << "Origin : " << _orig << endl;
+ cerr << "Occluders nb : " << _occluders.size() << endl;
+ }
+
+protected:
+ /*! Core of castRay and castInfiniteRay, find occluders along the given ray */
+ inline void castRayInternal(GridVisitor& visitor) {
+ Cell *current_cell = NULL;
+ do {
+ current_cell = getCell(_current_cell);
+ if (current_cell) {
+ visitor.discoverCell(current_cell);
+ OccludersSet& occluders = current_cell->getOccluders(); // FIXME: I had forgotten the ref &
+ for (OccludersSet::iterator it = occluders.begin(); it != occluders.end(); it++) {
+ if ((unsigned long)(*it)->userdata2 != _timestamp) {
+ (*it)->userdata2 = (void*)_timestamp;
+ visitor.examineOccluder(*it);
+ }
+ }
+ visitor.finishCell(current_cell);
+ }
+ } while ((!visitor.stop()) && (nextRayCell(_current_cell, _current_cell)));
+ }
+
+
+ /*! returns the cell next to the cell passed as argument. */
+ bool nextRayCell(Vec3u& current_cell, Vec3u& next_cell);
+
+ unsigned int _timestamp;
+
+ Vec3u _cells_nb; // number of cells for x,y,z axis
+ Vec3r _cell_size; // cell x,y,z dimensions
+ Vec3r _size; // grid x,y,x dimensions
+ Vec3r _orig; // grid origin
+
+ Vec3r _ray_dir; // direction vector for the ray
+ Vec3u _current_cell; // The current cell being processed (designated by its 3 coordinates)
+ Vec3r _pt; // Points corresponding to the incoming and outgoing intersections of one cell with the ray
+ real _t_end; // To know when we are at the end of the ray
+ real _t;
+
+ //OccludersSet _ray_occluders; // Set storing the occluders contained in the cells traversed by a ray
+ OccludersSet _occluders; // List of all occluders inserted in the grid
};
//
@@ -378,15 +362,16 @@ public:
///////////////////////////////////////////////////////////////////////////////
class VirtualOccludersSet {
- public:
- VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
- Polygon3r* begin();
- Polygon3r* next();
- Polygon3r* next(bool stopOnNewCell);
- private:
- Polygon3r* firstOccluderFromNextCell();
- Grid& grid;
- OccludersSet::iterator it, end;
+public:
+ VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
+ Polygon3r* begin();
+ Polygon3r* next();
+ Polygon3r* next(bool stopOnNewCell);
+
+private:
+ Polygon3r* firstOccluderFromNextCell();
+ Grid& grid;
+ OccludersSet::iterator it, end;
};
-#endif // GRID_H
+#endif // __GRID_H__
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.cpp b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
index dcf24a72efb..055a47f6bd5 100644
--- a/source/blender/freestyle/intern/geometry/GridHelpers.cpp
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
@@ -1,49 +1,52 @@
-//
-// Filename : GridHelpers.cpp
-// Author(s) : Alexander Beels
-// Purpose : Class to define a cell grid surrounding
-// the projected image of a scene
-// Date of creation : 2010-12-21
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/GridHelpers.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-21
+ */
#include <math.h>
+
#include "GridHelpers.h"
-void GridHelpers::getDefaultViewProscenium(real viewProscenium[4]) {
+void GridHelpers::getDefaultViewProscenium(real viewProscenium[4])
+{
// Get proscenium boundary for culling
- // bufferZone determines the amount by which the area processed
- // should exceed the actual image area. This is intended to
- // avoid visible artifacts generated along the proscenium edge.
- // Perhaps this is no longer needed now that entire view edges
- // are culled at once, since that theoretically should eliminate
- // visible artifacts.
- // To the extent it is still useful, bufferZone should be put into
- // the UI as configurable percentage value
+ // bufferZone determines the amount by which the area processed should exceed the actual image area.
+ // This is intended to avoid visible artifacts generated along the proscenium edge.
+ // Perhaps this is no longer needed now that entire view edges are culled at once, since that theoretically
+ // should eliminate visible artifacts.
+ // To the extent it is still useful, bufferZone should be put into the UI as configurable percentage value
const real bufferZone = 0.05;
- // borderZone describes a blank border outside the proscenium, but
- // still inside the image area. Only intended for exposing possible
- // artifacts along or outside the proscenium edge during debugging.
+ // borderZone describes a blank border outside the proscenium, but still inside the image area.
+ // Only intended for exposing possible artifacts along or outside the proscenium edge during debugging.
const real borderZone = 0.0;
viewProscenium[0] = freestyle_viewport[2] * (borderZone - bufferZone);
viewProscenium[1] = freestyle_viewport[2] * (1.0f - borderZone + bufferZone);
@@ -51,6 +54,6 @@ void GridHelpers::getDefaultViewProscenium(real viewProscenium[4]) {
viewProscenium[3] = freestyle_viewport[3] * (1.0f - borderZone + bufferZone);
}
-GridHelpers::Transform::~Transform () {}
-
-
+GridHelpers::Transform::~Transform ()
+{
+}
diff --git a/source/blender/freestyle/intern/geometry/GridHelpers.h b/source/blender/freestyle/intern/geometry/GridHelpers.h
index b079005c1b5..4391b4f61a3 100644
--- a/source/blender/freestyle/intern/geometry/GridHelpers.h
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.h
@@ -1,47 +1,55 @@
-//
-// Filename : GridHelpers.h
-// Author(s) : Alexander Beels
-// Purpose : Class to define a cell grid surrounding
-// the projected image of a scene
-// Date of creation : 2010-12-13
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-//
-// 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 GRIDHELPERS_H
-#define GRIDHELPERS_H
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __GRIDHELPERS_H__
+#define __GRIDHELPERS_H__
+
+/** \file blender/freestyle/intern/geometry/GridHelpers.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the projected image of a scene
+ * \author Alexander Beels
+ * \date 2010-12-13
+ */
#include <vector>
-#include "Polygon.h"
-#include "../winged_edge/WEdge.h"
+
#include "FRS_freestyle.h"
+
#include "GeomUtils.h"
+#include "Polygon.h"
+
+#include "../winged_edge/WEdge.h"
namespace GridHelpers {
/*! Computes the distance from a point P to a segment AB */
template<class T>
-T closestPointToSegment(const T& P, const T& A , const T& B, real& distance) {
+T closestPointToSegment(const T& P, const T& A , const T& B, real& distance)
+{
T AB, AP, BP;
AB = B - A;
AP = P - A;
@@ -59,31 +67,32 @@ T closestPointToSegment(const T& P, const T& A , const T& B, real& distance) {
return B; // B is closest point
}
- real b = c1 / c2;
- T Pb, PPb;
- Pb = A + b * AB;
- PPb = P - Pb;
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
- distance = PPb.norm();
+ distance = PPb.norm();
return Pb; // closest point lies on AB
}
-inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly) {
+inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly)
+{
// First cast a ray from the point onto the polygon plane
// If the ray intersects the polygon, then the intersection point
// is the closest point on the polygon
real t, u, v;
- if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
+ if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
return point + poly.getNormal() * t;
}
// Otherwise, get the nearest point on each edge, and take the closest
real distance;
Vec3r closest = closestPointToSegment(point, poly.getVertices()[2], poly.getVertices()[0], distance);
- for ( unsigned i = 0; i < 2; ++i ) {
+ for (unsigned int i = 0; i < 2; ++i) {
real t;
Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
- if ( t < distance ) {
+ if (t < distance) {
distance = t;
closest = p;
}
@@ -91,57 +100,63 @@ inline Vec3r closestPointOnPolygon(const Vec3r& point, const Polygon3r& poly) {
return closest;
}
-inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly) {
+inline real distancePointToPolygon(const Vec3r& point, const Polygon3r& poly)
+{
// First cast a ray from the point onto the polygon plane
// If the ray intersects the polygon, then the intersection point
// is the closest point on the polygon
real t, u, v;
- if ( poly.rayIntersect(point, poly.getNormal(), t, u, v) ) {
- return t > 0.0 ? t : -t;
+ if (poly.rayIntersect(point, poly.getNormal(), t, u, v)) {
+ return (t > 0.0) ? t : -t;
}
// Otherwise, get the nearest point on each edge, and take the closest
real distance = GeomUtils::distPointSegment(point, poly.getVertices()[2], poly.getVertices()[0]);
- for ( unsigned i = 0; i < 2; ++i ) {
+ for (unsigned int i = 0; i < 2; ++i) {
real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
- if ( t < distance ) {
+ if (t < distance) {
distance = t;
}
}
return distance;
}
-class Transform {
+class Transform
+{
public:
- virtual ~Transform () =0;
- virtual Vec3r operator()(const Vec3r& point) const =0;
+ virtual ~Transform () = 0;
+ virtual Vec3r operator()(const Vec3r& point) const = 0;
};
-inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon) {
- // N.B. The bounding box check is redundant for inserting occluders into
- // cells, because the cell selection code in insertOccluders has already
- // guaranteed that the bounding boxes will overlap.
+inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon)
+{
+ // N.B. The bounding box check is redundant for inserting occluders into cells, because the cell selection code
+ // in insertOccluders has already guaranteed that the bounding boxes will overlap.
// First check the viewport edges, since they are the easiest case
// Check if the bounding box is entirely outside the proscenium
Vec3r bbMin, bbMax;
polygon.getBBox(bbMin, bbMax);
- if ( bbMax[0] < proscenium[0]
- || bbMin[0] > proscenium[1]
- || bbMax[1] < proscenium[2]
- || bbMin[1] > proscenium[3] ) {
+ if (bbMax[0] < proscenium[0] || bbMin[0] > proscenium[1] || bbMax[1] < proscenium[2] || bbMin[1] > proscenium[3]) {
return false;
}
- Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0, proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
- Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0, (proscenium[3] - proscenium[2]) / 2.0, 1.0);
- Vec3r triverts[3] = { Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0), Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0), Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0) };
+ Vec3r boxCenter(proscenium[0] + (proscenium[1] - proscenium[0]) / 2.0,
+ proscenium[2] + (proscenium[3] - proscenium[2]) / 2.0, 0.0);
+ Vec3r boxHalfSize((proscenium[1] - proscenium[0]) / 2.0,
+ (proscenium[3] - proscenium[2]) / 2.0, 1.0);
+ Vec3r triverts[3] = {
+ Vec3r(polygon.getVertices()[0][0], polygon.getVertices()[0][1], 0.0),
+ Vec3r(polygon.getVertices()[1][0], polygon.getVertices()[1][1], 0.0),
+ Vec3r(polygon.getVertices()[2][0], polygon.getVertices()[2][1], 0.0)
+ };
return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
}
-inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges) {
+inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges)
+{
vector<Vec3r> points;
// Iterate over vertices, storing projections in points
- for(vector<WOEdge*>::const_iterator woe=fedges.begin(), woend=fedges.end(); woe!=woend; woe++) {
+ for (vector<WOEdge*>::const_iterator woe = fedges.begin(), woend = fedges.end(); woe != woend; woe++) {
points.push_back((*woe)->GetaVertex()->GetVertex());
}
@@ -150,50 +165,51 @@ inline vector<Vec3r> enumerateVertices(const vector<WOEdge*>& fedges) {
void getDefaultViewProscenium(real viewProscenium[4]);
-inline void expandProscenium (real proscenium[4], const Polygon3r& polygon) {
+inline void expandProscenium (real proscenium[4], const Polygon3r& polygon)
+{
Vec3r bbMin, bbMax;
polygon.getBBox(bbMin, bbMax);
const real epsilon = 1.0e-6;
- if ( bbMin[0] <= proscenium[0] ) {
+ if (bbMin[0] <= proscenium[0]) {
proscenium[0] = bbMin[0] - epsilon;
}
- if ( bbMin[1] <= proscenium[2] ) {
+ if (bbMin[1] <= proscenium[2]) {
proscenium[2] = bbMin[1] - epsilon;
}
- if ( bbMax[0] >= proscenium[1] ) {
+ if (bbMax[0] >= proscenium[1]) {
proscenium[1] = bbMax[0] + epsilon;
}
- if ( bbMax[1] >= proscenium[3] ) {
+ if (bbMax[1] >= proscenium[3]) {
proscenium[3] = bbMax[1] + epsilon;
}
}
-inline void expandProscenium (real proscenium[4], const Vec3r& point) {
+inline void expandProscenium (real proscenium[4], const Vec3r& point)
+{
const real epsilon = 1.0e-6;
- if ( point[0] <= proscenium[0] ) {
+ if (point[0] <= proscenium[0]) {
proscenium[0] = point[0] - epsilon;
}
- if ( point[1] <= proscenium[2] ) {
+ if (point[1] <= proscenium[2]) {
proscenium[2] = point[1] - epsilon;
}
- if ( point[0] >= proscenium[1] ) {
+ if (point[0] >= proscenium[1]) {
proscenium[1] = point[0] + epsilon;
}
- if ( point[1] >= proscenium[3] ) {
+ if (point[1] >= proscenium[3]) {
proscenium[3] = point[1] + epsilon;
}
}
-};
-
-#endif // GRIDHELPERS_H
+}; // GridHelpers namespace
+#endif // __GRIDHELPERS_H__
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
index 3cf845d57ef..b0ad9e0f276 100644
--- a/source/blender/freestyle/intern/geometry/HashGrid.cpp
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -1,41 +1,53 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/** \file blender/freestyle/intern/geometry/HashGrid.cpp
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
#include "HashGrid.h"
void HashGrid::clear()
{
- if(!_cells.empty()) {
- for(GridHashTable::iterator it = _cells.begin();
- it !=_cells.end();
- it++) {
- Cell* cell = (*it).second;
- delete cell;
- }
- _cells.clear();
- }
+ if (!_cells.empty()) {
+ for (GridHashTable::iterator it = _cells.begin(); it !=_cells.end(); it++) {
+ Cell* cell = (*it).second;
+ delete cell;
+ }
+ _cells.clear();
+ }
- Grid::clear();
+ Grid::clear();
}
-void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb) {
- Grid::configure(orig, size, nb);
+void HashGrid::configure(const Vec3r& orig, const Vec3r& size, unsigned nb)
+{
+ Grid::configure(orig, size, nb);
}
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h
index f6605957676..ca6edb258a9 100644
--- a/source/blender/freestyle/intern/geometry/HashGrid.h
+++ b/source/blender/freestyle/intern/geometry/HashGrid.h
@@ -1,109 +1,116 @@
-//
-// Filename : HashGrid.h
-// Author(s) : Stephane Grabli
-// Purpose : Class to define a cell grid surrounding the
-// bounding box of the scene
-// Date of creation : 30/07/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 HASHGRID_H
-# define HASHGRID_H
-
-//# if defined(__GNUC__) && (__GNUC__ >= 3)
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __HASHGRID_H__
+#define __HASHGRID_H__
+
+/** \file blender/freestyle/intern/geometry/HashGrid.h
+ * \ingroup freestyle
+ * \brief Class to define a cell grid surrounding the bounding box of the scene
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#if 0
+# if defined(__GNUC__) && (__GNUC__ >= 3)
// hash_map is not part of the C++ standard anymore;
// hash_map.h has been kept though for backward compatibility
-//# include <hash_map.h>
-//# else
-//# include <hash_map>
-//# endif
+# include <hash_map.h>
+# else
+# include <hash_map>
+# endif
+#endif
+
+#include <map>
+
+#include "Grid.h"
-# include "Grid.h"
-# include <map>
/*! Defines a hash table used for searching the Cells */
-struct GridHasher{
+struct GridHasher
+{
#define _MUL 950706376UL
#define _MOD 2147483647UL
- inline size_t operator() (const Vec3u& p) const
- {
- size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
- res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
- return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
- }
+ inline size_t operator() (const Vec3u& p) const
+ {
+ size_t res = ((unsigned long) (p[0] * _MUL)) % _MOD;
+ res = ((res + (unsigned long) (p[1]) * _MUL)) % _MOD;
+ return ((res +(unsigned long) (p[2]) * _MUL)) % _MOD;
+ }
+#undef _MUL
+#undef _MOD
};
-/*! Class to define a regular grid used for ray
- casting computations */
-
+/*! Class to define a regular grid used for ray casting computations */
class LIB_GEOMETRY_EXPORT HashGrid : public Grid
{
- public:
-
- typedef map<Vec3u, Cell*> GridHashTable;
-
- HashGrid() : Grid() {}
-
- virtual ~HashGrid() {
- clear();
- }
-
- /*! clears the grid
- * Deletes all the cells, clears the hashtable,
- * resets size, size of cell, number of cells.
- */
- virtual void clear();
-
- /*! Sets the different parameters of the grid
- * orig
- * The grid origin
- * size
- * The grid's dimensions
- * nb
- * The number of cells of the grid
- */
- virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
-
- /*! returns the cell whose coordinates
- * are pased as argument
- */
- virtual Cell* getCell(const Vec3u& p) {
- Cell* found_cell = NULL;
-
- GridHashTable::const_iterator found = _cells.find(p);
- if (found != _cells.end())
- found_cell = (*found).second;
- return found_cell;
- }
-
- /*! Fills the case p with the cell iCell */
- virtual void fillCell(const Vec3u& p, Cell& cell) {
- _cells[p] = &cell;
- }
+public:
+ typedef map<Vec3u, Cell*> GridHashTable;
-protected:
+ HashGrid() : Grid() {}
- GridHashTable _cells;
+ virtual ~HashGrid()
+ {
+ clear();
+ }
+
+ /*! clears the grid
+ * Deletes all the cells, clears the hashtable, resets size, size of cell, number of cells.
+ */
+ virtual void clear();
+
+ /*! Sets the different parameters of the grid
+ * orig
+ * The grid origin
+ * size
+ * The grid's dimensions
+ * nb
+ * The number of cells of the grid
+ */
+ virtual void configure(const Vec3r& orig, const Vec3r& size, unsigned nb);
+
+ /*! returns the cell whose coordinates are pased as argument */
+ virtual Cell* getCell(const Vec3u& p)
+ {
+ Cell* found_cell = NULL;
+
+ GridHashTable::const_iterator found = _cells.find(p);
+ if (found != _cells.end())
+ found_cell = (*found).second;
+ return found_cell;
+ }
+
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u& p, Cell& cell)
+ {
+ _cells[p] = &cell;
+ }
+
+protected:
+ GridHashTable _cells;
};
-#endif // HASHGRID_H
+#endif // __HASHGRID_H__
diff --git a/source/blender/freestyle/intern/geometry/Noise.cpp b/source/blender/freestyle/intern/geometry/Noise.cpp
index ede8c434d9d..0769664fcbb 100644
--- a/source/blender/freestyle/intern/geometry/Noise.cpp
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -1,264 +1,285 @@
-
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+/** \file blender/freestyle/intern/geometry/Noise.cpp
+ * \ingroup freestyle
+ * \brief Class to define Perlin noise
+ * \author Emmanuel Turquin
+ * \date 12/01/2004
+ */
+
+#include <math.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <time.h>
#include "Noise.h"
-# include <stdlib.h>
-# include <stdio.h>
-# include <math.h>
-#include <time.h>
-#define MINX -1000000
-#define MINY MINX
-#define MINZ MINX
-#define SCURVE(a) ((a)*(a)*(3.0-2.0*(a)))
-#define REALSCALE ( 2.0 / 65536.0 )
-#define NREALSCALE ( 2.0 / 4096.0 )
-#define HASH3D(a,b,c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
-#define HASH(a,b,c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
-#define INCRSUM(m,s,x,y,z) ((s)*(RTable[m]*0.5 \
- + RTable[m+1]*(x) \
- + RTable[m+2]*(y) \
- + RTable[m+3]*(z)))
-#define MAXSIZE 500
-#define nrand() ((float)rand()/(float)RAND_MAX)
-#define seednrand(x) srand(x*RAND_MAX)
+#define MINX -1000000
+#define MINY MINX
+#define MINZ MINX
-#define BM 0xff
+#define SCURVE(a) ((a) * (a) * (3.0 - 2.0 * (a)))
-#define N 0x1000
-#define NP 12 /* 2^N */
-#define NM 0xfff
+#define REALSCALE (2.0 / 65536.0)
+#define NREALSCALE (2.0 / 4096.0)
+
+#define HASH3D(a, b, c) hashTable[hashTable[hashTable[(a) & 0xfff] ^ ((b) & 0xfff)] ^ ((c) & 0xfff)]
+#define HASH(a, b, c) (xtab[(xtab[(xtab[(a) & 0xff] ^ (b)) & 0xff] ^ (c)) & 0xff] & 0xff)
+
+#define INCRSUM(m, s, x, y, z) \
+ ((s) * (RTable[m] * 0.5 + RTable[m + 1] * (x) + RTable[m + 2] * (y) + RTable[m + 3] * (z)))
-#define s_curve(t) ( t * t * (3. - 2. * t) )
+#define MAXSIZE 500
-#define lerp(t, a, b) ( a + t * (b - a) )
+#if 0 // XXX Unused
+#define NRAND() ((float)rand() / (float)RAND_MAX)
+#endif
+#define SEEDNRAND(x) (srand(x * RAND_MAX))
-#define setup(i,b0,b1,r0,r1)\
- t = i + N;\
- b0 = ((int)t) & BM;\
- b1 = (b0+1) & BM;\
- r0 = t - (int)t;\
- r1 = r0 - 1.;
+#define BM 0xff
+#define N 0x1000
+#define NP 12 /* 2^N */
+#define NM 0xfff
+
+#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
+
+#define SETUP(i, b0, b1, r0, r1) \
+ { \
+ (t) = (i) + (N); \
+ (b0) = ((int)(t)) & BM; \
+ (b1) = ((b0) + 1) & BM; \
+ (r0) = (t) - (int)(t); \
+ (r1) = (r0) - 1.0; \
+ } (void)0
static void normalize2(float v[2])
{
- float s;
+ float s;
- s = sqrt(v[0] * v[0] + v[1] * v[1]);
- v[0] = v[0] / s;
- v[1] = v[1] / s;
+ s = sqrt(v[0] * v[0] + v[1] * v[1]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
}
static void normalize3(float v[3])
{
- float s;
+ float s;
- s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
- v[0] = v[0] / s;
- v[1] = v[1] / s;
- v[2] = v[2] / s;
+ s = sqrt(v[0] * v[0] + v[1] * v[1] + v[2] * v[2]);
+ v[0] = v[0] / s;
+ v[1] = v[1] / s;
+ v[2] = v[2] / s;
}
float Noise::turbulence1(float arg, float freq, float amp, unsigned oct)
{
- float t;
- float vec;
-
- for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
- {
- vec = freq * arg;
- t += smoothNoise1(vec) * amp;
- }
- return t;
+ float t;
+ float vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec = freq * arg;
+ t += smoothNoise1(vec) * amp;
+ }
+ return t;
}
float Noise::turbulence2(Vec2f& v, float freq, float amp, unsigned oct)
{
- float t;
- Vec2f vec;
-
- for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
- {
- vec.x() = freq * v.x();
- vec.y() = freq * v.y();
- t += smoothNoise2(vec) * amp;
- }
- return t;
+ float t;
+ Vec2f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ t += smoothNoise2(vec) * amp;
+ }
+ return t;
}
float Noise::turbulence3(Vec3f& v, float freq, float amp, unsigned oct)
{
- float t;
- Vec3f vec;
-
- for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct)
- {
- vec.x() = freq * v.x();
- vec.y() = freq * v.y();
- vec.z() = freq * v.z();
- t += smoothNoise3(vec) * amp;
- }
- return t;
+ float t;
+ Vec3f vec;
+
+ for (t = 0; oct > 0 && freq > 0; freq *= 2, amp /= 2, --oct) {
+ vec.x() = freq * v.x();
+ vec.y() = freq * v.y();
+ vec.z() = freq * v.z();
+ t += smoothNoise3(vec) * amp;
+ }
+ return t;
}
// Noise functions over 1, 2, and 3 dimensions
-
float Noise::smoothNoise1(float arg)
{
- int bx0, bx1;
- float rx0, rx1, sx, t, u, v, vec;
+ int bx0, bx1;
+ float rx0, rx1, sx, t, u, v, vec;
- vec = arg;
- setup(vec, bx0,bx1, rx0,rx1);
+ vec = arg;
+ SETUP(vec, bx0, bx1, rx0, rx1);
- sx = s_curve(rx0);
+ sx = SCURVE(rx0);
- u = rx0 * g1[ p[ bx0 ] ];
- v = rx1 * g1[ p[ bx1 ] ];
+ u = rx0 * g1[p[bx0]];
+ v = rx1 * g1[p[bx1]];
- return lerp(sx, u, v);
+ return LERP(sx, u, v);
}
float Noise::smoothNoise2(Vec2f& vec)
{
- int bx0, bx1, by0, by1, b00, b10, b01, b11;
- float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
- register int i, j;
+ int bx0, bx1, by0, by1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, *q, sx, sy, a, b, t, u, v;
+ register int i, j;
+
+ SETUP(vec.x(), bx0, bx1, rx0, rx1);
+ SETUP(vec.y(), by0, by1, ry0, ry1);
- setup(vec.x(), bx0,bx1, rx0,rx1);
- setup(vec.y(), by0,by1, ry0,ry1);
+ i = p[bx0];
+ j = p[bx1];
- i = p[ bx0 ];
- j = p[ bx1 ];
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
- b00 = p[ i + by0 ];
- b10 = p[ j + by0 ];
- b01 = p[ i + by1 ];
- b11 = p[ j + by1 ];
+ sx = SCURVE(rx0);
+ sy = SCURVE(ry0);
- sx = s_curve(rx0);
- sy = s_curve(ry0);
+#define AT2(rx, ry) ((rx) * q[0] + (ry) * q[1])
-#define at2(rx,ry) ( rx * q[0] + ry * q[1] )
+ q = g2[b00];
+ u = AT2(rx0, ry0);
+ q = g2[b10];
+ v = AT2(rx1, ry0);
+ a = LERP(sx, u, v);
- q = g2[ b00 ] ; u = at2(rx0,ry0);
- q = g2[ b10 ] ; v = at2(rx1,ry0);
- a = lerp(sx, u, v);
+ q = g2[b01];
+ u = AT2(rx0, ry1);
+ q = g2[b11];
+ v = AT2(rx1, ry1);
+ b = LERP(sx, u, v);
- q = g2[ b01 ] ; u = at2(rx0,ry1);
- q = g2[ b11 ] ; v = at2(rx1,ry1);
- b = lerp(sx, u, v);
+#undef AT2
- return lerp(sy, a, b);
+ return LERP(sy, a, b);
}
float Noise::smoothNoise3(Vec3f& vec)
{
- int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
- float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
- register int i, j;
+ int bx0, bx1, by0, by1, bz0, bz1, b00, b10, b01, b11;
+ float rx0, rx1, ry0, ry1, rz0, rz1, *q, sy, sz, a, b, c, d, t, u, v;
+ register int i, j;
+
+ SETUP(vec.x(), bx0, bx1, rx0, rx1);
+ SETUP(vec.y(), by0, by1, ry0, ry1);
+ SETUP(vec.z(), bz0, bz1, rz0, rz1);
- setup(vec.x(), bx0,bx1, rx0,rx1);
- setup(vec.y(), by0,by1, ry0,ry1);
- setup(vec.z(), bz0,bz1, rz0,rz1);
+ i = p[bx0];
+ j = p[bx1];
- i = p[ bx0 ];
- j = p[ bx1 ];
+ b00 = p[i + by0];
+ b10 = p[j + by0];
+ b01 = p[i + by1];
+ b11 = p[j + by1];
- b00 = p[ i + by0 ];
- b10 = p[ j + by0 ];
- b01 = p[ i + by1 ];
- b11 = p[ j + by1 ];
+ t = SCURVE(rx0);
+ sy = SCURVE(ry0);
+ sz = SCURVE(rz0);
- t = s_curve(rx0);
- sy = s_curve(ry0);
- sz = s_curve(rz0);
+#define AT3(rx, ry, rz) ((rx) * q[0] + (ry) * q[1] + (rz) * q[2])
-#define at3(rx,ry,rz) ( rx * q[0] + ry * q[1] + rz * q[2] )
+ q = g3[b00 + bz0];
+ u = AT3(rx0, ry0, rz0);
+ q = g3[b10 + bz0];
+ v = AT3(rx1, ry0, rz0);
+ a = LERP(t, u, v);
- q = g3[ b00 + bz0 ] ;
- u = at3(rx0,ry0,rz0);
- q = g3[ b10 + bz0 ] ;
- v = at3(rx1,ry0,rz0);
- a = lerp(t, u, v);
+ q = g3[b01 + bz0];
+ u = AT3(rx0, ry1, rz0);
+ q = g3[b11 + bz0];
+ v = AT3(rx1, ry1, rz0);
+ b = LERP(t, u, v);
- q = g3[ b01 + bz0 ] ;
- u = at3(rx0,ry1,rz0);
- q = g3[ b11 + bz0 ] ;
- v = at3(rx1,ry1,rz0);
- b = lerp(t, u, v);
+ c = LERP(sy, a, b);
- c = lerp(sy, a, b);
+ q = g3[b00 + bz1];
+ u = AT3(rx0, ry0, rz1);
+ q = g3[b10 + bz1];
+ v = AT3(rx1, ry0, rz1);
+ a = LERP(t, u, v);
- q = g3[ b00 + bz1 ] ;
- u = at3(rx0,ry0,rz1);
- q = g3[ b10 + bz1 ] ;
- v = at3(rx1,ry0,rz1);
- a = lerp(t, u, v);
+ q = g3[b01 + bz1];
+ u = AT3(rx0, ry1, rz1);
+ q = g3[b11 + bz1];
+ v = AT3(rx1, ry1, rz1);
+ b = LERP(t, u, v);
- q = g3[ b01 + bz1 ] ;
- u = at3(rx0,ry1,rz1);
- q = g3[ b11 + bz1 ] ;
- v = at3(rx1,ry1,rz1);
- b = lerp(t, u, v);
+ d = LERP(sy, a, b);
- d = lerp(sy, a, b);
+#undef AT3
- return lerp(sz, c, d);
+ return LERP(sz, c, d);
}
Noise::Noise(long seed)
{
- int i, j, k;
-
- seednrand((seed < 0) ? time(NULL) : seed);
- for (i = 0 ; i < _Noise_B_ ; i++)
- {
- p[i] = i;
-
- g1[i] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
-
- for (j = 0 ; j < 2 ; j++)
- g2[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
- normalize2(g2[i]);
-
- for (j = 0 ; j < 3 ; j++)
- g3[i][j] = (float)((rand() % (_Noise_B_ + _Noise_B_)) - _Noise_B_) / _Noise_B_;
- normalize3(g3[i]);
- }
-
- while (--i)
- {
- k = p[i];
- p[i] = p[j = rand() % _Noise_B_];
- p[j] = k;
- }
-
- for (i = 0 ; i < _Noise_B_ + 2 ; i++)
- {
- p[_Noise_B_ + i] = p[i];
- g1[_Noise_B_ + i] = g1[i];
- for (j = 0 ; j < 2 ; j++)
- g2[_Noise_B_ + i][j] = g2[i][j];
- for (j = 0 ; j < 3 ; j++)
- g3[_Noise_B_ + i][j] = g3[i][j];
- }
+ int i, j, k;
+
+ SEEDNRAND((seed < 0) ? time(NULL) : seed);
+ for (i = 0 ; i < _NOISE_B ; i++) {
+ p[i] = i;
+ g1[i] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ normalize2(g2[i]);
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[i][j] = (float)((rand() % (_NOISE_B + _NOISE_B)) - _NOISE_B) / _NOISE_B;
+ normalize3(g3[i]);
+ }
+
+ while (--i) {
+ k = p[i];
+ p[i] = p[j = rand() % _NOISE_B];
+ p[j] = k;
+ }
+
+ for (i = 0 ; i < _NOISE_B + 2 ; i++) {
+ p[_NOISE_B + i] = p[i];
+ g1[_NOISE_B + i] = g1[i];
+
+ for (j = 0 ; j < 2 ; j++)
+ g2[_NOISE_B + i][j] = g2[i][j];
+
+ for (j = 0 ; j < 3 ; j++)
+ g3[_NOISE_B + i][j] = g3[i][j];
+ }
}
diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h
index f92cf07e914..35d1af3712f 100644
--- a/source/blender/freestyle/intern/geometry/Noise.h
+++ b/source/blender/freestyle/intern/geometry/Noise.h
@@ -1,40 +1,45 @@
-//
-// Filename : Noise.h
-// Author(s) : Emmanuel Turquin
-// Purpose : Class to define Perlin noise
-// Date of creation : 12/01/2004
-//
-///////////////////////////////////////////////////////////////////////////////
-
-
-//
-// 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 NOISE_H
-# define NOISE_H
-
-
-# include "../system/FreestyleConfig.h"
-# include "Geom.h"
-
-#define _Noise_B_ 0x100
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __NOISE_H__
+#define __NOISE_H__
+
+/** \file blender/freestyle/intern/geometry/Noise.h
+ * \ingroup freestyle
+ * \brief Class to define Perlin noise
+ * \author Emmanuel Turquin
+ * \date 12/01/2004
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
+#define _NOISE_B 0x100
using namespace Geometry;
using namespace std;
@@ -42,36 +47,37 @@ using namespace std;
/*! Class to provide Perlin Noise functionalities */
class LIB_GEOMETRY_EXPORT Noise
{
- public:
+public:
+ /*! Builds a Noise object */
+ Noise(long seed = -1);
- /*! Builds a Noise object */
- Noise(long seed = -1);
- /*! Destructor */
- ~Noise() {}
+ /*! Destructor */
+ ~Noise() {}
- /*! Returns a noise value for a 1D element */
- float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
+ /*! Returns a noise value for a 1D element */
+ float turbulence1(float arg, float freq, float amp, unsigned oct = 4);
- /*! Returns a noise value for a 2D element */
- float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
+ /*! Returns a noise value for a 2D element */
+ float turbulence2(Vec2f& v, float freq, float amp, unsigned oct = 4);
- /*! Returns a noise value for a 3D element */
- float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
+ /*! Returns a noise value for a 3D element */
+ float turbulence3(Vec3f& v, float freq, float amp, unsigned oct = 4);
- /*! Returns a smooth noise value for a 1D element */
- float smoothNoise1(float arg);
- /*! Returns a smooth noise value for a 2D element */
- float smoothNoise2(Vec2f& vec);
- /*! Returns a smooth noise value for a 3D element */
- float smoothNoise3(Vec3f& vec);
+ /*! Returns a smooth noise value for a 1D element */
+ float smoothNoise1(float arg);
- private:
+ /*! Returns a smooth noise value for a 2D element */
+ float smoothNoise2(Vec2f& vec);
- int p[ _Noise_B_ + _Noise_B_ + 2];
- float g3[ _Noise_B_ + _Noise_B_ + 2][3];
- float g2[ _Noise_B_ + _Noise_B_ + 2][2];
- float g1[ _Noise_B_ + _Noise_B_ + 2];
- int start;
+ /*! Returns a smooth noise value for a 3D element */
+ float smoothNoise3(Vec3f& vec);
+
+private:
+ int p[_NOISE_B + _NOISE_B + 2];
+ float g3[_NOISE_B + _NOISE_B + 2][3];
+ float g2[_NOISE_B + _NOISE_B + 2][2];
+ float g1[_NOISE_B + _NOISE_B + 2];
+ int start;
};
-#endif // NOISE_H
+#endif // __NOISE_H__
diff --git a/source/blender/freestyle/intern/geometry/Polygon.h b/source/blender/freestyle/intern/geometry/Polygon.h
index 911804d80f7..5ee4353ef5a 100644
--- a/source/blender/freestyle/intern/geometry/Polygon.h
+++ b/source/blender/freestyle/intern/geometry/Polygon.h
@@ -1,38 +1,44 @@
-//
-// Filename : Polygon.h
-// Author(s) : Stephane Grabli
-// Purpose : Class to define a polygon
-// Date of creation : 30/07/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 POLYGON_H
-# define POLYGON_H
-
-# include <vector>
-# include "Geom.h"
-# include "GeomUtils.h"
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __POLYGON_H__
+#define __POLYGON_H__
+
+/** \file blender/freestyle/intern/geometry/Polygon.h
+ * \ingroup freestyle
+ * \brief Class to define a polygon
+ * \author Stephane Grabli
+ * \date 30/07/2002
+ */
+
+#include <vector>
+
+#include "Geom.h"
+#include "GeomUtils.h"
using namespace std;
@@ -41,129 +47,129 @@ namespace Geometry {
template <class Point>
class Polygon
{
- public:
-
- inline Polygon() {
- _id = 0;
- userdata = 0;
- userdata2 = 0;
- }
-
- inline Polygon(const vector<Point>& vertices) {
- _vertices = vertices;
- computeBBox();
- _id = 0;
- userdata = 0;
- userdata2 = 0;
- }
-
- inline Polygon(const Polygon<Point>& poly) {
- Point p;
- for(typename vector<Point>::const_iterator it = poly.getVertices().begin();
- it != poly.getVertices().end();
- it++) {
- p = *it;
- _vertices.push_back(p);
- }
-
- _id = poly.getId();
- poly.getBBox(_min, _max);
- userdata = 0;
- userdata2 = 0;
- }
-
- virtual ~Polygon() {}
-
- //
- // Accessors
- //
- /////////////////////////////////////////////////////////////////////////////
-
- inline const vector<Point>& getVertices() const {
- return _vertices;
- }
-
- inline void getBBox(Point& min, Point& max) const {
- min = _min;
- max = _max;
- }
-
- inline Point& getBBoxCenter()
- {
- Point result;
- result = (_min + _max) / 2;
- return result;
- }
-
- inline Point& getCenter() {
- Point result;
- for (typename vector<Point>::iterator it = _vertices.begin();
- it != _vertices.end();
- it++)
- result += *it;
- result /= _vertices.size();
- return result;
- }
-
- inline unsigned getId() const {
- return _id;
- }
-
- //
- // Modifiers
- //
- /////////////////////////////////////////////////////////////////////////////
-
- inline void setVertices(const vector<Point>& vertices) {
- _vertices.clear();
- Point p;
- for (typename vector<Point>::const_iterator it = vertices.begin();
- it != vertices.end();
- it++) {
- p = *it;
- _vertices.push_back(p);
- }
- computeBBox();
- }
-
- inline void setId(unsigned id) {
- _id = id;
- }
-
- //
- // Other methods
- //
- /////////////////////////////////////////////////////////////////////////////
-
- inline void computeBBox() {
- if(_vertices.empty())
- return;
-
- _max = _vertices[0];
- _min = _vertices[0];
-
- for(typename vector<Point>::iterator it = _vertices.begin();
- it != _vertices.end();
- it++) {
- for(unsigned i = 0; i < Point::dim(); i++) {
- if((*it)[i] > _max[i])
- _max[i] = (*it)[i];
- if((*it)[i] < _min[i])
- _min[i] = (*it)[i];
- }
- }
- }
-
- // FIXME Is it possible to get rid of userdatas ?
- void* userdata;
- void* userdata2; // Used during ray casting
-
- protected:
-
- vector<Point> _vertices;
- Point _min;
- Point _max;
- unsigned _id;
+public:
+ inline Polygon()
+ {
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const vector<Point>& vertices)
+ {
+ _vertices = vertices;
+ computeBBox();
+ _id = 0;
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ inline Polygon(const Polygon<Point>& poly)
+ {
+ Point p;
+ for (typename vector<Point>::const_iterator it = poly.getVertices().begin();
+ it != poly.getVertices().end();
+ it++)
+ {
+ p = *it;
+ _vertices.push_back(p);
+ }
+
+ _id = poly.getId();
+ poly.getBBox(_min, _max);
+ userdata = 0;
+ userdata2 = 0;
+ }
+
+ virtual ~Polygon() {}
+
+ //
+ // Accessors
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline const vector<Point>& getVertices() const
+ {
+ return _vertices;
+ }
+
+ inline void getBBox(Point& min, Point& max) const
+ {
+ min = _min;
+ max = _max;
+ }
+
+ inline Point& getBBoxCenter()
+ {
+ Point result;
+ result = (_min + _max) / 2;
+ return result;
+ }
+
+ inline Point& getCenter()
+ {
+ Point result;
+ for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++)
+ result += *it;
+ result /= _vertices.size();
+ return result;
+ }
+
+ inline unsigned getId() const
+ {
+ return _id;
+ }
+
+ //
+ // Modifiers
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline void setVertices(const vector<Point>& vertices)
+ {
+ _vertices.clear();
+ Point p;
+ for (typename vector<Point>::const_iterator it = vertices.begin(); it != vertices.end(); it++) {
+ p = *it;
+ _vertices.push_back(p);
+ }
+ computeBBox();
+ }
+
+ inline void setId(unsigned id)
+ {
+ _id = id;
+ }
+
+ //
+ // Other methods
+ //
+ /////////////////////////////////////////////////////////////////////////////
+ inline void computeBBox()
+ {
+ if (_vertices.empty())
+ return;
+
+ _max = _vertices[0];
+ _min = _vertices[0];
+
+ for (typename vector<Point>::iterator it = _vertices.begin(); it != _vertices.end(); it++) {
+ for (unsigned int i = 0; i < Point::dim(); i++) {
+ if ((*it)[i] > _max[i])
+ _max[i] = (*it)[i];
+ if ((*it)[i] < _min[i])
+ _min[i] = (*it)[i];
+ }
+ }
+ }
+
+ // FIXME Is it possible to get rid of userdatas ?
+ void* userdata;
+ void* userdata2; // Used during ray casting
+
+protected:
+ vector<Point> _vertices;
+ Point _min;
+ Point _max;
+ unsigned _id;
};
@@ -171,44 +177,45 @@ class Polygon
// Polygon3r class
//
///////////////////////////////////////////////////////////////////////////////
-
class Polygon3r : public Polygon<Vec3r>
{
- public:
- inline Polygon3r() : Polygon<Vec3r>() {}
-
- inline Polygon3r(const vector<Vec3r>& vertices,
- const Vec3r& normal) : Polygon<Vec3r>(vertices) {
- setNormal(normal);
- }
-
- inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
-
- virtual ~Polygon3r() {}
-
- void setNormal(const Vec3r& normal) {
- _normal = normal;
- }
-
- inline Vec3r getNormal() const {
- return _normal;
- }
-
- /*! Check whether the Polygon intersects with the ray or not */
- inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir,
- real& t, real& u, real& v, real epsilon = M_EPSILON) const {
- // if (_vertices.size() < 3)
- // return false;
- return GeomUtils::intersectRayTriangle(orig, dir,
- _vertices[0], _vertices[1], _vertices[2],
- t, u, v, epsilon);
- }
-
- private:
-
- Vec3r _normal;
+public:
+ inline Polygon3r() : Polygon<Vec3r>() {}
+
+ inline Polygon3r(const vector<Vec3r>& vertices, const Vec3r& normal) : Polygon<Vec3r>(vertices)
+ {
+ setNormal(normal);
+ }
+
+ inline Polygon3r(const Polygon3r& poly) : Polygon<Vec3r>(poly), _normal(poly._normal) {}
+
+ virtual ~Polygon3r() {}
+
+ void setNormal(const Vec3r& normal)
+ {
+ _normal = normal;
+ }
+
+ inline Vec3r getNormal() const
+ {
+ return _normal;
+ }
+
+ /*! Check whether the Polygon intersects with the ray or not */
+ inline bool rayIntersect(const Vec3r& orig, const Vec3r& dir, real& t, real& u, real& v,
+ real epsilon = M_EPSILON) const
+ {
+#if 0
+ if (_vertices.size() < 3)
+ return false;
+#endif
+ return GeomUtils::intersectRayTriangle(orig, dir, _vertices[0], _vertices[1], _vertices[2], t, u, v, epsilon);
+ }
+
+private:
+ Vec3r _normal;
};
} // end of namespace Geometry
-#endif // POLYGON_H
+#endif // __POLYGON_H__
diff --git a/source/blender/freestyle/intern/geometry/SweepLine.h b/source/blender/freestyle/intern/geometry/SweepLine.h
index deecf3c5485..df73df155c4 100644
--- a/source/blender/freestyle/intern/geometry/SweepLine.h
+++ b/source/blender/freestyle/intern/geometry/SweepLine.h
@@ -1,198 +1,202 @@
-//
-// Filename : SweepLine.h
-// Author(s) : Stephane Grabli
-// Purpose : Class to define a Sweep Line
-// Date of creation : 29/08/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 SWEEPLINE_H
-# define SWEEPLINE_H
-
-# include <list>
-# include <vector>
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __SWEEPLINE_H__
+#define __SWEEPLINE_H__
+
+/** \file blender/freestyle/intern/geometry/SweepLine.h
+ * \ingroup freestyle
+ * \brief Class to define a Sweep Line
+ * \author Stephane Grabli
+ * \date 29/08/2002
+ */
+
+#include <list>
+#include <vector>
/*! Class to define the intersection berween two segments*/
template<class Edge>
class Intersection
{
public:
-
- template<class EdgeClass>
- Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
- {
- EdgeA = eA;
- EdgeB = eB;
- tA = ta;
- tB = tb;
- userdata = 0;
- }
-
- Intersection(const Intersection& iBrother)
- {
- EdgeA = iBrother.EdgeA;
- EdgeB = iBrother.EdgeB;
- tA = iBrother.tA;
- tB = iBrother.tB;
- userdata = 0;
- }
-
- /*! returns the parameter giving the
- * intersection, for the edge iEdge
- */
- real getParameter(Edge *iEdge)
- {
- if(iEdge == EdgeA)
- return tA;
- if(iEdge == EdgeB)
- return tB;
- return 0;
- }
+ template<class EdgeClass>
+ Intersection(EdgeClass* eA, real ta, EdgeClass* eB, real tb)
+ {
+ EdgeA = eA;
+ EdgeB = eB;
+ tA = ta;
+ tB = tb;
+ userdata = 0;
+ }
+
+ Intersection(const Intersection& iBrother)
+ {
+ EdgeA = iBrother.EdgeA;
+ EdgeB = iBrother.EdgeB;
+ tA = iBrother.tA;
+ tB = iBrother.tB;
+ userdata = 0;
+ }
+
+ /*! returns the parameter giving the intersection, for the edge iEdge */
+ real getParameter(Edge *iEdge)
+ {
+ if (iEdge == EdgeA)
+ return tA;
+ if (iEdge == EdgeB)
+ return tB;
+ return 0;
+ }
public:
- void * userdata; // FIXME
+ void * userdata; // FIXME
- Edge *EdgeA; // first segment
- Edge *EdgeB; // second segment
- real tA; // parameter defining the intersection point with respect to the segment EdgeA.
- real tB; // parameter defining the intersection point with respect to the segment EdgeB.
+ Edge *EdgeA; // first segment
+ Edge *EdgeB; // second segment
+ real tA; // parameter defining the intersection point with respect to the segment EdgeA.
+ real tB; // parameter defining the intersection point with respect to the segment EdgeB.
};
-
-
-
-
-
-
template<class T, class Point>
class Segment
{
- public:
- Segment()
- {
- }
- Segment(T& s, const Point& iA, const Point& iB)
- {
- _edge = s;
- if(iA < iB)
- {
- A = iA;
- B = iB;
- _order = true;
- }
- else
- {
- A = iB;
- B = iA;
- _order = false;
- }
- }
-
- Segment(Segment<T,Point>& iBrother)
- {
- _edge = iBrother.edge();
- A = iBrother.A;
- B = iBrother.B;
- _Intersections = iBrother._Intersections;
- _order = iBrother._order;
- }
-
- Segment(const Segment<T,Point>& iBrother)
- {
- _edge = iBrother._edge;
- A = iBrother.A;
- B = iBrother.B;
- _Intersections = iBrother._Intersections;
- _order = iBrother._order;
- }
-
- ~Segment() {
- _Intersections.clear();
- }
-
- inline Point operator[](const unsigned short int& i) const
- {
- return i%2==0 ? A : B;
- }
-
- inline bool operator==(const Segment<T,Point>& iBrother)
- {
- if(_edge == iBrother._edge)
- return true;
-
- return false;
- }
-
- /* Adds an intersection for this segment */
- inline void AddIntersection(Intersection<Segment<T,Point> > *i) {_Intersections.push_back(i);}
-
- /*! Checks for a common vertex with another edge */
- inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
- {
- if((A == S[0]) || (A == S[1]))
- {
- CP = A;
- return true;
- }
- if((B == S[0]) || (B == S[1]))
- {
- CP = B;
- return true;
- }
-
- return false;
- }
-
- inline vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
- inline bool order() {return _order;}
- inline T& edge() {return _edge;}
-
- private:
- T _edge;
- Point A;
- Point B;
- std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
- bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
+public:
+ Segment()
+ {
+ }
+
+ Segment(T& s, const Point& iA, const Point& iB)
+ {
+ _edge = s;
+ if (iA < iB) {
+ A = iA;
+ B = iB;
+ _order = true;
+ }
+ else {
+ A = iB;
+ B = iA;
+ _order = false;
+ }
+ }
+
+ Segment(Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother.edge();
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ Segment(const Segment<T,Point>& iBrother)
+ {
+ _edge = iBrother._edge;
+ A = iBrother.A;
+ B = iBrother.B;
+ _Intersections = iBrother._Intersections;
+ _order = iBrother._order;
+ }
+
+ ~Segment()
+ {
+ _Intersections.clear();
+ }
+
+ inline Point operator[](const unsigned short int& i) const
+ {
+ return (i % 2 == 0) ? A : B;
+ }
+
+ inline bool operator==(const Segment<T,Point>& iBrother)
+ {
+ if (_edge == iBrother._edge)
+ return true;
+ return false;
+ }
+
+ /* Adds an intersection for this segment */
+ inline void AddIntersection(Intersection<Segment<T,Point> > *i)
+ {
+ _Intersections.push_back(i);
+ }
+
+ /*! Checks for a common vertex with another edge */
+ inline bool CommonVertex(const Segment<T,Point>& S, Point& CP)
+ {
+ if ((A == S[0]) || (A == S[1])) {
+ CP = A;
+ return true;
+ }
+ if ((B == S[0]) || (B == S[1])) {
+ CP = B;
+ return true;
+ }
+ return false;
+ }
+
+ inline vector<Intersection<Segment<T,Point> >*>& intersections()
+ {
+ return _Intersections;
+ }
+
+ inline bool order()
+ {
+ return _order;
+ }
+
+ inline T& edge()
+ {
+ return _edge;
+ }
+
+private:
+ T _edge;
+ Point A;
+ Point B;
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // list of intersections parameters
+ bool _order; // true if A and B are in the same order than _edge.A and _edge.B. false otherwise.
};
-/*! defines a binary function that can be overload
- * by the user to specify at each condition
- * the intersection between 2 edges must be computed
+/*! defines a binary function that can be overload by the user to specify at each condition the intersection
+ * between 2 edges must be computed
*/
template<class T1, class T2>
-struct binary_rule
+struct binary_rule
{
- binary_rule() {}
- template<class T3,class T4>
- binary_rule(const binary_rule<T3,T4>& brother) {}
- virtual ~binary_rule() {}
-
- virtual bool operator()(T1&, T2&)
- {
- return true;
- }
+ binary_rule() {}
+ template<class T3,class T4> binary_rule(const binary_rule<T3,T4>& brother) {}
+ virtual ~binary_rule() {}
+
+ virtual bool operator()(T1&, T2&)
+ {
+ return true;
+ }
};
@@ -200,126 +204,121 @@ template<class T,class Point>
class SweepLine
{
public:
-
- SweepLine() {}
- ~SweepLine()
- {
- for(typename vector<Intersection<Segment<T,Point> >*>::iterator i=_Intersections.begin(),iend=_Intersections.end();
- i!=iend;
- i++)
- {
- delete (*i);
- }
- }
-
-
- inline void process(Point& p,
- vector<Segment<T,Point>*>& segments,
- binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
- //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>,Segment<T,Point> >(),
- real epsilon = M_EPSILON
- )
- {
- // first we remove the segments that need to be removed and then
- // we add the segments to add
- vector<Segment<T,Point>*> toadd;
- typename vector<Segment<T,Point>*>::iterator s, send;
- for(s=segments.begin(), send=segments.end();
- s!=send;
- s++)
- {
- if(p == (*(*s))[0])
- toadd.push_back((*s));
- else
- remove((*s));
- }
- for(s=toadd.begin(), send=toadd.end();
- s!=send;
- s++)
- {
- add((*s), binrule, epsilon);
- }
- }
-
- inline void add(Segment<T,Point>* S,
- binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
- //binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = binary_rule<Segment<T,Point>, Segment<T,Point> >(),
- real epsilon
- )
- {
- real t,u;
- Point CP;
- Vec2r v0, v1, v2, v3;
- if(true == S->order())
- {
- v0[0] = ((*S)[0])[0];
- v0[1] = ((*S)[0])[1];
- v1[0] = ((*S)[1])[0];
- v1[1] = ((*S)[1])[1];
- }
- else
- {
- v1[0] = ((*S)[0])[0];
- v1[1] = ((*S)[0])[1];
- v0[0] = ((*S)[1])[0];
- v0[1] = ((*S)[1])[1];
- }
- for(typename std::list<Segment<T,Point>* >::iterator s=_set.begin(), send=_set.end();
- s!=send;
- s++)
- {
- Segment<T,Point>* currentS = (*s);
- if(true != binrule(*S, *currentS))
- continue;
-
- if(true == currentS->order())
- {
- v2[0] = ((*currentS)[0])[0];
- v2[1] = ((*currentS)[0])[1];
- v3[0] = ((*currentS)[1])[0];
- v3[1] = ((*currentS)[1])[1];
- }
- else
- {
- v3[0] = ((*currentS)[0])[0];
- v3[1] = ((*currentS)[0])[1];
- v2[0] = ((*currentS)[1])[0];
- v2[1] = ((*currentS)[1])[1];
- }
- if(S->CommonVertex(*currentS, CP))
- continue; // the two edges have a common vertex->no need to check
-
- if(GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT)
- {
- // create the intersection
- Intersection<Segment<T,Point> > * inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
- // add it to the intersections list
- _Intersections.push_back(inter);
- // add this intersection to the first edge intersections list
- S->AddIntersection(inter);
- // add this intersection to the second edge intersections list
- currentS->AddIntersection(inter);
- }
- }
- // add the added segment to the list of active segments
- _set.push_back(S);
- }
-
- inline void remove(Segment<T,Point>* s)
- {
- if(s->intersections().size() > 0)
- _IntersectedEdges.push_back(s);
- _set.remove(s);
- }
-
- vector<Segment<T,Point>* >& intersectedEdges() {return _IntersectedEdges;}
- vector<Intersection<Segment<T,Point> >*>& intersections() {return _Intersections;}
-
+ SweepLine() {}
+ ~SweepLine()
+ {
+ for (typename vector<Intersection<Segment<T,Point> >*>::iterator i = _Intersections.begin(),
+ iend = _Intersections.end();
+ i != iend;
+ i++)
+ {
+ delete (*i);
+ }
+ }
+
+ inline void process(Point& p, vector<Segment<T,Point>*>& segments,
+#if 0
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = \
+ binary_rule<Segment<T,Point>,Segment<T,Point> >(),
+#else
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+#endif
+ real epsilon = M_EPSILON)
+ {
+ // first we remove the segments that need to be removed and then we add the segments to add
+ vector<Segment<T,Point>*> toadd;
+ typename vector<Segment<T,Point>*>::iterator s, send;
+ for (s = segments.begin(), send = segments.end(); s != send; s++) {
+ if (p == (*(*s))[0])
+ toadd.push_back((*s));
+ else
+ remove((*s));
+ }
+ for (s = toadd.begin(), send = toadd.end(); s != send; s++) {
+ add((*s), binrule, epsilon);
+ }
+ }
+
+ inline void add(Segment<T,Point>* S,
+#if 0
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule = \
+ binary_rule<Segment<T,Point>, Segment<T,Point> >(),
+#else
+ binary_rule<Segment<T,Point>,Segment<T,Point> >& binrule,
+#endif
+ real epsilon)
+ {
+ real t,u;
+ Point CP;
+ Vec2r v0, v1, v2, v3;
+ if (true == S->order()) {
+ v0[0] = ((*S)[0])[0];
+ v0[1] = ((*S)[0])[1];
+ v1[0] = ((*S)[1])[0];
+ v1[1] = ((*S)[1])[1];
+ }
+ else {
+ v1[0] = ((*S)[0])[0];
+ v1[1] = ((*S)[0])[1];
+ v0[0] = ((*S)[1])[0];
+ v0[1] = ((*S)[1])[1];
+ }
+ for (typename std::list<Segment<T,Point>* >::iterator s = _set.begin(), send = _set.end(); s != send; s++) {
+ Segment<T,Point>* currentS = (*s);
+ if (true != binrule(*S, *currentS))
+ continue;
+
+ if (true == currentS->order()) {
+ v2[0] = ((*currentS)[0])[0];
+ v2[1] = ((*currentS)[0])[1];
+ v3[0] = ((*currentS)[1])[0];
+ v3[1] = ((*currentS)[1])[1];
+ }
+ else {
+ v3[0] = ((*currentS)[0])[0];
+ v3[1] = ((*currentS)[0])[1];
+ v2[0] = ((*currentS)[1])[0];
+ v2[1] = ((*currentS)[1])[1];
+ }
+ if (S->CommonVertex(*currentS, CP))
+ continue; // the two edges have a common vertex->no need to check
+
+ if (GeomUtils::intersect2dSeg2dSegParametric(v0, v1, v2, v3, t, u, epsilon) == GeomUtils::DO_INTERSECT) {
+ // create the intersection
+ Intersection<Segment<T,Point> > *inter = new Intersection<Segment<T,Point> >(S,t,currentS,u);
+ // add it to the intersections list
+ _Intersections.push_back(inter);
+ // add this intersection to the first edge intersections list
+ S->AddIntersection(inter);
+ // add this intersection to the second edge intersections list
+ currentS->AddIntersection(inter);
+ }
+ }
+ // add the added segment to the list of active segments
+ _set.push_back(S);
+ }
+
+ inline void remove(Segment<T,Point>* s)
+ {
+ if (s->intersections().size() > 0)
+ _IntersectedEdges.push_back(s);
+ _set.remove(s);
+ }
+
+ vector<Segment<T,Point>* >& intersectedEdges()
+ {
+ return _IntersectedEdges;
+ }
+
+ vector<Intersection<Segment<T,Point> >*>& intersections()
+ {
+ return _Intersections;
+ }
private:
- std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
- std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
- std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
+ std::list<Segment<T,Point>* > _set; // set of active edges for a given position of the sweep line
+ std::vector<Segment<T,Point>* > _IntersectedEdges; // the list of intersected edges
+ std::vector<Intersection<Segment<T,Point> >*> _Intersections; // the list of all intersections.
};
-#endif // SWEEPLINE_H
+#endif // __SWEEPLINE_H__
diff --git a/source/blender/freestyle/intern/geometry/VecMat.h b/source/blender/freestyle/intern/geometry/VecMat.h
index 9bbec3b1349..5b64a6e4502 100644
--- a/source/blender/freestyle/intern/geometry/VecMat.h
+++ b/source/blender/freestyle/intern/geometry/VecMat.h
@@ -1,899 +1,976 @@
+/*
+ * ***** 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.
+ *
+ * The Original Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is: all of this file.
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
+
+#ifndef __VECMAT_H__
+#define __VECMAT_H__
+
+/** \file blender/freestyle/intern/geometry/VecMat.h
+ * \ingroup freestyle
+ * \brief Vectors and Matrices definition and manipulation
+ * \author Sylvain Paris
+ * \author Emmanuel Turquin
+ * \author Stephane Grabli
+ * \date 12/06/2003
+ */
+
+#include <iostream>
+#include <math.h>
+#include <vector>
+
+namespace VecMat {
+
+namespace Internal {
+ template <bool B>
+ struct is_false {};
+
+ template <>
+ struct is_false<false>
+ {
+ static inline void ensure() {}
+ };
+} // end of namespace Internal
+
//
-// Filename : VecMat.h
-// Author(s) : Sylvain Paris
-// Emmanuel Turquin
-// Stephane Grabli
-// Purpose : Vectors and Matrices definition and manipulation
-// Date of creation : 12/06/2003
+// Vector class
+// - T: value type
+// - N: dimension
//
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T, unsigned N>
+class Vec
+{
+public:
+ typedef T value_type;
+
+ // constructors
+ inline Vec()
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Vec()
+ {
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Vec(const U tab[N])
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const std::vector<U>& tab)
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)tab[i];
+ }
+
+ template <class U>
+ explicit inline Vec(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+
+ // accessors
+ inline value_type operator[](const unsigned i) const
+ {
+ return this->_coord[i];
+ }
+
+ inline value_type& operator[](const unsigned i)
+ {
+ return this->_coord[i];
+ }
+
+ static inline unsigned dim()
+ {
+ return N;
+ }
+
+ // various useful methods
+ inline value_type norm() const
+ {
+ return (T)sqrt((float)squareNorm());
+ }
+
+ inline value_type squareNorm() const
+ {
+ return (*this) * (*this);
+ }
+
+ inline Vec<T, N>& normalize()
+ {
+ value_type n = norm();
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ return *this;
+ }
+
+ inline Vec<T, N>& normalizeSafe()
+ {
+ value_type n = norm();
+ if (n) {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] /= n;
+ }
+ return *this;
+ }
+
+ // classical operators
+ inline Vec<T, N> operator+(const Vec<T, N>& v) const
+ {
+ Vec<T, N> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec<T, N> operator-(const Vec<T,N>& v) const
+ {
+ Vec<T, N> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const
+ {
+ Vec<T, N> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const
+ {
+ Vec<T, N> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec<T, N>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < N; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator=(const Vec<U, N>& v)
+ {
+ if (this != &v) {
+ for (unsigned int i = 0; i < N; i++)
+ this->_coord[i] = (T)v[i];
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator+=(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] += (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator-=(const Vec<U, N>& v)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] -= (T)v[i];
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator*=(const U r)
+ {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] *= r;
+ return *this;
+ }
+
+ template <class U>
+ inline Vec<T, N>& operator/=(const U r)
+ {
+ if (r) {
+ for (unsigned int i = 0 ; i < N; i++)
+ this->_coord[i] /= r;
+ }
+ return *this;
+ }
+
+ inline bool operator==(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] != v[i])
+ return false;
+ }
+ return true;
+ }
+
+ inline bool operator!=(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] != v[i])
+ return true;
+ }
+ return false;
+ }
+
+ inline bool operator<(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] < v[i])
+ return true;
+ if (this->_coord[i] > v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+ inline bool operator>(const Vec<T, N>& v) const
+ {
+ for (unsigned int i = 0; i < N; i++) {
+ if (this->_coord[i] > v[i])
+ return true;
+ if (this->_coord[i] < v[i])
+ return false;
+ if (this->_coord[i] == v[i])
+ continue;
+ }
+ return false;
+ }
+
+protected:
+ value_type _coord[N];
+ enum {
+ _dim = N,
+ };
+};
//
-// Copyright (C) : Please refer to the COPYRIGHT file distributed
-// with this source distribution.
+// Vec2 class (2D Vector)
+// - T: value type
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+class Vec2 : public Vec<T, 2>
+{
+public:
+ typedef typename Vec<T, 2>::value_type value_type;
+
+ inline Vec2() : Vec<T, 2>() {}
+
+ template <class U>
+ explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
+
+ template <class U>
+ inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
+
+ inline Vec2(const value_type x, const value_type y = 0) : Vec<T, 2>()
+ {
+ this->_coord[0] = (T)x;
+ this->_coord[1] = (T)y;
+ }
+
+ inline value_type x() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& x()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& y()
+ {
+ return this->_coord[1];
+ }
+
+ inline void setX(const value_type v)
+ {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v)
+ {
+ this->_coord[1] = v;
+ }
+
+ // FIXME: hack swig -- no choice
+ inline Vec2<T> operator+(const Vec2<T>& v) const
+ {
+ Vec2<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec2<T> operator-(const Vec2<T>& v) const
+ {
+ Vec2<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec2<T> operator*(const value_type r) const
+ {
+ Vec2<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec2<T> operator/(const value_type r) const
+ {
+ Vec2<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec2<T>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < 2; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+};
+
+
//
-// 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.
+// HVec3 class (3D Vector in homogeneous coordinates)
+// - T: value type
//
-// 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.
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T>
+class HVec3 : public Vec<T, 4>
+{
+public:
+ typedef typename Vec<T, 4>::value_type value_type;
+
+ inline HVec3() : Vec<T, 4>() {}
+
+ template <class U>
+ explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
+
+ template <class U>
+ explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
+
+ template<class U>
+ inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
+
+ inline HVec3(const value_type sx, const value_type sy = 0, const value_type sz = 0, const value_type s = 1)
+ {
+ this->_coord[0] = sx;
+ this->_coord[1] = sy;
+ this->_coord[2] = sz;
+ this->_coord[3] = s;
+ }
+
+ template <class U>
+ inline HVec3(const Vec<U, 3>& sv, const U s = 1)
+ {
+ this->_coord[0] = (T)sv[0];
+ this->_coord[1] = (T)sv[1];
+ this->_coord[2] = (T)sv[2];
+ this->_coord[3] = (T)s;
+ }
+
+ inline value_type sx() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& sx()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type sy() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& sy(){
+ return this->_coord[1];
+ }
+
+ inline value_type sz() const
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type& sz()
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type s() const
+ {
+ return this->_coord[3];
+ }
+
+ inline value_type& s()
+ {
+ return this->_coord[3];
+ }
+
+ // Acces to non-homogeneous coordinates in 3D
+ inline value_type x() const
+ {
+ return this->_coord[0] / this->_coord[3];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1] / this->_coord[3];
+ }
+
+ inline value_type z() const
+ {
+ return this->_coord[2] / this->_coord[3];
+ }
+};
+
+
//
-// 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.
+// Vec3 class (3D Vec)
+// - T: value type
//
-///////////////////////////////////////////////////////////////////////////////
+/////////////////////////////////////////////////////////////////////////////
+template <class T>
+class Vec3 : public Vec<T, 3>
+{
+public:
+ typedef typename Vec<T, 3>::value_type value_type;
+
+ inline Vec3() : Vec<T, 3>() {}
+
+ template <class U>
+ explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
+
+ template <class U>
+ explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
+
+ template<class U>
+ inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
+
+ template<class U>
+ inline Vec3(const HVec3<U>& v)
+ {
+ this->_coord[0] = (T)v.x();
+ this->_coord[1] = (T)v.y();
+ this->_coord[2] = (T)v.z();
+ }
+
+ inline Vec3(const value_type x, const value_type y = 0, const value_type z = 0) : Vec<T, 3>()
+ {
+ this->_coord[0] = x;
+ this->_coord[1] = y;
+ this->_coord[2] = z;
+ }
+
+ inline value_type x() const
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type& x()
+ {
+ return this->_coord[0];
+ }
+
+ inline value_type y() const
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type& y()
+ {
+ return this->_coord[1];
+ }
+
+ inline value_type z() const
+ {
+ return this->_coord[2];
+ }
+
+ inline value_type& z()
+ {
+ return this->_coord[2];
+ }
+
+ inline void setX(const value_type v)
+ {
+ this->_coord[0] = v;
+ }
+
+ inline void setY(const value_type v)
+ {
+ this->_coord[1] = v;
+ }
+
+ inline void setZ(const value_type v)
+ {
+ this->_coord[2] = v;
+ }
+
+ // classical operators
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator+(const Vec3<T>& v) const
+ {
+ Vec3<T> res(v);
+ res += *this;
+ return res;
+ }
+
+ inline Vec3<T> operator-(const Vec3<T>& v) const
+ {
+ Vec3<T> res(*this);
+ res -= v;
+ return res;
+ }
+
+ inline Vec3<T> operator*(const value_type r) const
+ {
+ Vec3<T> res(*this);
+ res *= r;
+ return res;
+ }
+
+ inline Vec3<T> operator/(const value_type r) const
+ {
+ Vec3<T> res(*this);
+ if (r)
+ res /= r;
+ return res;
+ }
+
+ // dot product
+ inline value_type operator*(const Vec3<T>& v) const
+ {
+ value_type sum = 0;
+ for (unsigned int i = 0; i < 3; i++)
+ sum += (*this)[i] * v[i];
+ return sum;
+ }
+
+ // cross product for 3D Vectors
+ // FIXME: hack swig -- no choice
+ inline Vec3<T> operator^(const Vec3<T>& v) const
+ {
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+
+ // cross product for 3D Vectors
+ template <typename U>
+ inline Vec3<T> operator^(const Vec<U, 3>& v) const
+ {
+ Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
+ (*this)[2] * v[0] - (*this)[0] * v[2],
+ (*this)[0] * v[1] - (*this)[1] * v[0]);
+ return res;
+ }
+};
-#ifndef VECMAT_H
-# define VECMAT_H
-# include <math.h>
-# include <vector>
-# include <iostream>
+//
+// Matrix class
+// - T: value type
+// - M: rows
+// - N: cols
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Dirty, but icc under Windows needs this
+#define _SIZE (M * N)
+
+template <class T, unsigned M, unsigned N>
+class Matrix
+{
+public:
+ typedef T value_type;
+
+ inline Matrix()
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = 0;
+ }
+
+ ~Matrix()
+ {
+ Internal::is_false<(M == 0)>::ensure();
+ Internal::is_false<(N == 0)>::ensure();
+ }
+
+ template <class U>
+ explicit inline Matrix(const U tab[_SIZE])
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ explicit inline Matrix(const std::vector<U>& tab)
+ {
+ for (unsigned int i = 0; i < _SIZE; i++)
+ this->_coord[i] = tab[i];
+ }
+
+ template <class U>
+ inline Matrix(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+ }
+
+ inline value_type operator()(const unsigned i, const unsigned j) const
+ {
+ return this->_coord[i * N + j];
+ }
+
+ inline value_type& operator()(const unsigned i, const unsigned j)
+ {
+ return this->_coord[i * N + j];
+ }
+
+ static inline unsigned rows()
+ {
+ return M;
+ }
+
+ static inline unsigned cols()
+ {
+ return N;
+ }
+
+ inline Matrix<T, M, N>& transpose() const
+ {
+ Matrix<T, N, M> res;
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ res(j, i) = this->_coord[i * N + j];
+ }
+ return res;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m)
+ {
+ if (this != &m) {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] = (T)m(i, j);
+ }
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] += (T)m(i, j);
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] -= (T)m(i, j);
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator*=(const U lambda)
+ {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] *= lambda;
+ }
+ return *this;
+ }
+
+ template <class U>
+ inline Matrix<T, M, N>& operator/=(const U lambda)
+ {
+ if (lambda) {
+ for (unsigned int i = 0; i < M; i++) {
+ for (unsigned int j = 0; j < N; j++)
+ this->_coord[i * N + j] /= lambda;
+ }
+ }
+ return *this;
+ }
+
+protected:
+ value_type _coord[_SIZE];
+};
+
+#undef _SIZE
-namespace VecMat {
+//
+// SquareMatrix class
+// - T: value type
+// - N: rows & cols
+//
+/////////////////////////////////////////////////////////////////////////////
+
+// Dirty, but icc under Windows needs this
+#define _SIZE (N * N)
+
+template <class T, unsigned N>
+class SquareMatrix : public Matrix<T, N, N>
+{
+public:
+ typedef T value_type;
+
+ inline SquareMatrix() : Matrix<T, N, N>() {}
+
+ template <class U>
+ explicit inline SquareMatrix(const U tab[_SIZE]) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
+
+ template <class U>
+ inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
- namespace Internal {
-
- template <bool B>
- struct is_false {};
-
- template <>
- struct is_false<false> {
- static inline void ensure() {}
- };
-
- } // end of namespace Internal
-
- //
- // Vector class
- // - T: value type
- // - N: dimension
- //
- /////////////////////////////////////////////////////////////////////////////
-
- template <class T, unsigned N>
- class Vec
- {
- public:
-
- typedef T value_type;
-
- // constructors
-
- inline Vec() {
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] = 0;
- }
-
- ~Vec() {
- Internal::is_false<(N == 0)>::ensure();
- }
-
- template <class U>
- explicit inline Vec(const U tab[N]) {
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] = (T)tab[i];
- }
-
- template <class U>
- explicit inline Vec(const std::vector<U>& tab) {
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] = (T)tab[i];
- }
-
- template <class U>
- explicit inline Vec(const Vec<U, N>& v) {
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] = (T)v[i];
- }
-
- // accessors
-
- inline value_type operator[](const unsigned i) const {
- return this->_coord[i];
- }
-
- inline value_type& operator[](const unsigned i) {
- return this->_coord[i];
- }
-
- static inline unsigned dim() {
- return N;
- }
-
- // various useful methods
-
- inline value_type norm() const {
- return (T)sqrt((float)squareNorm());
- }
-
- inline value_type squareNorm() const {
- return (*this) * (*this);
- }
-
- inline Vec<T, N>& normalize() {
- value_type n = norm();
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] /= n;
- return *this;
- }
-
- inline Vec<T, N>& normalizeSafe() {
- value_type n = norm();
- if (n)
- for (unsigned i=0; i < N; i++)
- this->_coord[i] /= n;
- return *this;
- }
-
- // classical operators
- inline Vec<T, N> operator+(const Vec<T, N>& v) const{
- Vec<T, N> res(v);
- res += *this;
- return res;
- }
-
- inline Vec<T, N> operator-(const Vec<T,N>& v) const{
- Vec<T, N> res(*this);
- res -= v;
- return res;
- }
-
- inline Vec<T, N> operator*(const typename Vec<T,N>::value_type r) const{
- Vec<T, N> res(*this);
- res *= r;
- return res;
- }
-
- inline Vec<T, N> operator/(const typename Vec<T,N>::value_type r) const{
- Vec<T, N> res(*this);
- if (r)
- res /= r;
- return res;
- }
-
- // dot product
- inline value_type operator*(const Vec<T, N>& v) const{
- value_type sum = 0;
- for (unsigned i = 0; i < N; i++)
- sum += (*this)[i] * v[i];
- return sum;
- }
-
- template <class U>
- inline Vec<T, N>& operator=(const Vec<U, N>& v) {
- if (this != &v)
- for (unsigned i = 0; i < N; i++)
- this->_coord[i] = (T)v[i];
- return *this;
- }
-
- template <class U>
- inline Vec<T, N>& operator+=(const Vec<U, N>& v) {
- for (unsigned i = 0 ; i < N; i++)
- this->_coord[i] += (T)v[i];
- return *this;
- }
-
- template <class U>
- inline Vec<T, N>& operator-=(const Vec<U, N>& v) {
- for (unsigned i = 0 ; i < N; i++)
- this->_coord[i] -= (T)v[i];
- return *this;
- }
-
- template <class U>
- inline Vec<T, N>& operator*=(const U r) {
- for (unsigned i = 0 ; i < N; i++)
- this->_coord[i] *= r;
- return *this;
- }
-
- template <class U>
- inline Vec<T, N>& operator/=(const U r) {
- if (r)
- for (unsigned i = 0 ; i < N; i++)
- this->_coord[i] /= r;
- return *this;
- }
-
-
- inline bool operator==(const Vec<T, N>& v) const {
- for(unsigned i = 0; i < N; i++)
- if (this->_coord[i] != v[i])
- return false;
- return true;
- }
-
- inline bool operator!=(const Vec<T, N>& v) const {
- for(unsigned i = 0; i < N; i++)
- if (this->_coord[i] != v[i])
- return true;
- return false;
- }
-
- inline bool operator<(const Vec<T, N>& v) const {
- for (unsigned i = 0; i<N; i++) {
- if (this->_coord[i] < v[i])
- return true;
- if (this->_coord[i] > v[i])
- return false;
- if (this->_coord[i] == v[i])
- continue;
- }
- return false;
- }
-
- inline bool operator>(const Vec<T, N>& v) const {
- for (unsigned i=0; i<N; i++) {
- if(this->_coord[i] > v[i])
- return true;
- if(this->_coord[i] < v[i])
- return false;
- if(this->_coord[i] == v[i])
- continue;
- }
- return false;
- }
-
- protected:
-
- value_type _coord[N];
- enum {
- _dim = N,
- };
- };
-
-
- //
- // Vec2 class (2D Vector)
- // - T: value type
- //
- /////////////////////////////////////////////////////////////////////////////
-
- template <class T>
- class Vec2 : public Vec<T, 2>
- {
- public:
-
- typedef typename Vec<T, 2>::value_type value_type;
-
- inline Vec2() : Vec<T, 2>() {}
-
- template <class U>
- explicit inline Vec2(const U tab[2]) : Vec<T, 2>(tab) {}
-
- template <class U>
- explicit inline Vec2(const std::vector<U>& tab) : Vec<T, 2>(tab) {}
-
- template <class U>
- inline Vec2(const Vec<U, 2>& v) : Vec<T, 2>(v) {}
-
- inline Vec2(const value_type x,
- const value_type y = 0) : Vec<T, 2>() {
- this->_coord[0] = (T)x;
- this->_coord[1] = (T)y;
- }
-
- inline value_type x() const {
- return this->_coord[0];
- }
-
- inline value_type& x() {
- return this->_coord[0];
- }
-
- inline value_type y() const {
- return this->_coord[1];
- }
-
- inline value_type& y() {
- return this->_coord[1];
- }
-
- inline void setX(const value_type v) {
- this->_coord[0] = v;
- }
-
- inline void setY(const value_type v) {
- this->_coord[1] = v;
- }
-
- // FIXME: hack swig -- no choice
- inline Vec2<T> operator+(const Vec2<T>& v) const{
- Vec2<T> res(v);
- res += *this;
- return res;
- }
-
- inline Vec2<T> operator-(const Vec2<T>& v) const{
- Vec2<T> res(*this);
- res -= v;
- return res;
- }
-
- inline Vec2<T> operator*(const value_type r) const{
- Vec2<T> res(*this);
- res *= r;
- return res;
- }
-
- inline Vec2<T> operator/(const value_type r) const{
- Vec2<T> res(*this);
- if (r)
- res /= r;
- return res;
- }
-
- // dot product
- inline value_type operator*(const Vec2<T>& v) const{
- value_type sum = 0;
- for (unsigned i = 0; i < 2; i++)
- sum += (*this)[i] * v[i];
- return sum;
- }
- };
-
-
- //
- // HVec3 class (3D Vector in homogeneous coordinates)
- // - T: value type
- //
- /////////////////////////////////////////////////////////////////////////////
-
- template <class T>
- class HVec3 : public Vec<T, 4>
- {
- public:
-
- typedef typename Vec<T, 4>::value_type value_type;
-
- inline HVec3() : Vec<T, 4>() {}
-
- template <class U>
- explicit inline HVec3(const U tab[4]) : Vec<T, 4>(tab) {}
-
- template <class U>
- explicit inline HVec3(const std::vector<U>& tab) : Vec<T, 4>(tab) {}
-
- template<class U>
- inline HVec3(const Vec<U, 4>& v) : Vec<T, 4>(v) {}
-
- inline HVec3(const value_type sx,
- const value_type sy = 0,
- const value_type sz = 0,
- const value_type s = 1) {
- this->_coord[0] = sx;
- this->_coord[1] = sy;
- this->_coord[2] = sz;
- this->_coord[3] = s;
- }
-
- template <class U>
- inline HVec3(const Vec<U, 3>& sv,
- const U s = 1) {
- this->_coord[0] = (T)sv[0];
- this->_coord[1] = (T)sv[1];
- this->_coord[2] = (T)sv[2];
- this->_coord[3] = (T)s;
- }
-
- inline value_type sx() const {
- return this->_coord[0];
- }
-
- inline value_type& sx() {
- return this->_coord[0];
- }
-
- inline value_type sy() const {
- return this->_coord[1];
- }
-
- inline value_type& sy() {
- return this->_coord[1];
- }
-
- inline value_type sz() const {
- return this->_coord[2];
- }
-
- inline value_type& sz() {
- return this->_coord[2];
- }
-
- inline value_type s() const {
- return this->_coord[3];
- }
-
- inline value_type& s() {
- return this->_coord[3];
- }
-
- // Acces to non-homogeneous coordinates in 3D
-
- inline value_type x() const {
- return this->_coord[0] / this->_coord[3];
- }
-
- inline value_type y() const {
- return this->_coord[1] / this->_coord[3];
- }
-
- inline value_type z() const {
- return this->_coord[2] / this->_coord[3];
- }
- };
-
-
- //
- // Vec3 class (3D Vec)
- // - T: value type
- //
- /////////////////////////////////////////////////////////////////////////////
-
- template <class T>
- class Vec3 : public Vec<T, 3>
- {
- public:
-
- typedef typename Vec<T, 3>::value_type value_type;
-
- inline Vec3() : Vec<T, 3>() {}
-
- template <class U>
- explicit inline Vec3(const U tab[3]) : Vec<T, 3>(tab) {}
-
- template <class U>
- explicit inline Vec3(const std::vector<U>& tab) : Vec<T, 3>(tab) {}
-
- template<class U>
- inline Vec3(const Vec<U, 3>& v) : Vec<T, 3>(v) {}
-
- template<class U>
- inline Vec3(const HVec3<U>& v) {
- this->_coord[0] = (T)v.x();
- this->_coord[1] = (T)v.y();
- this->_coord[2] = (T)v.z();
- }
-
- inline Vec3(const value_type x,
- const value_type y = 0,
- const value_type z = 0) : Vec<T, 3>() {
- this->_coord[0] = x;
- this->_coord[1] = y;
- this->_coord[2] = z;
- }
-
- inline value_type x() const {
- return this->_coord[0];
- }
-
- inline value_type& x() {
- return this->_coord[0];
- }
-
- inline value_type y() const {
- return this->_coord[1];
- }
-
- inline value_type& y() {
- return this->_coord[1];
- }
-
- inline value_type z() const {
- return this->_coord[2];
- }
-
- inline value_type& z() {
- return this->_coord[2];
- }
-
- inline void setX(const value_type v) {
- this->_coord[0] = v;
- }
-
- inline void setY(const value_type v) {
- this->_coord[1] = v;
- }
-
- inline void setZ(const value_type v) {
- this->_coord[2] = v;
- }
-
- // classical operators
- // FIXME: hack swig -- no choice
- inline Vec3<T> operator+(const Vec3<T>& v) const{
- Vec3<T> res(v);
- res += *this;
- return res;
- }
-
- inline Vec3<T> operator-(const Vec3<T>& v) const{
- Vec3<T> res(*this);
- res -= v;
- return res;
- }
-
- inline Vec3<T> operator*(const value_type r) const{
- Vec3<T> res(*this);
- res *= r;
- return res;
- }
-
- inline Vec3<T> operator/(const value_type r) const{
- Vec3<T> res(*this);
- if (r)
- res /= r;
- return res;
- }
-
- // dot product
- inline value_type operator*(const Vec3<T>& v) const{
- value_type sum = 0;
- for (unsigned i = 0; i < 3; i++)
- sum += (*this)[i] * v[i];
- return sum;
- }
-
- // cross product for 3D Vectors
- // FIXME: hack swig -- no choice
- inline Vec3<T> operator^(const Vec3<T>& v) const{
- Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
- (*this)[2] * v[0] - (*this)[0] * v[2],
- (*this)[0] * v[1] - (*this)[1] * v[0]);
- return res;
- }
-
- // cross product for 3D Vectors
- template <typename U>
- inline Vec3<T> operator^(const Vec<U, 3>& v) const{
- Vec3<T> res((*this)[1] * v[2] - (*this)[2] * v[1],
- (*this)[2] * v[0] - (*this)[0] * v[2],
- (*this)[0] * v[1] - (*this)[1] * v[0]);
- return res;
- }
- };
-
-
- //
- // Matrix class
- // - T: value type
- // - M: rows
- // - N: cols
- //
- /////////////////////////////////////////////////////////////////////////////
-
- // Dirty, but icc under Windows needs this
-# define _SIZE (M * N)
-
- template <class T, unsigned M, unsigned N>
- class Matrix
- {
- public:
-
- typedef T value_type;
-
- inline Matrix() {
- for (unsigned i = 0; i < _SIZE; i++)
- this->_coord[i] = 0;
- }
-
- ~Matrix() {
- Internal::is_false<(M == 0)>::ensure();
- Internal::is_false<(N == 0)>::ensure();
- }
-
- template <class U>
- explicit inline Matrix(const U tab[_SIZE]) {
- for (unsigned i = 0; i < _SIZE; i++)
- this->_coord[i] = tab[i];
- }
-
- template <class U>
- explicit inline Matrix(const std::vector<U>& tab) {
- for (unsigned i = 0; i < _SIZE; i++)
- this->_coord[i] = tab[i];
- }
-
- template <class U>
- inline Matrix(const Matrix<U, M, N>& m) {
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] = (T)m(i, j);
- }
-
- inline value_type operator()(const unsigned i, const unsigned j) const {
- return this->_coord[i * N + j];
- }
-
- inline value_type& operator()(const unsigned i, const unsigned j) {
- return this->_coord[i * N + j];
- }
-
- static inline unsigned rows() {
- return M;
- }
-
- static inline unsigned cols() {
- return N;
- }
-
- inline Matrix<T, M, N>& transpose() const {
- Matrix<T, N, M> res;
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- res(j,i) = this->_coord[i * N + j];
- return res;
- }
-
- template <class U>
- inline Matrix<T, M, N>& operator=(const Matrix<U, M, N>& m) {
- if (this != &m)
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] = (T)m(i, j);
- return *this;
- }
-
- template <class U>
- inline Matrix<T, M, N>& operator+=(const Matrix<U, M, N>& m) {
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] += (T)m(i, j);
- return *this;
- }
-
- template <class U>
- inline Matrix<T, M, N>& operator-=(const Matrix<U, M, N>& m) {
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] -= (T)m(i, j);
- return *this;
- }
-
- template <class U>
- inline Matrix<T, M, N>& operator*=(const U lambda) {
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] *= lambda;
- return *this;
- }
-
- template <class U>
- inline Matrix<T, M, N>& operator/=(const U lambda) {
- if (lambda)
- for (unsigned i = 0; i < M; i++)
- for (unsigned j = 0; j < N; j++)
- this->_coord[i * N + j] /= lambda;
- return *this;
- }
-
- protected:
-
- value_type _coord[_SIZE];
- };
-
-
- //
- // SquareMatrix class
- // - T: value type
- // - N: rows & cols
- //
- /////////////////////////////////////////////////////////////////////////////
-
- // Dirty, but icc under Windows needs this
-# define __SIZE (N * N)
-
- template <class T, unsigned N>
- class SquareMatrix : public Matrix<T, N, N>
- {
- public:
-
- typedef T value_type;
-
- inline SquareMatrix() : Matrix<T, N, N>() {}
-
- template <class U>
- explicit inline SquareMatrix(const U tab[__SIZE]) : Matrix<T, N, N>(tab) {}
-
- template <class U>
- explicit inline SquareMatrix(const std::vector<U>& tab) : Matrix<T, N, N>(tab) {}
-
- template <class U>
- inline SquareMatrix(const Matrix<U, N, N>& m) : Matrix<T, N, N>(m) {}
-
- static inline SquareMatrix<T, N> identity() {
- SquareMatrix<T, N> res;
- for (unsigned i = 0; i < N; i++)
- res(i, i) = 1;
- return res;
- }
- };
-
-
- //
- // Vector external functions
- //
- /////////////////////////////////////////////////////////////////////////////
-
- // template <class T, unsigned N>
- // inline Vec<T, N> operator+(const Vec<T, N>& v1,
- // const Vec<T, N>& v2) {
- // Vec<T, N> res(v1);
- // res += v2;
- // return res;
- // }
- //
- // template <class T, unsigned N>
- // inline Vec<T, N> operator-(const Vec<T, N>& v1,
- // const Vec<T, N>& v2) {
- // Vec<T, N> res(v1);
- // res -= v2;
- // return res;
- // }
- // template <class T, unsigned N>
- // inline Vec<T, N> operator*(const Vec<T, N>& v,
- // const typename Vec<T, N>::value_type r) {
- // Vec<T, N> res(v);
- // res *= r;
- // return res;
- // }
-
- template <class T, unsigned N>
- inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r,
- const Vec<T, N>& v) {
- Vec<T, N> res(v);
- res *= r;
- return res;
- }
- //
- // template <class T, unsigned N>
- // inline Vec<T, N> operator/(const Vec<T, N>& v,
- // const typename Vec<T, N>::value_type r) {
- // Vec<T, N> res(v);
- // if (r)
- // res /= r;
- // return res;
- // }
- //
- // dot product
- // template <class T, unsigned N>
- // inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1,
- // const Vec<T, N>& v2) {
- // typename Vec<T, N>::value_type sum = 0;
- // for (unsigned i = 0; i < N; i++)
- // sum += v1[i] * v2[i];
- // return sum;
- // }
- //
- // // cross product for 3D Vectors
- // template <typename T>
- // inline Vec3<T> operator^(const Vec<T, 3>& v1,
- // const Vec<T, 3>& v2) {
- // Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1],
- // v1[2] * v2[0] - v1[0] * v2[2],
- // v1[0] * v2[1] - v1[1] * v2[0]);
- // return res;
- // }
-
- // stream operator
- template <class T, unsigned N>
- inline std::ostream& operator<<(std::ostream& s,
- const Vec<T, N>& v) {
- unsigned i;
- s << "[";
- for (i = 0; i < N - 1; i++)
- s << v[i] << ", ";
- s << v[i] << "]";
- return s;
- }
-
-
- //
- // Matrix external functions
- //
- /////////////////////////////////////////////////////////////////////////////
-
- template <class T, unsigned M, unsigned N>
- inline Matrix<T, M, N>
- operator+(const Matrix<T, M, N>& m1,
- const Matrix<T, M, N>& m2) {
- Matrix<T, M, N> res(m1);
- res += m2;
- return res;
- }
-
- template <class T, unsigned M, unsigned N>
- inline Matrix<T, M, N>
- operator-(const Matrix<T, M, N>& m1,
- const Matrix<T, M, N>& m2) {
- Matrix<T, M, N> res(m1);
- res -= m2;
- return res;
- }
-
- template <class T, unsigned M, unsigned N>
- inline Matrix<T, M, N>
- operator*(const Matrix<T, M, N>& m1,
- const typename Matrix<T, M, N>::value_type lambda) {
- Matrix<T, M, N> res(m1);
- res *= lambda;
- return res;
- }
-
- template <class T, unsigned M, unsigned N>
- inline Matrix<T, M, N>
- operator*(const typename Matrix<T, M, N>::value_type lambda,
- const Matrix<T, M, N>& m1) {
- Matrix<T, M, N> res(m1);
- res *= lambda;
- return res;
- }
-
- template <class T, unsigned M, unsigned N>
- inline Matrix<T, M, N>
- operator/(const Matrix<T, M, N>& m1,
- const typename Matrix<T, M, N>::value_type lambda) {
- Matrix<T, M, N> res(m1);
- res /= lambda;
- return res;
- }
-
- template <class T, unsigned M, unsigned N, unsigned P>
- inline Matrix<T, M, P>
- operator*(const Matrix<T, M, N>& m1,
- const Matrix<T, N, P>& m2) {
- unsigned i, j, k;
- Matrix<T, M, P> res;
- typename Matrix<T, N, P>::value_type scale;
-
- for (j = 0; j < P; j++) {
- for (k = 0; k < N; k++) {
- scale = m2(k, j);
- for (i = 0; i < N; i++)
- res(i, j) += m1(i, k) * scale;
- }
- }
- return res;
- }
-
- template <class T, unsigned M, unsigned N>
- inline Vec<T, M>
- operator*(const Matrix<T, M, N>& m,
- const Vec<T, N>& v) {
-
- Vec<T, M> res;
- typename Matrix<T, M, N>::value_type scale;
-
- for (unsigned j = 0; j < M; j++) {
- scale = v[j];
- for (unsigned i = 0; i < N; i++)
- res[i] += m(i, j) * scale;
- }
- return res;
- }
-
- // stream operator
- template <class T, unsigned M, unsigned N>
- inline std::ostream& operator<<(std::ostream& s,
- const Matrix<T, M, N>& m) {
- unsigned i, j;
- for (i = 0; i < M; i++) {
- s << "[";
- for (j = 0; j < N - 1; j++)
- s << m(i, j) << ", ";
- s << m(i, j) << "]" << std::endl;
- }
- return s;
- }
+ static inline SquareMatrix<T, N> identity()
+ {
+ SquareMatrix<T, N> res;
+ for (unsigned int i = 0; i < N; i++)
+ res(i, i) = 1;
+ return res;
+ }
+};
+
+#undef _SIZE
+
+//
+// Vector external functions
+//
+/////////////////////////////////////////////////////////////////////////////
+
+#if 0
+template <class T, unsigned N>
+inline Vec<T, N> operator+(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ Vec<T, N> res(v1);
+ res += v2;
+ return res;
+}
+
+template <class T, unsigned N>
+inline Vec<T, N> operator-(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ Vec<T, N> res(v1);
+ res -= v2;
+ return res;
+}
+
+template <class T, unsigned N>
+inline Vec<T, N> operator*(const Vec<T, N>& v, const typename Vec<T, N>::value_type r)
+{
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+}
+#endif
+
+template <class T, unsigned N>
+inline Vec<T, N> operator*(const typename Vec<T, N>::value_type r, const Vec<T, N>& v)
+{
+ Vec<T, N> res(v);
+ res *= r;
+ return res;
+}
+
+#if 0
+template <class T, unsigned N>
+inline Vec<T, N> operator/(const Vec<T, N>& v, const typename Vec<T, N>::value_type r)
+{
+ Vec<T, N> res(v);
+ if (r)
+ res /= r;
+ return res;
+}
+
+// dot product
+template <class T, unsigned N>
+inline typename Vec<T, N>::value_type operator*(const Vec<T, N>& v1, const Vec<T, N>& v2)
+{
+ typename Vec<T, N>::value_type sum = 0;
+ for (unsigned int i = 0; i < N; i++)
+ sum += v1[i] * v2[i];
+ return sum;
+}
+
+// cross product for 3D Vectors
+template <typename T>
+inline Vec3<T> operator^(const Vec<T, 3>& v1, const Vec<T, 3>& v2)
+{
+ Vec3<T> res(v1[1] * v2[2] - v1[2] * v2[1], v1[2] * v2[0] - v1[0] * v2[2], v1[0] * v2[1] - v1[1] * v2[0]);
+ return res;
+}
+#endif
+
+// stream operator
+template <class T, unsigned N>
+inline std::ostream& operator<<(std::ostream& s, const Vec<T, N>& v)
+{
+ unsigned int i;
+ s << "[";
+ for (i = 0; i < N - 1; i++)
+ s << v[i] << ", ";
+ s << v[i] << "]";
+ return s;
+}
+
+//
+// Matrix external functions
+//
+/////////////////////////////////////////////////////////////////////////////
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator+(const Matrix<T, M, N>& m1, const Matrix<T, M, N>& m2)
+{
+ Matrix<T, M, N> res(m1);
+ res += m2;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator-(const Matrix<T, M, N>& m1, const Matrix<T, M, N>& m2)
+{
+ Matrix<T, M, N> res(m1);
+ res -= m2;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(const Matrix<T, M, N>& m1, const typename Matrix<T, M, N>::value_type lambda)
+{
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator*(const typename Matrix<T, M, N>::value_type lambda, const Matrix<T, M, N>& m1)
+{
+ Matrix<T, M, N> res(m1);
+ res *= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Matrix<T, M, N> operator/(const Matrix<T, M, N>& m1, const typename Matrix<T, M, N>::value_type lambda)
+{
+ Matrix<T, M, N> res(m1);
+ res /= lambda;
+ return res;
+}
+
+template <class T, unsigned M, unsigned N, unsigned P>
+inline Matrix<T, M, P> operator*(const Matrix<T, M, N>& m1, const Matrix<T, N, P>& m2)
+{
+ unsigned int i, j, k;
+ Matrix<T, M, P> res;
+ typename Matrix<T, N, P>::value_type scale;
+
+ for (j = 0; j < P; j++) {
+ for (k = 0; k < N; k++) {
+ scale = m2(k, j);
+ for (i = 0; i < N; i++)
+ res(i, j) += m1(i, k) * scale;
+ }
+ }
+ return res;
+}
+
+template <class T, unsigned M, unsigned N>
+inline Vec<T, M> operator*(const Matrix<T, M, N>& m, const Vec<T, N>& v)
+{
+ Vec<T, M> res;
+ typename Matrix<T, M, N>::value_type scale;
+
+ for (unsigned int j = 0; j < M; j++) {
+ scale = v[j];
+ for (unsigned int i = 0; i < N; i++)
+ res[i] += m(i, j) * scale;
+ }
+ return res;
+}
+
+// stream operator
+template <class T, unsigned M, unsigned N>
+inline std::ostream& operator<<(std::ostream& s, const Matrix<T, M, N>& m)
+{
+ unsigned int i, j;
+ for (i = 0; i < M; i++) {
+ s << "[";
+ for (j = 0; j < N - 1; j++)
+ s << m(i, j) << ", ";
+ s << m(i, j) << "]" << std::endl;
+ }
+ return s;
+}
} // end of namespace VecMat
-#endif // VECMAT_H
+#endif // __VECMAT_H__
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.cpp b/source/blender/freestyle/intern/geometry/matrix_util.cpp
index 2117b06e62f..089535561d7 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.cpp
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -1,265 +1,266 @@
/*
- * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
- * Copyright (C) 2000 Bruno Levy
+ * ***** 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 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.
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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.
*
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
*
- * Contact: Bruno Levy
+ * The Original Code is:
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
*
- * levy@loria.fr
+ * Contributor(s): none yet.
*
- * ISA Project
- * LORIA, INRIA Lorraine,
- * Campus Scientifique, BP 239
- * 54506 VANDOEUVRE LES NANCY CEDEX
- * FRANCE
- *
- * Note that the GNU General Public License does not permit incorporating
- * the Software into proprietary programs.
+ * ***** END GPL LICENSE BLOCK *****
*/
+/** \file blender/freestyle/intern/geometry/matrix_util.cpp
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
-#include "matrix_util.h"
#include <math.h>
-
+#include "matrix_util.h"
namespace OGF {
-
- namespace MatrixUtil {
-
- static const double EPS = 0.00001 ;
- static int MAX_ITER = 100 ;
-
- void semi_definite_symmetric_eigen(
- const double *mat, int n, double *eigen_vec, double *eigen_val
- ) {
- double *a,*v;
- double a_norm,a_normEPS,thr,thr_nn;
- int nb_iter = 0;
- int jj;
- int i,j,k,ij,ik,l,m,lm,mq,lq,ll,mm,imv,im,iq,ilv,il,nn;
- int *index;
- double a_ij,a_lm,a_ll,a_mm,a_im,a_il;
- double a_lm_2;
- double v_ilv,v_imv;
- double x;
- double sinx,sinx_2,cosx,cosx_2,sincos;
- double delta;
-
- // Number of entries in mat
-
- nn = (n*(n+1))/2;
-
- // Step 1: Copy mat to a
-
- a = new double[nn];
-
- for( ij=0; ij<nn; ij++ ) {
- a[ij] = mat[ij];
- }
-
- // Ugly Fortran-porting trick: indices for a are between 1 and n
- a--;
-
- // Step 2 : Init diagonalization matrix as the unit matrix
- v = new double[n*n];
-
- ij = 0;
- for( i=0; i<n; i++ ) {
- for( j=0; j<n; j++ ) {
- if( i==j ) {
- v[ij++] = 1.0;
- } else {
- v[ij++] = 0.0;
- }
- }
- }
-
- // Ugly Fortran-porting trick: indices for v are between 1 and n
- v--;
-
- // Step 3 : compute the weight of the non diagonal terms
- ij = 1 ;
- a_norm = 0.0;
- for( i=1; i<=n; i++ ) {
- for( j=1; j<=i; j++ ) {
- if( i!=j ) {
- a_ij = a[ij];
- a_norm += a_ij*a_ij;
- }
- ij++;
- }
- }
-
- if( a_norm != 0.0 ) {
-
- a_normEPS = a_norm*EPS;
- thr = a_norm ;
-
- // Step 4 : rotations
- while( thr > a_normEPS && nb_iter < MAX_ITER ) {
-
- nb_iter++;
- thr_nn = thr / nn;
-
- for( l=1 ; l< n; l++ ) {
- for( m=l+1; m<=n; m++ ) {
-
- // compute sinx and cosx
-
- lq = (l*l-l)/2;
- mq = (m*m-m)/2;
-
- lm = l+mq;
- a_lm = a[lm];
- a_lm_2 = a_lm*a_lm;
-
- if( a_lm_2 < thr_nn ) {
- continue ;
- }
-
- ll = l+lq;
- mm = m+mq;
- a_ll = a[ll];
- a_mm = a[mm];
-
- delta = a_ll - a_mm;
-
- if( delta == 0.0 ) {
- x = - M_PI/4 ;
- } else {
- x = - atan( (a_lm+a_lm) / delta ) / 2.0 ;
- }
-
- sinx = sin(x) ;
- cosx = cos(x) ;
- sinx_2 = sinx*sinx;
- cosx_2 = cosx*cosx;
- sincos = sinx*cosx;
-
- // rotate L and M columns
-
- ilv = n*(l-1);
- imv = n*(m-1);
-
- for( i=1; i<=n;i++ ) {
- if( (i!=l) && (i!=m) ) {
- iq = (i*i-i)/2;
-
- if( i<m ) {
- im = i + mq;
- } else {
- im = m + iq;
- }
- a_im = a[im];
-
- if( i<l ) {
- il = i + lq;
- } else {
- il = l + iq;
- }
- a_il = a[il];
-
- a[il] = a_il*cosx - a_im*sinx;
- a[im] = a_il*sinx + a_im*cosx;
- }
-
- ilv++;
- imv++;
-
- v_ilv = v[ilv];
- v_imv = v[imv];
-
- v[ilv] = cosx*v_ilv - sinx*v_imv;
- v[imv] = sinx*v_ilv + cosx*v_imv;
- }
-
- x = a_lm*sincos; x+=x;
-
- a[ll] = a_ll*cosx_2 + a_mm*sinx_2 - x;
- a[mm] = a_ll*sinx_2 + a_mm*cosx_2 + x;
- a[lm] = 0.0;
-
- thr = fabs( thr - a_lm_2 );
- }
- }
- }
- }
-
- // Step 5: index conversion and copy eigen values
-
- // back from Fortran to C++
- a++;
-
- for( i=0; i<n; i++ ) {
- k = i + (i*(i+1))/2;
- eigen_val[i] = a[k];
- }
-
- delete[] a;
-
- // Step 6: sort the eigen values and eigen vectors
-
- index = new int[n];
- for( i=0; i<n; i++ ) {
- index[i] = i;
- }
-
- for( i=0; i<(n-1); i++ ) {
- x = eigen_val[i];
- k = i;
-
- for( j=i+1; j<n; j++ ) {
- if( x < eigen_val[j] ) {
- k = j;
- x = eigen_val[j];
- }
- }
-
- eigen_val[k] = eigen_val[i];
- eigen_val[i] = x;
-
- jj = index[k];
- index[k] = index[i];
- index[i] = jj;
- }
-
-
- // Step 7: save the eigen vectors
-
- v++; // back from Fortran to to C++
-
- ij = 0;
- for( k=0; k<n; k++ ) {
- ik = index[k]*n;
- for( i=0; i<n; i++ ) {
- eigen_vec[ij++] = v[ik++];
- }
- }
-
- delete[] v ;
- delete[] index;
- return;
- }
-
+
+namespace MatrixUtil {
+
+ static const double EPS = 0.00001;
+ static int MAX_ITER = 100;
+
+ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val)
+ {
+ double *a, *v;
+ double a_norm, a_normEPS, thr, thr_nn;
+ int nb_iter = 0;
+ int jj;
+ int i, j, k, ij, ik, l, m, lm, mq, lq, ll, mm, imv, im, iq, ilv, il, nn;
+ int *index;
+ double a_ij, a_lm, a_ll, a_mm, a_im, a_il;
+ double a_lm_2;
+ double v_ilv, v_imv;
+ double x;
+ double sinx, sinx_2, cosx, cosx_2, sincos;
+ double delta;
+
+ // Number of entries in mat
+ nn = (n * (n + 1)) / 2;
+
+ // Step 1: Copy mat to a
+ a = new double[nn];
+
+ for (ij = 0; ij < nn; ij++) {
+ a[ij] = mat[ij];
+ }
+
+ // Ugly Fortran-porting trick: indices for a are between 1 and n
+ a--;
+
+ // Step 2 : Init diagonalization matrix as the unit matrix
+ v = new double[n * n];
+
+ ij = 0;
+ for (i = 0; i < n; i++) {
+ for (j = 0; j < n; j++) {
+ if (i == j) {
+ v[ij++] = 1.0;
+ }
+ else {
+ v[ij++] = 0.0;
+ }
+ }
+ }
+
+ // Ugly Fortran-porting trick: indices for v are between 1 and n
+ v--;
+
+ // Step 3 : compute the weight of the non diagonal terms
+ ij = 1;
+ a_norm = 0.0;
+ for (i = 1; i <= n; i++) {
+ for (j = 1; j <= i; j++) {
+ if (i != j) {
+ a_ij = a[ij];
+ a_norm += a_ij * a_ij;
+ }
+ ij++;
+ }
+ }
+
+ if (a_norm != 0.0) {
+ a_normEPS = a_norm * EPS;
+ thr = a_norm;
+
+ // Step 4 : rotations
+ while (thr > a_normEPS && nb_iter < MAX_ITER) {
+ nb_iter++;
+ thr_nn = thr / nn;
+
+ for (l = 1; l < n; l++) {
+ for (m = l + 1; m <= n; m++) {
+ // compute sinx and cosx
+ lq = (l * l - l) / 2;
+ mq = (m * m - m) / 2;
+
+ lm = l + mq;
+ a_lm = a[lm];
+ a_lm_2 = a_lm * a_lm;
+
+ if (a_lm_2 < thr_nn) {
+ continue;
+ }
+
+ ll = l + lq;
+ mm = m + mq;
+ a_ll = a[ll];
+ a_mm = a[mm];
+
+ delta = a_ll - a_mm;
+
+ if (delta == 0.0) {
+ x = -M_PI / 4;
+ }
+ else {
+ x = -atan((a_lm + a_lm) / delta) / 2.0;
+ }
+
+ sinx = sin(x);
+ cosx = cos(x);
+ sinx_2 = sinx * sinx;
+ cosx_2 = cosx * cosx;
+ sincos = sinx * cosx;
+
+ // rotate L and M columns
+ ilv = n * (l - 1);
+ imv = n * (m - 1);
+
+ for (i = 1; i <= n; i++) {
+ if ((i != l) && (i != m)) {
+ iq = (i * i - i) / 2;
+
+ if (i < m) {
+ im = i + mq;
+ }
+ else {
+ im = m + iq;
+ }
+ a_im = a[im];
+
+ if (i < l) {
+ il = i + lq;
+ }
+ else {
+ il = l + iq;
+ }
+ a_il = a[il];
+
+ a[il] = a_il * cosx - a_im * sinx;
+ a[im] = a_il * sinx + a_im * cosx;
+ }
+
+ ilv++;
+ imv++;
+
+ v_ilv = v[ilv];
+ v_imv = v[imv];
+
+ v[ilv] = cosx * v_ilv - sinx * v_imv;
+ v[imv] = sinx * v_ilv + cosx * v_imv;
+ }
+
+ x = a_lm * sincos;
+ x += x;
+
+ a[ll] = a_ll * cosx_2 + a_mm * sinx_2 - x;
+ a[mm] = a_ll * sinx_2 + a_mm * cosx_2 + x;
+ a[lm] = 0.0;
+
+ thr = fabs(thr - a_lm_2);
+ }
+ }
+ }
+ }
+
+ // Step 5: index conversion and copy eigen values
+
+ // back from Fortran to C++
+ a++;
+
+ for (i = 0; i < n; i++) {
+ k = i + (i * (i + 1)) / 2;
+ eigen_val[i] = a[k];
+ }
+
+ delete[] a;
+
+ // Step 6: sort the eigen values and eigen vectors
+
+ index = new int[n];
+ for (i = 0; i < n; i++) {
+ index[i] = i;
+ }
+
+ for (i = 0; i < (n - 1); i++) {
+ x = eigen_val[i];
+ k = i;
+
+ for (j = i + 1; j < n; j++) {
+ if (x < eigen_val[j]) {
+ k = j;
+ x = eigen_val[j];
+ }
+ }
+
+ eigen_val[k] = eigen_val[i];
+ eigen_val[i] = x;
+
+ jj = index[k];
+ index[k] = index[i];
+ index[i] = jj;
+ }
+
+ // Step 7: save the eigen vectors
+
+ // back from Fortran to to C++
+ v++;
+
+ ij = 0;
+ for (k = 0; k < n; k++) {
+ ik = index[k] * n;
+ for (i = 0; i < n; i++) {
+ eigen_vec[ij++] = v[ik++];
+ }
+ }
+
+ delete[] v;
+ delete[] index;
+ return;
+ }
+
//_________________________________________________________
- }
-}
+} // MatrixUtil namespace
+
+} // OGF namespace
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
index a990413c403..1cf58a8e1fd 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.h
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -1,69 +1,72 @@
/*
- * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
- * Copyright (C) 2000 Bruno Levy
+ * ***** 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 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.
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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.
*
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
*
- * Contact: Bruno Levy
+ * The Original Code is:
+ * GXML/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
*
- * levy@loria.fr
+ * Contributor(s): none yet.
*
- * ISA Project
- * LORIA, INRIA Lorraine,
- * Campus Scientifique, BP 239
- * 54506 VANDOEUVRE LES NANCY CEDEX
- * FRANCE
- *
- * Note that the GNU General Public License does not permit incorporating
- * the Software into proprietary programs.
+ * ***** END GPL LICENSE BLOCK *****
*/
#ifndef __MATRIX_UTIL__
#define __MATRIX_UTIL__
-# include "../system/FreestyleConfig.h"
+/** \file blender/freestyle/intern/geometry/matrix_util.h
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include "../system/FreestyleConfig.h"
namespace OGF {
- namespace MatrixUtil {
+namespace MatrixUtil {
+
+ /**
+ * computes the eigen values and eigen vectors of a semi definite symmetric matrix
+ *
+ * @param matrix is stored in column symmetric storage, i.e.
+ * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
+ * size = n(n+1)/2
+ *
+ * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
+ * where vk = vk0, vk1, ..., vkn
+ * size = n^2, must be allocated by caller
+ *
+ * @param eigen_values (return) are in decreasing order
+ * size = n, must be allocated by caller
+ */
+ LIB_GEOMETRY_EXPORT
+ void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
+
+} // MatrixUtil namespace
- /**
- * computes the eigen values and eigen vectors
- * of a semi definite symmetric matrix
- *
- * @param matrix is stored in column symmetric storage, i.e.
- * matrix = { m11, m12, m22, m13, m23, m33, m14, m24, m34, m44 ... }
- * size = n(n+1)/2
- *
- * @param eigen_vectors (return) = { v1, v2, v3, ..., vn }
- * where vk = vk0, vk1, ..., vkn
- * size = n^2, must be allocated by caller
- *
- * @param eigen_values (return) are in decreasing order
- * size = n, must be allocated by caller
- */
- LIB_GEOMETRY_EXPORT
- void semi_definite_symmetric_eigen(
- const double *mat, int n, double *eigen_vec, double *eigen_val
- ) ;
-
- }
-}
+} // OGF namespace
-#endif
+#endif // __MATRIX_UTIL__
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
index 3a697d54731..2f0aa268c9f 100644
--- a/source/blender/freestyle/intern/geometry/normal_cycle.cpp
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
@@ -1,87 +1,100 @@
+/*
+ * ***** 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.
+ *
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
+ *
+ * The Original Code is:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
+ *
+ * Contributor(s): none yet.
+ *
+ * ***** END GPL LICENSE BLOCK *****
+ */
-//
-// 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.
-//
-///////////////////////////////////////////////////////////////////////////////
-#include "normal_cycle.h"
-#include "matrix_util.h"
+/** \file blender/freestyle/intern/geometry/normal_cycle.cpp
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+#include "matrix_util.h"
+#include "normal_cycle.h"
namespace OGF {
//_________________________________________________________
-
-
- NormalCycle::NormalCycle() {
- }
-
- void NormalCycle::begin() {
- M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0 ;
- }
-
- void NormalCycle::end() {
-
- double eigen_vectors[9] ;
- MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_) ;
-
- axis_[0] = Vec3r(
- eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]
- ) ;
-
- axis_[1] = Vec3r(
- eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]
- ) ;
-
- axis_[2] = Vec3r(
- eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]
- ) ;
-
- // Normalize the eigen vectors
-
- for(int i=0; i<3; i++) {
- axis_[i].normalize() ;
- }
-
- // Sort the eigen vectors
-
- i_[0] = 0 ;
- i_[1] = 1 ;
- i_[2] = 2 ;
-
- double l0 = ::fabs(eigen_value_[0]) ;
- double l1 = ::fabs(eigen_value_[1]) ;
- double l2 = ::fabs(eigen_value_[2]) ;
-
- if(l1 > l0) {
- ogf_swap(l0 , l1 ) ;
- ogf_swap(i_[0], i_[1]) ;
- }
- if(l2 > l1) {
- ogf_swap(l1 , l2 ) ;
- ogf_swap(i_[1], i_[2]) ;
- }
- if(l1 > l0) {
- ogf_swap(l0 , l1 ) ;
- ogf_swap(i_[0],i_[1]) ;
- }
-
- }
-//_________________________________________________________
+NormalCycle::NormalCycle()
+{
}
+
+void NormalCycle::begin()
+{
+ M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0;
+}
+
+void NormalCycle::end()
+{
+ double eigen_vectors[9];
+ MatrixUtil::semi_definite_symmetric_eigen(M_, 3, eigen_vectors, eigen_value_);
+
+ axis_[0] = Vec3r(eigen_vectors[0], eigen_vectors[1], eigen_vectors[2]);
+
+ axis_[1] = Vec3r(eigen_vectors[3], eigen_vectors[4], eigen_vectors[5]);
+
+ axis_[2] = Vec3r(eigen_vectors[6], eigen_vectors[7], eigen_vectors[8]);
+
+ // Normalize the eigen vectors
+ for (int i = 0; i < 3; i++) {
+ axis_[i].normalize();
+ }
+
+ // Sort the eigen vectors
+ i_[0] = 0;
+ i_[1] = 1;
+ i_[2] = 2;
+
+ double l0 = ::fabs(eigen_value_[0]);
+ double l1 = ::fabs(eigen_value_[1]);
+ double l2 = ::fabs(eigen_value_[2]);
+
+ if (l1 > l0) {
+ ogf_swap(l0 , l1 );
+ ogf_swap(i_[0], i_[1]);
+ }
+ if (l2 > l1) {
+ ogf_swap(l1 , l2 );
+ ogf_swap(i_[1], i_[2]);
+ }
+ if (l1 > l0) {
+ ogf_swap(l0 , l1 );
+ ogf_swap(i_[0], i_[1]);
+ }
+}
+
+//_________________________________________________________
+
+} // OGF namespace
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
index cdf00a0b4c5..3fbf4fb58ae 100644
--- a/source/blender/freestyle/intern/geometry/normal_cycle.h
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -1,110 +1,144 @@
/*
- * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
- * Copyright (C) 2000 Bruno Levy
+ * ***** 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 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.
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ * 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.
*
- * If you modify this software, you should include a notice giving the
- * name of the person performing the modification, the date of modification,
- * and the reason for such modification.
+ * This Code is Copyright (C) 2010 Blender Foundation.
+ * All rights reserved.
*
- * Contact: Bruno Levy
+ * The Original Code is:
+ * OGF/Graphite: Geometry and Graphics Programming Library + Utilities
+ * Copyright (C) 2000 Bruno Levy
+ * Contact: Bruno Levy
+ * levy@loria.fr
+ * ISA Project
+ * LORIA, INRIA Lorraine,
+ * Campus Scientifique, BP 239
+ * 54506 VANDOEUVRE LES NANCY CEDEX
+ * FRANCE
*
- * levy@loria.fr
+ * Contributor(s): none yet.
*
- * ISA Project
- * LORIA, INRIA Lorraine,
- * Campus Scientifique, BP 239
- * 54506 VANDOEUVRE LES NANCY CEDEX
- * FRANCE
- *
- * Note that the GNU General Public License does not permit incorporating
- * the Software into proprietary programs.
+ * ***** END GPL LICENSE BLOCK *****
*/
#ifndef __MESH_TOOLS_MATH_NORMAL_CYCLE__
#define __MESH_TOOLS_MATH_NORMAL_CYCLE__
-# include "../system/FreestyleConfig.h"
-# include "Geom.h"
+/** \file blender/freestyle/intern/geometry/normal_cycle.h
+ * \ingroup freestyle
+ * \author Bruno Levy
+ */
+
+#include "Geom.h"
+
+#include "../system/FreestyleConfig.h"
+
using namespace Geometry;
-
+
namespace OGF {
-template <class T> inline void ogf_swap(T& x, T& y) {
- T z = x ;
- x = y ;
- y = z ;
- }
+template <class T> inline void ogf_swap(T& x, T& y)
+{
+ T z = x ;
+ x = y ;
+ y = z ;
+}
//_________________________________________________________
- /**
- * NormalCycle evaluates the curvature tensor in function
- * of a set of dihedral angles and associated vectors.
- * Reference:
- * Restricted Delaunay Triangulation and Normal Cycle,
- * D. Cohen-Steiner and J.M. Morvan,
- * SOCG 2003
- */
- class LIB_GEOMETRY_EXPORT NormalCycle {
- public:
- NormalCycle() ;
- void begin() ;
- void end() ;
- /**
- * Note: the specified edge vector needs to be pre-clipped
- * by the neighborhood.
- */
- void accumulate_dihedral_angle(
- const Vec3r& edge, real angle, real neigh_area = 1.0
- ) ;
- const Vec3r& eigen_vector(int i) const { return axis_[i_[i]] ; }
- real eigen_value(int i) const { return eigen_value_[i_[i]] ; }
-
- const Vec3r& N() const { return eigen_vector(2) ; }
- const Vec3r& Kmax() const { return eigen_vector(1) ; }
- const Vec3r& Kmin() const { return eigen_vector(0) ; }
-
- real n() const { return eigen_value(2) ; }
- real kmax() const { return eigen_value(1) ; }
- real kmin() const { return eigen_value(0) ; }
-
- private:
- real center_[3] ;
- Vec3r axis_[3] ;
- real eigen_value_[3] ;
- real M_[6] ;
- int i_[3] ;
- } ;
-
- inline void NormalCycle::accumulate_dihedral_angle(
- const Vec3r& edge, const double beta, double neigh_area
- ) {
- double s = beta * neigh_area / edge.norm();
-
- M_[0] += s * edge.x() * edge.x() ;
- M_[1] += s * edge.x() * edge.y() ;
- M_[2] += s * edge.y() * edge.y() ;
- M_[3] += s * edge.x() * edge.z() ;
- M_[4] += s * edge.y() * edge.z() ;
- M_[5] += s * edge.z() * edge.z() ;
- }
-
-//_________________________________________________________
+/**
+* NormalCycle evaluates the curvature tensor in function
+* of a set of dihedral angles and associated vectors.
+* Reference:
+* Restricted Delaunay Triangulation and Normal Cycle,
+* D. Cohen-Steiner and J.M. Morvan,
+* SOCG 2003
+*/
+class LIB_GEOMETRY_EXPORT NormalCycle {
+public:
+ NormalCycle();
+ void begin();
+ void end();
+ /**
+ * Note: the specified edge vector needs to be pre-clipped by the neighborhood.
+ */
+ void accumulate_dihedral_angle(const Vec3r& edge, real angle, real neigh_area = 1.0);
+
+ const Vec3r& eigen_vector(int i) const
+ {
+ return axis_[i_[i]];
+ }
+
+ real eigen_value(int i) const
+ {
+ return eigen_value_[i_[i]];
+ }
+
+ const Vec3r& N() const
+ {
+ return eigen_vector(2);
+ }
+ const Vec3r& Kmax() const
+ {
+ return eigen_vector(1);
+ }
+
+ const Vec3r& Kmin() const
+ {
+ return eigen_vector(0);
+ }
+
+ real n() const
+ {
+ return eigen_value(2);
+ }
+
+ real kmax() const
+ {
+ return eigen_value(1);
+ }
+
+ real kmin() const
+ {
+ return eigen_value(0);
+ }
+
+private:
+ real center_[3];
+ Vec3r axis_[3];
+ real eigen_value_[3];
+ real M_[6];
+ int i_[3];
+};
+
+inline void NormalCycle::accumulate_dihedral_angle(const Vec3r& edge, const double beta, double neigh_area)
+{
+ double s = beta * neigh_area / edge.norm();
+
+ M_[0] += s * edge.x() * edge.x();
+ M_[1] += s * edge.x() * edge.y();
+ M_[2] += s * edge.y() * edge.y();
+ M_[3] += s * edge.x() * edge.z();
+ M_[4] += s * edge.y() * edge.z();
+ M_[5] += s * edge.z() * edge.z();
}
-#endif
+//_________________________________________________________
+
+} // OGF namespace
+
+#endif // __MESH_TOOLS_MATH_NORMAL_CYCLE__