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:
authorCampbell Barton <ideasman42@gmail.com>2019-04-17 07:17:24 +0300
committerCampbell Barton <ideasman42@gmail.com>2019-04-17 07:21:24 +0300
commite12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch)
tree8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/freestyle/intern/geometry
parentb3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (diff)
ClangFormat: apply to source, most of intern
Apply clang format as proposed in T53211. For details on usage and instructions for migrating branches without conflicts, see: https://wiki.blender.org/wiki/Tools/ClangFormat
Diffstat (limited to 'source/blender/freestyle/intern/geometry')
-rw-r--r--source/blender/freestyle/intern/geometry/BBox.h222
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.cpp130
-rw-r--r--source/blender/freestyle/intern/geometry/Bezier.h80
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.cpp66
-rw-r--r--source/blender/freestyle/intern/geometry/FastGrid.h68
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.cpp670
-rw-r--r--source/blender/freestyle/intern/geometry/FitCurve.h141
-rw-r--r--source/blender/freestyle/intern/geometry/Geom.h62
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.cpp357
-rw-r--r--source/blender/freestyle/intern/geometry/GeomCleaner.h367
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.cpp1191
-rw-r--r--source/blender/freestyle/intern/geometry/GeomUtils.h146
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.cpp606
-rw-r--r--source/blender/freestyle/intern/geometry/Grid.h633
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.cpp30
-rw-r--r--source/blender/freestyle/intern/geometry/GridHelpers.h268
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.cpp20
-rw-r--r--source/blender/freestyle/intern/geometry/HashGrid.h120
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.cpp327
-rw-r--r--source/blender/freestyle/intern/geometry/Noise.h59
-rw-r--r--source/blender/freestyle/intern/geometry/Polygon.h339
-rw-r--r--source/blender/freestyle/intern/geometry/SweepLine.h548
-rw-r--r--source/blender/freestyle/intern/geometry/VecMat.h1576
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.cpp426
-rw-r--r--source/blender/freestyle/intern/geometry/matrix_util.h34
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.cpp75
-rw-r--r--source/blender/freestyle/intern/geometry/normal_cycle.h146
27 files changed, 4416 insertions, 4291 deletions
diff --git a/source/blender/freestyle/intern/geometry/BBox.h b/source/blender/freestyle/intern/geometry/BBox.h
index 741d4e6715e..7350fabbc13 100644
--- a/source/blender/freestyle/intern/geometry/BBox.h
+++ b/source/blender/freestyle/intern/geometry/BBox.h
@@ -28,133 +28,127 @@
#include "BLI_utildefines.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
-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 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)
- {
- BLI_assert(!b.empty());
- _min = b.getMin();
- _max = b.getMax();
- _empty = false;
- return *this;
- }
-
- inline BBox<Point>& operator+=(const BBox<Point>& b)
- {
- BLI_assert(!b.empty());
- 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;
+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 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)
+ {
+ BLI_assert(!b.empty());
+ _min = b.getMin();
+ _max = b.getMax();
+ _empty = false;
+ return *this;
+ }
+
+ inline BBox<Point> &operator+=(const BBox<Point> &b)
+ {
+ BLI_assert(!b.empty());
+ 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;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BBox")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BBox")
#endif
};
-template <class Point>
-BBox<Point>& operator+(const BBox<Point> &b1, const BBox<Point> &b2)
+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 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];
- }
+ 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);
}
} /* namespace Freestyle */
-#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 aeac71fca11..3f6b6b25f76 100644
--- a/source/blender/freestyle/intern/geometry/Bezier.cpp
+++ b/source/blender/freestyle/intern/geometry/Bezier.cpp
@@ -34,90 +34,90 @@ BezierCurveSegment::~BezierCurveSegment()
{
}
-void BezierCurveSegment::AddControlPoint(const Vec2d& iPoint)
+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.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;
- }
+ 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)
+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 (!_Segments.empty()) {
- vector<BezierCurveSegment*>::iterator v, vend;
- for (v = _Segments.begin(), vend = _Segments.end(); v != vend; ++v)
- delete *v;
- }
- if (_currentSegment)
- delete _currentSegment;
+ if (!_Segments.empty()) {
+ vector<BezierCurveSegment *>::iterator v, vend;
+ for (v = _Segments.begin(), vend = _Segments.end(); v != vend; ++v)
+ delete *v;
+ }
+ if (_currentSegment)
+ delete _currentSegment;
}
-void BezierCurve::AddControlPoint(const Vec2d& iPoint)
+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);
+ }
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/Bezier.h b/source/blender/freestyle/intern/geometry/Bezier.h
index babeb3e9e57..adcd6e3a652 100644
--- a/source/blender/freestyle/intern/geometry/Bezier.h
+++ b/source/blender/freestyle/intern/geometry/Bezier.h
@@ -29,70 +29,68 @@
#include "../system/FreestyleConfig.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
using namespace Geometry;
-class BezierCurveSegment
-{
-private:
- std::vector<Vec2d> _ControlPolygon;
- std::vector<Vec2d> _Vertices;
+class BezierCurveSegment {
+ private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<Vec2d> _Vertices;
-public:
- BezierCurveSegment();
- virtual ~BezierCurveSegment();
+ public:
+ BezierCurveSegment();
+ virtual ~BezierCurveSegment();
- void AddControlPoint(const Vec2d& iPoint);
- void Build();
+ void AddControlPoint(const Vec2d &iPoint);
+ void Build();
- inline int size() const
- {
- return _ControlPolygon.size();
- }
+ inline int size() const
+ {
+ return _ControlPolygon.size();
+ }
- inline std::vector<Vec2d>& vertices()
- {
- return _Vertices;
- }
+ inline std::vector<Vec2d> &vertices()
+ {
+ return _Vertices;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BezierCurveSegment")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BezierCurveSegment")
#endif
};
-class BezierCurve
-{
-private:
- std::vector<Vec2d> _ControlPolygon;
- std::vector<BezierCurveSegment*> _Segments;
- BezierCurveSegment *_currentSegment;
+class BezierCurve {
+ private:
+ std::vector<Vec2d> _ControlPolygon;
+ std::vector<BezierCurveSegment *> _Segments;
+ BezierCurveSegment *_currentSegment;
-public:
- BezierCurve();
- BezierCurve(std::vector<Vec2d>& iPoints, double error=4.0);
- virtual ~BezierCurve();
+ public:
+ BezierCurve();
+ BezierCurve(std::vector<Vec2d> &iPoints, double error = 4.0);
+ virtual ~BezierCurve();
- void AddControlPoint(const Vec2d& iPoint);
+ void AddControlPoint(const Vec2d &iPoint);
- std::vector<Vec2d>& controlPolygon()
- {
- return _ControlPolygon;
- }
+ std::vector<Vec2d> &controlPolygon()
+ {
+ return _ControlPolygon;
+ }
- std::vector<BezierCurveSegment*>& segments()
- {
- return _Segments;
- }
+ std::vector<BezierCurveSegment *> &segments()
+ {
+ return _Segments;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BezierCurve")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:BezierCurve")
#endif
};
} /* namespace Freestyle */
-#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 dec22e67acb..e0d36bece6e 100644
--- a/source/blender/freestyle/intern/geometry/FastGrid.cpp
+++ b/source/blender/freestyle/intern/geometry/FastGrid.cpp
@@ -30,52 +30,52 @@ namespace Freestyle {
void FastGrid::clear()
{
- if (!_cells)
- return;
+ if (!_cells)
+ return;
- for (unsigned int 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)
+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));
+ 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)
+Cell *FastGrid::getCell(const Vec3u &p)
{
#if 0
- if (G.debug & G_DEBUG_FREESTYLE) {
- cout << _cells << " " << p << " " << _cells_nb[0] << "-" << _cells_nb[1] << "-" << _cells_nb[2]
- << " " << _cells_size << endl;
- }
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ cout << _cells << " " << p << " " << _cells_nb[0] << "-" << _cells_nb[1] << "-" << _cells_nb[2]
+ << " " << _cells_size << endl;
+ }
#endif
- BLI_assert(_cells || ("_cells is a null pointer"));
- BLI_assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
- BLI_assert(p[0] < _cells_nb[0]);
- BLI_assert(p[1] < _cells_nb[1]);
- BLI_assert(p[2] < _cells_nb[2]);
- return _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]];
+ BLI_assert(_cells || ("_cells is a null pointer"));
+ BLI_assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ BLI_assert(p[0] < _cells_nb[0]);
+ BLI_assert(p[1] < _cells_nb[1]);
+ BLI_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)
+void FastGrid::fillCell(const Vec3u &p, Cell &cell)
{
- BLI_assert(_cells || ("_cells is a null pointer"));
- BLI_assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
- BLI_assert(p[0] < _cells_nb[0]);
- BLI_assert(p[1] < _cells_nb[1]);
- BLI_assert(p[2] < _cells_nb[2]);
- _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
+ BLI_assert(_cells || ("_cells is a null pointer"));
+ BLI_assert((_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]) < _cells_size);
+ BLI_assert(p[0] < _cells_nb[0]);
+ BLI_assert(p[1] < _cells_nb[1]);
+ BLI_assert(p[2] < _cells_nb[2]);
+ _cells[_cells_nb[0] * (p[2] * _cells_nb[1] + p[1]) + p[0]] = &cell;
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/FastGrid.h b/source/blender/freestyle/intern/geometry/FastGrid.h
index 8c22703a68c..e2345d4831c 100644
--- a/source/blender/freestyle/intern/geometry/FastGrid.h
+++ b/source/blender/freestyle/intern/geometry/FastGrid.h
@@ -30,51 +30,49 @@ namespace Freestyle {
* 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 FastGrid : public Grid
-{
-public:
- FastGrid() : Grid()
- {
- _cells = NULL;
- _cells_size = 0;
- }
+class FastGrid : public Grid {
+ public:
+ 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();
+ /*! 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);
+ /*! 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);
+ /*! 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);
+ /*! Fills the case p with the cell iCell */
+ virtual void fillCell(const Vec3u &p, Cell &cell);
-protected:
- Cell **_cells;
- unsigned _cells_size;
+ protected:
+ Cell **_cells;
+ unsigned _cells_size;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FastGrid")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FastGrid")
#endif
-
};
} /* namespace Freestyle */
-#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 9e12507b896..b0408826763 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.cpp
+++ b/source/blender/freestyle/intern/geometry/FitCurve.cpp
@@ -20,7 +20,7 @@
* \brief from "Graphics Gems", Academic Press, 1990
*/
-#include <cstdlib> // for malloc and free
+#include <cstdlib> // for malloc and free
#include <stdio.h>
#include <math.h>
@@ -41,9 +41,11 @@ static double B1(double u);
static double B2(double u);
static double B3(double u);
static Vector2 ComputeLeftTangent(Vector2 *d, int end);
-static double ComputeMaxError(Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint);
+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);
@@ -51,64 +53,64 @@ static Vector2 V2SubII(Vector2 a, Vector2 b);
/* returns squared length of input vector */
static double V2SquaredLength(Vector2 *a)
{
- return (((*a)[0] * (*a)[0]) + ((*a)[1] * (*a)[1]));
+ 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)
{
- 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)
{
- 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)
{
- 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)
{
- (*v)[0] = -(*v)[0];
- (*v)[1] = -(*v)[1];
- return v;
+ (*v)[0] = -(*v)[0];
+ (*v)[1] = -(*v)[1];
+ return v;
}
/* GenerateBezier:
@@ -118,92 +120,88 @@ static Vector2 *V2Negate(Vector2 *v)
* 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)
+static BezierCurve GenerateBezier(
+ Vector2 *d, int first, int last, double *uPrime, Vector2 tHat1, Vector2 tHat2)
{
- int i;
- Vector2 A[2]; /* 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;
-
- /* 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++) {
- /* Compute the A's */
- A[0] = tHat1;
- A[1] = tHat2;
- V2Scale(&A[0], B1(uPrime[i]));
- V2Scale(&A[1], B2(uPrime[i]));
-
- C[0][0] += V2Dot(&A[0], &A[0]);
- C[0][1] += V2Dot(&A[0], &A[1]);
-// C[1][0] += V2Dot(&A[0], &A[1]);
- C[1][0] = C[0][1];
- C[1][1] += V2Dot(&A[1], &A[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[0], &tmp);
- X[1] += V2Dot(&A[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);
+ int i;
+ Vector2 A[2]; /* 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;
+
+ /* 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++) {
+ /* Compute the A's */
+ A[0] = tHat1;
+ A[1] = tHat2;
+ V2Scale(&A[0], B1(uPrime[i]));
+ V2Scale(&A[1], B2(uPrime[i]));
+
+ C[0][0] += V2Dot(&A[0], &A[0]);
+ C[0][1] += V2Dot(&A[0], &A[1]);
+ // C[1][0] += V2Dot(&A[0], &A[1]);
+ C[1][0] = C[0][1];
+ C[1][1] += V2Dot(&A[1], &A[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[0], &tmp);
+ X[1] += V2Dot(&A[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);
}
/*
@@ -216,15 +214,15 @@ static BezierCurve GenerateBezier(Vector2 *d, int first, int last, double *uPri
*/
static double *Reparameterize(Vector2 *d, int first, int last, double *u, BezierCurve bezCurve)
{
- 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);
}
/*
@@ -236,41 +234,41 @@ static double *Reparameterize(Vector2 *d, int first, int last, double *u, Bezier
*/
static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
{
- 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;
}
/*
@@ -282,27 +280,27 @@ static double NewtonRaphsonRootFind(BezierCurve Q, Vector2 P, double u)
*/
static Vector2 BezierII(int degree, Vector2 *V, double t)
{
- 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++) {
- 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];
- }
- }
-
- Q = Vtemp[0];
- free((void *)Vtemp);
- return Q;
+ 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++) {
+ 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];
+ }
+ }
+
+ Q = Vtemp[0];
+ free((void *)Vtemp);
+ return Q;
}
/*
@@ -311,25 +309,25 @@ static Vector2 BezierII(int degree, Vector2 *V, double t)
*/
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);
}
/*
@@ -341,10 +339,10 @@ static double B3(double u)
*/
static Vector2 ComputeLeftTangent(Vector2 *d, int end)
{
- 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
@@ -352,10 +350,10 @@ static Vector2 ComputeLeftTangent(Vector2 *d, int end)
*/
static Vector2 ComputeRightTangent(Vector2 *d, int end)
{
- 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
@@ -363,20 +361,20 @@ static Vector2 ComputeRightTangent(Vector2 *d, int end)
*/
static Vector2 ComputeCenterTangent(Vector2 *d, int center)
{
- Vector2 V1, V2, 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);
+ 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);
- /* avoid numerical singularity in the special case when V1 == -V2 */
- if (V2Length(&tHatCenter) < M_EPSILON) {
- tHatCenter = *V2Normalize(&V1);
- }
+ /* avoid numerical singularity in the special case when V1 == -V2 */
+ if (V2Length(&tHatCenter) < M_EPSILON) {
+ tHatCenter = *V2Normalize(&V1);
+ }
- return tHatCenter;
+ return tHatCenter;
}
/*
@@ -387,21 +385,21 @@ static Vector2 ComputeCenterTangent(Vector2 *d, int center)
*/
static double *ChordLengthParameterize(Vector2 *d, int first, int last)
{
- 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;
}
/*
@@ -413,50 +411,51 @@ static double *ChordLengthParameterize(Vector2 *d, int first, int last)
* 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)
+static double ComputeMaxError(
+ Vector2 *d, int first, int last, BezierCurve bezCurve, double *u, int *splitPoint)
{
- 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;
- }
- }
- return maxDist;
+ 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;
+ }
+ }
+ 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;
}
//------------------------- WRAPPER -----------------------------//
@@ -467,114 +466,115 @@ FitCurveWrapper::FitCurveWrapper()
FitCurveWrapper::~FitCurveWrapper()
{
- _vertices.clear();
+ _vertices.clear();
}
void FitCurveWrapper::DrawBezierCurve(int n, Vector2 *curve)
{
- for (int i = 0; i <= n; ++i)
- _vertices.push_back(curve[i]);
+ for (int i = 0; i <= n; ++i)
+ _vertices.push_back(curve[i]);
}
-void FitCurveWrapper::FitCurve(vector<Vec2d>& data, vector<Vec2d>& oCurve, double error)
+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];
- }
+ 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);
+ FitCurve(d, size, error);
- delete[] d;
+ delete[] d;
- // copy results
- for (vector<Vector2>::iterator v = _vertices.begin(), vend = _vertices.end(); v != vend; ++v) {
- oCurve.push_back(Vec2d(v->x(), v->y())) ;
- }
+ // 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)
+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));
- 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);
- return;
- }
-
- /* 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) {
- DrawBezierCurve(3, bezCurve);
- free((void *)u);
- free((void *)bezCurve);
- return;
- }
-
- /* 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);
-
- free((void *)u);
- free((void *)bezCurve);
- u = uPrime;
-
- bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
- maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
-
- if (maxError < error) {
- DrawBezierCurve(3, bezCurve);
- free((void *)u);
- free((void *)bezCurve);
- return;
- }
- }
- }
-
- /* 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);
+ 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);
+ return;
+ }
+
+ /* 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) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+
+ /* 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);
+
+ free((void *)u);
+ free((void *)bezCurve);
+ u = uPrime;
+
+ bezCurve = GenerateBezier(d, first, last, u, tHat1, tHat2);
+ maxError = ComputeMaxError(d, first, last, bezCurve, u, &splitPoint);
+
+ if (maxError < error) {
+ DrawBezierCurve(3, bezCurve);
+ free((void *)u);
+ free((void *)bezCurve);
+ return;
+ }
+ }
+ }
+
+ /* 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);
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/FitCurve.h b/source/blender/freestyle/intern/geometry/FitCurve.h
index f32549ed526..92afd685d8f 100644
--- a/source/blender/freestyle/intern/geometry/FitCurve.h
+++ b/source/blender/freestyle/intern/geometry/FitCurve.h
@@ -34,83 +34,80 @@ namespace Freestyle {
using namespace Geometry;
/* 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];
- }
+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;
-
-class FitCurveWrapper
-{
-private:
- 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);
-
-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);
+class FitCurveWrapper {
+ private:
+ 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);
+
+ 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);
};
} /* namespace Freestyle */
-#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 ecd07f88835..63785d56cab 100644
--- a/source/blender/freestyle/intern/geometry/Geom.h
+++ b/source/blender/freestyle/intern/geometry/Geom.h
@@ -30,44 +30,44 @@ namespace Freestyle {
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<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
+} // end of namespace Geometry
} /* namespace Freestyle */
-#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 9643593a03d..32d6fc62085 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.cpp
@@ -20,13 +20,13 @@
*/
#if 0
-#if defined(__GNUC__) && (__GNUC__ >= 3)
+# 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 <stdio.h>
@@ -43,188 +43,209 @@ using namespace std;
namespace Freestyle {
-void GeomCleaner::SortIndexedVertexArray(const float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, float **oVertices, unsigned **oIndices)
+void GeomCleaner::SortIndexedVertexArray(const float *iVertices,
+ unsigned iVSize,
+ const unsigned *iIndices,
+ unsigned iISize,
+ float **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(Vec3f(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 float[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(Vec3f(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 float[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 float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, float **oVertices, unsigned *oVSize, unsigned **oIndices)
+void GeomCleaner::CompressIndexedVertexArray(const float *iVertices,
+ unsigned iVSize,
+ const unsigned *iIndices,
+ unsigned iISize,
+ float **oVertices,
+ unsigned *oVSize,
+ unsigned **oIndices)
{
- // First, we build a list of IndexVertex:
- vector<Vec3f> vertices;
- unsigned i;
- for (i = 0; i < iVSize; i += 3) {
- vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
- }
-
- unsigned *mapVertex = new unsigned[iVSize];
- vector<Vec3f>::iterator v = vertices.begin();
-
- vector<Vec3f> compressedVertices;
- Vec3f previous = *v;
- mapVertex[0] = 0;
- compressedVertices.push_back(vertices.front());
-
- v++;
- Vec3f 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 float[*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<Vec3f> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3) {
+ vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+ }
+
+ unsigned *mapVertex = new unsigned[iVSize];
+ vector<Vec3f>::iterator v = vertices.begin();
+
+ vector<Vec3f> compressedVertices;
+ Vec3f previous = *v;
+ mapVertex[0] = 0;
+ compressedVertices.push_back(vertices.front());
+
+ v++;
+ Vec3f 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 float[*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, float **oVertices, unsigned *oVSize,
+void GeomCleaner::SortAndCompressIndexedVertexArray(const float *iVertices,
+ unsigned iVSize,
+ const unsigned *iIndices,
+ unsigned iISize,
+ float **oVertices,
+ unsigned *oVSize,
unsigned **oIndices)
{
- // tmp arrays used to store the sorted data:
- float *tmpVertices;
- unsigned *tmpIndices;
-
- Chronometer chrono;
- // Sort data
- chrono.start();
- GeomCleaner::SortIndexedVertexArray(iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
- if (G.debug & G_DEBUG_FREESTYLE) {
- printf("Sorting: %lf sec.\n", chrono.stop());
- }
-
- // compress data
- chrono.start();
- GeomCleaner::CompressIndexedVertexArray(tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
- real duration = chrono.stop();
- if (G.debug & G_DEBUG_FREESTYLE) {
- printf("Merging: %lf sec.\n", duration);
- }
-
- // deallocates memory:
- delete [] tmpVertices;
- delete [] tmpIndices;
+ // tmp arrays used to store the sorted data:
+ float *tmpVertices;
+ unsigned *tmpIndices;
+
+ Chronometer chrono;
+ // Sort data
+ chrono.start();
+ GeomCleaner::SortIndexedVertexArray(
+ iVertices, iVSize, iIndices, iISize, &tmpVertices, &tmpIndices);
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Sorting: %lf sec.\n", chrono.stop());
+ }
+
+ // compress data
+ chrono.start();
+ GeomCleaner::CompressIndexedVertexArray(
+ tmpVertices, iVSize, tmpIndices, iISize, oVertices, oVSize, oIndices);
+ real duration = chrono.stop();
+ if (G.debug & G_DEBUG_FREESTYLE) {
+ printf("Merging: %lf sec.\n", duration);
+ }
+
+ // 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, float **oVertices, unsigned *oVSize, unsigned **oIndices)
+void GeomCleaner::CleanIndexedVertexArray(const float *iVertices,
+ unsigned iVSize,
+ const unsigned *iIndices,
+ unsigned iISize,
+ float **oVertices,
+ unsigned *oVSize,
+ unsigned **oIndices)
{
- typedef map<Vec3f, unsigned> cleanHashTable;
- vector<Vec3f> vertices;
- unsigned i;
- for (i = 0; i < iVSize; i += 3)
- vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
-
- cleanHashTable ht;
- vector<unsigned> newIndices;
- vector<Vec3f> newVertices;
-
- // elimination of needless points
- unsigned currentIndex = 0;
- vector<Vec3f>::const_iterator v = vertices.begin();
- vector<Vec3f>::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 float[*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<Vec3f, unsigned> cleanHashTable;
+ vector<Vec3f> vertices;
+ unsigned i;
+ for (i = 0; i < iVSize; i += 3)
+ vertices.push_back(Vec3f(iVertices[i], iVertices[i + 1], iVertices[i + 2]));
+
+ cleanHashTable ht;
+ vector<unsigned> newIndices;
+ vector<Vec3f> newVertices;
+
+ // elimination of needless points
+ unsigned currentIndex = 0;
+ vector<Vec3f>::const_iterator v = vertices.begin();
+ vector<Vec3f>::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 float[*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];
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/GeomCleaner.h b/source/blender/freestyle/intern/geometry/GeomCleaner.h
index 32bcc244f69..b34828f87a9 100644
--- a/source/blender/freestyle/intern/geometry/GeomCleaner.h
+++ b/source/blender/freestyle/intern/geometry/GeomCleaner.h
@@ -27,204 +27,225 @@
#include "../system/FreestyleConfig.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
using namespace Geometry;
-class 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, float **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 float *iVertices, unsigned iVSize, const unsigned *iIndices,
- unsigned iISize, float **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, float **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, float **oVertices, unsigned *oVSize, unsigned **oIndices);
+class 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,
+ float **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 float *iVertices,
+ unsigned iVSize,
+ const unsigned *iIndices,
+ unsigned iISize,
+ float **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,
+ float **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,
+ float **oVertices,
+ unsigned *oVSize,
+ unsigned **oIndices);
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GeomCleaner")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GeomCleaner")
#endif
};
-
/*! 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 IndexedVertex
-{
-private:
- Vec3f _Vector;
- unsigned _index;
-
-public:
- inline IndexedVertex() {}
-
- inline IndexedVertex(Vec3f iVector, unsigned iIndex)
- {
- _Vector = iVector;
- _index = iIndex;
- }
-
- /*! accessors */
- inline const Vec3f& vector() const
- {
- return _Vector;
- }
-
- inline unsigned index()
- {
- return _index;
- }
-
- inline float x()
- {
- return _Vector[0];
- }
-
- inline float y()
- {
- return _Vector[1];
- }
-
- inline float z()
- {
- return _Vector[2];
- }
-
- /*! modifiers */
- inline void setVector(const Vec3f& 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 float 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);
- }
+class IndexedVertex {
+ private:
+ Vec3f _Vector;
+ unsigned _index;
+
+ public:
+ inline IndexedVertex()
+ {
+ }
+
+ inline IndexedVertex(Vec3f iVector, unsigned iIndex)
+ {
+ _Vector = iVector;
+ _index = iIndex;
+ }
+
+ /*! accessors */
+ inline const Vec3f &vector() const
+ {
+ return _Vector;
+ }
+
+ inline unsigned index()
+ {
+ return _index;
+ }
+
+ inline float x()
+ {
+ return _Vector[0];
+ }
+
+ inline float y()
+ {
+ return _Vector[1];
+ }
+
+ inline float z()
+ {
+ return _Vector[2];
+ }
+
+ /*! modifiers */
+ inline void setVector(const Vec3f &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 float 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);
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:IndexedVertex")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:IndexedVertex")
#endif
};
#if 0
bool operator<(const IndexedVertex& iv1, const IndexedVertex& iv2)
{
- return iv1.operator<(iv2);
+ return iv1.operator<(iv2);
}
#endif
} /* namespace Freestyle */
-#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 da7774d3843..2ac83526268 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.cpp
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.cpp
@@ -28,166 +28,172 @@ 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)
+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);
+ 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)
+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;
+ 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)
+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);
+ 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)
+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
+ 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 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];
+ // 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);
+ // 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 = b1 * c2 - b2 * c1;
+ res[0] = num / denom;
- num = a2 * c1 - a1 * c2;
- res[1] = num / denom;
+ num = a2 * c1 - a1 * c2;
+ res[1] = num / denom;
- return (DO_INTERSECT);
+ return (DO_INTERSECT);
}
-intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2, const Vec2r& p3, const Vec2r& p4,
- real& t, real& u, real epsilon)
+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
+ 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 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;
+ // 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);
+ // 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 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;
+ // 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);
+ // 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);
+ // Line segments intersect: compute intersection point.
+ denom = a1 * b2 - a2 * b1;
+ if (fabs(denom) < epsilon)
+ return (COLINEAR);
- real d1, e1;
+ real d1, e1;
- d1 = p1[1] - p3[1];
- e1 = p1[0] - p3[0];
+ d1 = p1[1] - p3[1];
+ e1 = p1[0] - p3[0];
- num = -b2 * d1 - a2 * e1;
- t = num / denom;
+ num = -b2 * d1 - a2 * e1;
+ t = num / denom;
- num = -b1 * d1 - a1 * e1;
- u = num / denom;
+ num = -b1 * d1 - a1 * e1;
+ u = num / denom;
- return (DO_INTERSECT);
+ return (DO_INTERSECT);
}
// AABB-triangle overlap test code by Tomas Akenine-Möller
@@ -204,198 +210,205 @@ intersection_test intersect2dSeg2dSegParametric(const Vec2r& p1, const Vec2r& p2
#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; \
- } (void)0
+ { \
+ 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
+#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
+#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
+#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);
+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])
+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
+ 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
@@ -409,271 +422,287 @@ bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3])
// 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)
+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;
+ 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
// The plane is represented by a set of points P implicitly defined as dot(norm, P) + d = 0.
// The ray is represented as r(t) = orig + dir * t.
-intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, const Vec3r& norm, const real d,
- real& t, const real epsilon)
+intersection_test intersectRayPlane(const Vec3r &orig,
+ const Vec3r &dir,
+ const Vec3r &norm,
+ const real d,
+ real &t,
+ const real epsilon)
{
- real denom = norm * dir;
+ 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;
- }
+ 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;
+ t = -(d + (norm * orig)) / denom;
- if (t < 0.0f)
- return DONT_INTERSECT;
+ if (t < 0.0f)
+ return DONT_INTERSECT;
- return DO_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
+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));
+ 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)
+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 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
+ Vec3r N(AB ^ BC); // triangle's normal
- N.normalize();
+ N.normalize();
- Vec3r J(AB ^ AP), K(BC ^ BP), L(CA ^ CP);
- J.normalize();
- K.normalize();
- L.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 (J * N < 0)
+ return false; // on the right of AB
- if (K * N < 0)
- return false; // on the right of BC
+ if (K * N < 0)
+ return false; // on the right of BC
- if (L * N < 0)
- return false; // on the right of CA
+ if (L * N < 0)
+ return false; // on the right of CA
- return true;
+ return true;
}
-void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res)
+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();
+ 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)
+void transformVertices(const vector<Vec3r> &vertices, const Matrix44r &trans, vector<Vec3r> &res)
{
- size_t i;
- res.resize(vertices.size());
- for (i = 0; i < vertices.size(); i++) {
- transformVertex(vertices[i], trans, res[i]);
- }
+ size_t i;
+ res.resize(vertices.size());
+ for (i = 0; i < vertices.size(); i++) {
+ transformVertex(vertices[i], trans, res[i]);
+ }
}
-Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v)
+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;
+ 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 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])
+void fromWorldToCamera(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4])
{
- fromCoordAToCoordB(p, q, model_view_matrix);
+ fromCoordAToCoordB(p, q, model_view_matrix);
}
-void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4])
+void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4])
{
- fromCoordAToCoordB(p, q, projection_matrix);
+ fromCoordAToCoordB(p, q, projection_matrix);
}
-void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4])
+void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4])
{
- // winX:
- q[0] = viewport[0] + viewport[2] * (p[0] + 1.0) / 2.0;
+ // 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;
+ // winY:
+ q[1] = viewport[1] + viewport[3] * (p[1] + 1.0) / 2.0;
- // winZ:
- q[2] = (p[2] + 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])
+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];
+ 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])
+void fromWorldToImage(const Vec3r &p, Vec3r &q, const real transform[4][4], const int viewport[4])
{
- fromCoordAToCoordB(p, q, transform);
+ fromCoordAToCoordB(p, q, transform);
- // winX:
- q[0] = viewport[0] + viewport[2] * (q[0] + 1.0) / 2.0;
+ // 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;
+ //winY:
+ q[1] = viewport[1] + viewport[3] * (q[1] + 1.0) / 2.0;
}
-void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4])
+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;
+ 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])
+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;
- }
+ 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;
+ }
}
-void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4])
+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]);
- }
+ 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]);
+ }
}
-
//
// Internal code
//
@@ -685,92 +714,92 @@ void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4]
// 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
+#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;
+ 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;
}
-inline bool overlapPlaneBox(Vec3r& normal, real d, Vec3r& maxbox)
+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;
+ 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 void fromCoordAToCoordB(const Vec3r&p, Vec3r& q, const real transform[4][4])
+inline void fromCoordAToCoordB(const Vec3r &p, Vec3r &q, const real transform[4][4])
{
- HVec3r hp(p);
- HVec3r hq(0, 0, 0, 0);
-
- for (unsigned int i = 0; i < 4; i++) {
- for (unsigned int j = 0; j < 4; j++) {
- hq[i] += transform[i][j] * hp[j];
- }
- }
-
- if (hq[3] == 0) {
- q = p;
- return;
- }
-
- for (unsigned int k = 0; k < 3; k++)
- q[k] = hq[k] / hq[3];
+ HVec3r hp(p);
+ HVec3r hq(0, 0, 0, 0);
+
+ for (unsigned int i = 0; i < 4; i++) {
+ for (unsigned int j = 0; j < 4; j++) {
+ hq[i] += transform[i][j] * hp[j];
+ }
+ }
+
+ if (hq[3] == 0) {
+ q = p;
+ return;
+ }
+
+ for (unsigned int k = 0; k < 3; k++)
+ q[k] = hq[k] / hq[3];
}
-} // end of namespace GeomUtils
+} // end of namespace GeomUtils
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/GeomUtils.h b/source/blender/freestyle/intern/geometry/GeomUtils.h
index 94904b72ff1..42ef9612074 100644
--- a/source/blender/freestyle/intern/geometry/GeomUtils.h
+++ b/source/blender/freestyle/intern/geometry/GeomUtils.h
@@ -42,28 +42,27 @@ namespace GeomUtils {
/////////////////////////////////////////////////////////////////////////////
/*! 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)
+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;
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
- real c1(AB * AP);
- if (c1 <= 0)
- return AP.norm();
+ real c1(AB * AP);
+ if (c1 <= 0)
+ return AP.norm();
- real c2(AB * AB);
- if (c2 <= c1)
- return BP.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;
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
- return PPb.norm();
+ return PPb.norm();
}
//
@@ -71,67 +70,83 @@ real distPointSegment(const T& P, const T& A, const T& B)
//
/////////////////////////////////////////////////////////////////////////////
typedef enum {
- DONT_INTERSECT,
- DO_INTERSECT,
- COLINEAR,
- COINCIDENT,
+ DONT_INTERSECT,
+ DO_INTERSECT,
+ COLINEAR,
+ COINCIDENT,
} intersection_test;
-intersection_test intersect2dSeg2dSeg(const Vec2r& p1, const Vec2r& p2, // first segment
- const Vec2r& p3, const Vec2r& p4, // second segment
- Vec2r& res); // found intersection point
-
-intersection_test intersect2dLine2dLine(const Vec2r& p1, const Vec2r& p2, // first segment
- const Vec2r& p3, const Vec2r& p4, // second segment
- Vec2r& res); // found intersection point
-
-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
+intersection_test intersect2dSeg2dSeg(const Vec2r &p1,
+ const Vec2r &p2, // first segment
+ const Vec2r &p3,
+ const Vec2r &p4, // second segment
+ Vec2r &res); // found intersection point
+
+intersection_test intersect2dLine2dLine(const Vec2r &p1,
+ const Vec2r &p2, // first segment
+ const Vec2r &p3,
+ const Vec2r &p4, // second segment
+ Vec2r &res); // found intersection point
+
+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 */
-bool intersect2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+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 */
-bool include2dSeg2dArea(const Vec2r& min, const Vec2r& max, const Vec2r& A, const Vec2r& B);
+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 */
-bool overlapTriangleBox(Vec3r& boxcenter, Vec3r& boxhalfsize, Vec3r triverts[3]);
+bool overlapTriangleBox(Vec3r &boxcenter, Vec3r &boxhalfsize, Vec3r triverts[3]);
/*! Fast, Minimum Storage Ray-Triangle Intersection, adapted from Tomas Möller and Ben Trumbore code. */
-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
+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 */
-intersection_test intersectRayPlane(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
+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
+ 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.
*/
-bool intersectRayBBox(const Vec3r& orig, const Vec3r& dir, // ray origin and direction
- const Vec3r& boxMin, const Vec3r& boxMax, // the bbox
+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
+ 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 */
-bool includePointTriangle(const Vec3r& P, const Vec3r& A, const Vec3r& B, const Vec3r& C);
+bool includePointTriangle(const Vec3r &P, const Vec3r &A, const Vec3r &B, const Vec3r &C);
-void transformVertex(const Vec3r& vert, const Matrix44r& matrix, Vec3r& res);
+void transformVertex(const Vec3r &vert, const Matrix44r &matrix, Vec3r &res);
-void transformVertices(const vector<Vec3r>& vertices, const Matrix44r& trans, vector<Vec3r>& res);
+void transformVertices(const vector<Vec3r> &vertices, const Matrix44r &trans, vector<Vec3r> &res);
-Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
+Vec3r rotateVector(const Matrix44r &mat, const Vec3r &v);
//
// Coordinates systems changing procedures
@@ -152,7 +167,10 @@ Vec3r rotateVector(const Matrix44r& mat, const Vec3r& v);
* viewport
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
*/
-void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4], const real projection_matrix[4][4],
+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
@@ -166,7 +184,7 @@ void fromWorldToImage(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][
* viewport
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport)
*/
-void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], const int viewport[4]);
+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
@@ -179,7 +197,7 @@ void fromWorldToImage(const Vec3r& p, Vec3r& q, const real transform[4][4], cons
* The model view matrix expressed in line major order (OpenGL
* matrices are column major ordered)
*/
-void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
+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.
@@ -191,7 +209,7 @@ void fromWorldToCamera(const Vec3r& p, Vec3r& q, const real model_view_matrix[4]
* The projection matrix expressed in line major order (OpenGL
* matrices are column major ordered)
*/
-void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4][4]);
+void fromCameraToRetina(const Vec3r &p, Vec3r &q, const real projection_matrix[4][4]);
/*! From retina to image.
* Returns the coordinates expressed in Image coordinates system.
@@ -202,7 +220,7 @@ void fromCameraToRetina(const Vec3r& p, Vec3r& q, const real projection_matrix[4
* viewport
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
*/
-void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4]);
+void fromRetinaToImage(const Vec3r &p, Vec3r &q, const int viewport[4]);
/*! From image to retina
* p
@@ -212,7 +230,7 @@ void fromRetinaToImage(const Vec3r& p, Vec3r& q, const int viewport[4]);
* viewport
* The viewport: x,y coordinates followed by width and height (OpenGL like viewport).
*/
-void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4]);
+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.
@@ -226,7 +244,7 @@ void fromImageToRetina(const Vec3r& p, Vec3r& q, const int viewport[4]);
* The projection matrix expressed in line major order (OpenGL
* matrices are column major ordered)
*/
-void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real z, const real projection_matrix[4][4]);
+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
@@ -239,10 +257,10 @@ void fromRetinaToCamera(const Vec3r& p, Vec3r& q, real z, const real projection_
* The model view matrix expressed in line major order (OpenGL
* matrices are column major ordered)
*/
-void fromCameraToWorld(const Vec3r& p, Vec3r& q, const real model_view_matrix[4][4]);
+void fromCameraToWorld(const Vec3r &p, Vec3r &q, const real model_view_matrix[4][4]);
-} // end of namespace GeomUtils
+} // end of namespace GeomUtils
} /* namespace Freestyle */
-#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 e7d3cf1a8cc..6a95e540c79 100644
--- a/source/blender/freestyle/intern/geometry/Grid.cpp
+++ b/source/blender/freestyle/intern/geometry/Grid.cpp
@@ -32,352 +32,356 @@ namespace Freestyle {
/////////////////
void allOccludersGridVisitor::examineOccluder(Polygon3r *occ)
{
- occluders_.push_back(occ);
+ occluders_.push_back(occ);
}
-static bool inBox(const Vec3r& inter, const Vec3r& box_min, const Vec3r& box_max)
+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;
+ 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_))
- {
+ // 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)) {
+ 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_) {
+ if (tmp_t < t_) {
#endif
- occluder_ = occ;
- u_ = tmp_u;
- v_ = tmp_v;
- t_ = tmp_t;
- }
- }
- else {
- occ->userdata2 = 0;
- }
- }
- }
+ occluder_ = occ;
+ u_ = tmp_u;
+ v_ = tmp_v;
+ t_ = tmp_t;
+ }
+ }
+ else {
+ occ->userdata2 = 0;
+ }
+ }
}
+} // namespace Freestyle
bool firstIntersectionGridVisitor::stop()
{
- if (occluder_)
- return true;
- return false;
+ 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();
- }
-
- _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();
+ 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)
+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];
+ _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];
}
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);
- }
- }
- }
- }
+ 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)
+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;
+ 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)
+void Grid::castRay(const Vec3r &orig,
+ const Vec3r &end,
+ OccludersSet &occluders,
+ unsigned timestamp)
{
- initRay(orig, end, timestamp);
- allOccludersGridVisitor visitor(occluders);
- castRayInternal(visitor);
+ initRay(orig, end, timestamp);
+ allOccludersGridVisitor visitor(occluders);
+ castRayInternal(visitor);
}
-void Grid::castInfiniteRay(const Vec3r& orig, const Vec3r& dir, OccludersSet& occluders, unsigned timestamp)
+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);
+ 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 *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.
- // 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;
+ 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.
+ // 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;
}
-void Grid::initRay (const Vec3r &orig, const Vec3r& end, unsigned timestamp)
+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();
+ _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)
+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)) {
- BLI_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;
+ _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)) {
+ BLI_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;
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/Grid.h b/source/blender/freestyle/intern/geometry/Grid.h
index c3a0f16a354..a2b64a446b6 100644
--- a/source/blender/freestyle/intern/geometry/Grid.h
+++ b/source/blender/freestyle/intern/geometry/Grid.h
@@ -22,9 +22,9 @@
* \brief Base class to define a cell grid surrounding the bounding box of the scene
*/
-#include <cstring> // for memset
+#include <cstring> // for memset
#include <float.h>
-#include <stdint.h> // For POINTER_FROM_UINT, i.e. uintptr_t.
+#include <stdint.h> // For POINTER_FROM_UINT, i.e. uintptr_t.
#include <vector>
#include "Geom.h"
@@ -34,11 +34,11 @@
#include "../system/FreestyleConfig.h"
extern "C" {
- #include "BLI_utildefines.h"
+#include "BLI_utildefines.h"
}
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
using namespace std;
@@ -47,119 +47,142 @@ namespace Freestyle {
using namespace Geometry;
-typedef vector<Polygon3r*> OccludersSet;
+typedef vector<Polygon3r *> OccludersSet;
//
// Class to define cells used by the regular grid
//
///////////////////////////////////////////////////////////////////////////////
-class 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;
+class 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;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Cell")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Cell")
#endif
};
+class GridVisitor {
+ public:
+ virtual ~GridVisitor(){}; //soc
-class GridVisitor
-{
-public:
- virtual ~GridVisitor() {}; //soc
+ virtual void discoverCell(Cell * /*cell*/)
+ {
+ }
- virtual void discoverCell(Cell * /*cell*/) {}
+ virtual void examineOccluder(Polygon3r * /*occ*/)
+ {
+ }
- virtual void examineOccluder(Polygon3r * /*occ*/) {}
+ virtual void finishCell(Cell * /*cell*/)
+ {
+ }
- virtual void finishCell(Cell * /*cell*/) {}
-
- virtual bool stop() {
- return false;
- }
+ virtual bool stop()
+ {
+ return false;
+ }
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridVisitor")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridVisitor")
#endif
};
/*! 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);
-
- OccludersSet& occluders() {
- return occluders_;
- }
-
- void clear() {
- occluders_.clear();
- }
-
-private:
- OccludersSet& occluders_;
+class allOccludersGridVisitor : public GridVisitor {
+ public:
+ allOccludersGridVisitor(OccludersSet &occluders) : GridVisitor(), occluders_(occluders)
+ {
+ }
+
+ virtual void examineOccluder(Polygon3r *occ);
+
+ OccludersSet &occluders()
+ {
+ return occluders_;
+ }
+
+ void clear()
+ {
+ occluders_.clear();
+ }
+
+ private:
+ OccludersSet &occluders_;
};
/*! Finds the first intersection and breaks.
* The occluder and the intersection information are stored and accessible.
*/
-class firstIntersectionGridVisitor : public GridVisitor
-{
-//soc - changed order to remove warnings
-public:
- double u_, v_, t_;
-
-private:
- Polygon3r *occluder_;
- Vec3r ray_org_, ray_dir_, cell_size_;
- 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_;
- }
+class firstIntersectionGridVisitor : public GridVisitor {
+ //soc - changed order to remove warnings
+ public:
+ double u_, v_, t_;
+
+ private:
+ Polygon3r *occluder_;
+ Vec3r ray_org_, ray_dir_, cell_size_;
+ 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_;
+ }
};
//
@@ -167,204 +190,218 @@ public:
//
///////////////////////////////////////////////////////////////////////////////
-class 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 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 constituting 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 (POINTER_AS_UINT((*it)->userdata2) != _timestamp) {
- (*it)->userdata2 = POINTER_FROM_UINT(_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
+class 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 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 constituting 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 (POINTER_AS_UINT((*it)->userdata2) != _timestamp) {
+ (*it)->userdata2 = POINTER_FROM_UINT(_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
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Grid")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Grid")
#endif
};
@@ -374,22 +411,22 @@ protected:
///////////////////////////////////////////////////////////////////////////////
class VirtualOccludersSet {
-public:
- VirtualOccludersSet(Grid& _grid) : grid (_grid) {};
- Polygon3r *begin();
- Polygon3r *next();
- Polygon3r *next(bool stopOnNewCell);
+ public:
+ VirtualOccludersSet(Grid &_grid) : grid(_grid){};
+ Polygon3r *begin();
+ Polygon3r *next();
+ Polygon3r *next(bool stopOnNewCell);
-private:
- Polygon3r *firstOccluderFromNextCell();
- Grid& grid;
- OccludersSet::iterator it, end;
+ private:
+ Polygon3r *firstOccluderFromNextCell();
+ Grid &grid;
+ OccludersSet::iterator it, end;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VirtualOccludersSet")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VirtualOccludersSet")
#endif
};
} /* namespace Freestyle */
-#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 09820043136..1f87bb7b76a 100644
--- a/source/blender/freestyle/intern/geometry/GridHelpers.cpp
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.cpp
@@ -25,23 +25,23 @@ namespace Freestyle {
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
- 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.
- const real borderZone = 0.0;
- viewProscenium[0] = g_freestyle.viewport[2] * (borderZone - bufferZone);
- viewProscenium[1] = g_freestyle.viewport[2] * (1.0f - borderZone + bufferZone);
- viewProscenium[2] = g_freestyle.viewport[3] * (borderZone - bufferZone);
- viewProscenium[3] = g_freestyle.viewport[3] * (1.0f - borderZone + bufferZone);
+ // 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
+ 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.
+ const real borderZone = 0.0;
+ viewProscenium[0] = g_freestyle.viewport[2] * (borderZone - bufferZone);
+ viewProscenium[1] = g_freestyle.viewport[2] * (1.0f - borderZone + bufferZone);
+ viewProscenium[2] = g_freestyle.viewport[3] * (borderZone - bufferZone);
+ viewProscenium[3] = g_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 6b0f55e3d6f..8a7503350a3 100644
--- a/source/blender/freestyle/intern/geometry/GridHelpers.h
+++ b/source/blender/freestyle/intern/geometry/GridHelpers.h
@@ -32,7 +32,7 @@
#include "../winged_edge/WEdge.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
@@ -40,175 +40,177 @@ namespace Freestyle {
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)
+template<class T> T closestPointToSegment(const T &P, const T &A, const T &B, real &distance)
{
- T AB, AP, BP;
- AB = B - A;
- AP = P - A;
- BP = P - B;
-
- real c1(AB * AP);
- if (c1 <= 0) {
- distance = AP.norm();
- return A; // A is closest point
- }
-
- real c2(AB * AB);
- if (c2 <= c1) {
- distance = BP.norm();
- return B; // B is closest point
- }
-
- real b = c1 / c2;
- T Pb, PPb;
- Pb = A + b * AB;
- PPb = P - Pb;
-
- distance = PPb.norm();
- return Pb; // closest point lies on AB
+ T AB, AP, BP;
+ AB = B - A;
+ AP = P - A;
+ BP = P - B;
+
+ real c1(AB * AP);
+ if (c1 <= 0) {
+ distance = AP.norm();
+ return A; // A is closest point
+ }
+
+ real c2(AB * AB);
+ if (c2 <= c1) {
+ distance = BP.norm();
+ return B; // B is closest point
+ }
+
+ real b = c1 / c2;
+ T Pb, PPb;
+ Pb = A + b * AB;
+ PPb = P - Pb;
+
+ 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)) {
- 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 int i = 0; i < 2; ++i) {
- real t;
- Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
- if (t < distance) {
- distance = t;
- closest = p;
- }
- }
- return closest;
+ // 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 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 int i = 0; i < 2; ++i) {
+ real t;
+ Vec3r p = closestPointToSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1], t);
+ if (t < distance) {
+ distance = t;
+ closest = p;
+ }
+ }
+ 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;
- }
-
- // 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 int i = 0; i < 2; ++i) {
- real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
- if (t < distance) {
- distance = t;
- }
- }
- return distance;
+ // 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;
+ }
+
+ // 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 int i = 0; i < 2; ++i) {
+ real t = GeomUtils::distPointSegment(point, poly.getVertices()[i], poly.getVertices()[i + 1]);
+ if (t < distance) {
+ distance = t;
+ }
+ }
+ return distance;
}
-class Transform
-{
-public:
- virtual ~Transform () = 0;
- virtual Vec3r operator()(const Vec3r& point) const = 0;
+class Transform {
+ public:
+ virtual ~Transform() = 0;
+ virtual Vec3r operator()(const Vec3r &point) const = 0;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridHelpers:Transform")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:GridHelpers:Transform")
#endif
};
-inline bool insideProscenium (const real proscenium[4], const Polygon3r& polygon)
+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]) {
- 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),
- };
- return GeomUtils::overlapTriangleBox(boxCenter, boxHalfSize, triverts);
+ // 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]) {
+ 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),
+ };
+ 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++) {
- points.push_back((*woe)->GetaVertex()->GetVertex());
- }
-
- return points;
+ vector<Vec3r> points;
+ // Iterate over vertices, storing projections in points
+ for (vector<WOEdge *>::const_iterator woe = fedges.begin(), woend = fedges.end(); woe != woend;
+ woe++) {
+ points.push_back((*woe)->GetaVertex()->GetVertex());
+ }
+
+ return points;
}
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);
+ Vec3r bbMin, bbMax;
+ polygon.getBBox(bbMin, bbMax);
- const real epsilon = 1.0e-6;
+ const real epsilon = 1.0e-6;
- if (bbMin[0] <= proscenium[0]) {
- proscenium[0] = bbMin[0] - epsilon;
- }
+ if (bbMin[0] <= proscenium[0]) {
+ proscenium[0] = bbMin[0] - epsilon;
+ }
- if (bbMin[1] <= proscenium[2]) {
- proscenium[2] = bbMin[1] - epsilon;
- }
+ if (bbMin[1] <= proscenium[2]) {
+ proscenium[2] = bbMin[1] - epsilon;
+ }
- if (bbMax[0] >= proscenium[1]) {
- proscenium[1] = bbMax[0] + epsilon;
- }
+ if (bbMax[0] >= proscenium[1]) {
+ proscenium[1] = bbMax[0] + epsilon;
+ }
- if (bbMax[1] >= proscenium[3]) {
- proscenium[3] = bbMax[1] + epsilon;
- }
+ 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;
+ const real epsilon = 1.0e-6;
- if (point[0] <= proscenium[0]) {
- proscenium[0] = point[0] - epsilon;
- }
+ if (point[0] <= proscenium[0]) {
+ proscenium[0] = point[0] - epsilon;
+ }
- if (point[1] <= proscenium[2]) {
- proscenium[2] = point[1] - epsilon;
- }
+ if (point[1] <= proscenium[2]) {
+ proscenium[2] = point[1] - epsilon;
+ }
- if (point[0] >= proscenium[1]) {
- proscenium[1] = point[0] + epsilon;
- }
+ if (point[0] >= proscenium[1]) {
+ proscenium[1] = point[0] + epsilon;
+ }
- if (point[1] >= proscenium[3]) {
- proscenium[3] = point[1] + epsilon;
- }
+ if (point[1] >= proscenium[3]) {
+ proscenium[3] = point[1] + epsilon;
+ }
}
-}; // GridHelpers namespace
+}; // namespace GridHelpers
} /* namespace Freestyle */
-#endif // __GRIDHELPERS_H__
+#endif // __GRIDHELPERS_H__
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.cpp b/source/blender/freestyle/intern/geometry/HashGrid.cpp
index 4011dabe1f5..bc24290c92a 100644
--- a/source/blender/freestyle/intern/geometry/HashGrid.cpp
+++ b/source/blender/freestyle/intern/geometry/HashGrid.cpp
@@ -25,20 +25,20 @@ namespace Freestyle {
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)
+void HashGrid::configure(const Vec3r &orig, const Vec3r &size, unsigned nb)
{
- Grid::configure(orig, size, nb);
+ Grid::configure(orig, size, nb);
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/HashGrid.h b/source/blender/freestyle/intern/geometry/HashGrid.h
index 289079fe0d9..b1fc4824b6f 100644
--- a/source/blender/freestyle/intern/geometry/HashGrid.h
+++ b/source/blender/freestyle/intern/geometry/HashGrid.h
@@ -23,13 +23,13 @@
*/
#if 0
-# if defined(__GNUC__) && (__GNUC__ >= 3)
+# 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>
@@ -39,69 +39,69 @@
namespace Freestyle {
/*! 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 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;
- }
-
-protected:
- GridHashTable _cells;
+class 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;
+ }
+
+ protected:
+ GridHashTable _cells;
};
} /* namespace Freestyle */
-#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 0764c89c8a3..09c29025d15 100644
--- a/source/blender/freestyle/intern/geometry/Noise.cpp
+++ b/source/blender/freestyle/intern/geometry/Noise.cpp
@@ -31,242 +31,243 @@ namespace Freestyle {
#define SCURVE(a) ((a) * (a) * (3.0 - 2.0 * (a)))
#if 0 // XXX Unused
-#define REALSCALE (2.0 / 65536.0)
-#define NREALSCALE (2.0 / 4096.0)
+# 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 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 MAXSIZE 500
+# define NRAND() ((float)rand() / (float)RAND_MAX)
#endif
#define SEEDNRAND(x) (srand(x * RAND_MAX))
#define BM 0xff
-#define N 0x1000
-#if 0 // XXX Unused
-#define NP 12 /* 2^N */
-#define NM 0xfff
+#define N 0x1000
+#if 0 // XXX Unused
+# define NP 12 /* 2^N */
+# define NM 0xfff
#endif
#define LERP(t, a, b) ((a) + (t) * ((b) - (a)))
#define SETUP(i, b0, b1, r0, r1) \
- { \
- (t) = (i) + (N); \
- (r0) = modff((t), &(u)); \
- (r1) = (r0) - 1.0; \
- (b0) = ((int)(u)) & BM; \
- (b1) = ((b0) + 1) & BM; \
- } (void)0
+ { \
+ (t) = (i) + (N); \
+ (r0) = modff((t), &(u)); \
+ (r1) = (r0)-1.0; \
+ (b0) = ((int)(u)) & BM; \
+ (b1) = ((b0) + 1) & BM; \
+ } \
+ (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 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 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 = SCURVE(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)
+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;
- 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;
+ 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 = SCURVE(rx0);
+ sy = SCURVE(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)
+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;
- 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;
+ 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 = SCURVE(rx0);
+ sy = SCURVE(ry0);
+ sz = SCURVE(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];
+ }
}
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/Noise.h b/source/blender/freestyle/intern/geometry/Noise.h
index 6787e098306..18992092b19 100644
--- a/source/blender/freestyle/intern/geometry/Noise.h
+++ b/source/blender/freestyle/intern/geometry/Noise.h
@@ -27,7 +27,7 @@
#include "../system/FreestyleConfig.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
using namespace std;
@@ -39,46 +39,47 @@ namespace Freestyle {
using namespace Geometry;
/*! Class to provide Perlin Noise functionalities */
-class Noise
-{
-public:
- /*! Builds a Noise object */
- Noise(long seed = -1);
+class Noise {
+ public:
+ /*! 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 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 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 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];
- /* UNUSED */
- // int start;
+ 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];
+ /* UNUSED */
+ // int start;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Noise")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Noise")
#endif
};
} /* namespace Freestyle */
-#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 b2359f82477..ad8a947d21d 100644
--- a/source/blender/freestyle/intern/geometry/Polygon.h
+++ b/source/blender/freestyle/intern/geometry/Polygon.h
@@ -28,7 +28,7 @@
#include "GeomUtils.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
using namespace std;
@@ -37,184 +37,193 @@ namespace Freestyle {
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 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;
+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 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;
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Geometry:Polygon")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Geometry:Polygon")
#endif
};
-
//
// 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
- {
+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 0
- if (_vertices.size() < 3)
- return false;
+ if (_vertices.size() < 3)
+ return false;
#endif
- return GeomUtils::intersectRayTriangle(orig, dir, _vertices[0], _vertices[1], _vertices[2], t, u, v, epsilon);
- }
+ return GeomUtils::intersectRayTriangle(
+ orig, dir, _vertices[0], _vertices[1], _vertices[2], t, u, v, epsilon);
+ }
-private:
- Vec3r _normal;
+ private:
+ Vec3r _normal;
};
-} // end of namespace Geometry
+} // end of namespace Geometry
} /* namespace Freestyle */
-#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 d7e3badbe3a..04797bc8998 100644
--- a/source/blender/freestyle/intern/geometry/SweepLine.h
+++ b/source/blender/freestyle/intern/geometry/SweepLine.h
@@ -26,314 +26,318 @@
#include <vector>
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
/*! 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;
- }
-
-public:
- 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.
+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;
+ }
+
+ public:
+ 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.
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Intersection")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Intersection")
#endif
};
#ifdef _MSC_VER
-#pragma warning(push)
-#pragma warning(disable: 4521) // disable warning C4521: multiple copy constructors specified
+# pragma warning(push)
+# pragma warning(disable : 4521) // disable warning C4521: multiple copy constructors specified
#endif
-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.
+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.
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Segment")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:Segment")
#endif
};
#ifdef _MSC_VER
-#pragma warning(pop)
+# pragma warning(pop)
#endif
/*! 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
-{
- 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;
- }
+template<class T1, class T2> 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;
+ }
};
-
-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,
+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,
#if 0
- binary_rule<Segment<T, Point>,Segment<T, Point> >& binrule = \
- binary_rule<Segment<T, Point>, Segment<T, Point> >(),
+ 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,
+ 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,
+ 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> >(),
+ 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,
+ 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.
+ 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.
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SweepLine")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SweepLine")
#endif
};
} /* namespace Freestyle */
-#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 2dd5c3f6718..22fcd3aef41 100644
--- a/source/blender/freestyle/intern/geometry/VecMat.h
+++ b/source/blender/freestyle/intern/geometry/VecMat.h
@@ -27,7 +27,7 @@
#include <vector>
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
@@ -35,15 +35,15 @@ namespace Freestyle {
namespace VecMat {
namespace Internal {
- template <bool B>
- struct is_false {};
+template<bool B> struct is_false {
+};
- template <>
- struct is_false<false>
- {
- static inline void ensure() {}
- };
-} // end of namespace Internal
+template<> struct is_false<false> {
+ static inline void ensure()
+ {
+ }
+};
+} // end of namespace Internal
//
// Vector class
@@ -52,571 +52,566 @@ namespace Internal {
//
/////////////////////////////////////////////////////////////////////////////
-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,
- };
+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,
+ };
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VecMat:Vec")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VecMat:Vec")
#endif
};
-
//
// 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;
- }
+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;
+ }
};
-
//
// 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];
- }
+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 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;
- }
+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;
+ }
};
-
//
// Matrix class
// - T: value type
@@ -628,137 +623,127 @@ public:
// 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];
- }
- *this = res;
- return *this;
- }
-
- 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];
+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];
+ }
+ *this = res;
+ return *this;
+ }
+
+ 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];
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VecMat:Matrix")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:VecMat:Matrix")
#endif
};
@@ -774,30 +759,33 @@ protected:
// 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 int i = 0; i < N; i++)
- res(i, i) = 1;
- return res;
- }
+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 int i = 0; i < N; i++)
+ res(i, i) = 1;
+ return res;
+ }
};
#undef _SIZE
@@ -811,75 +799,74 @@ public:
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;
+ 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;
+ 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;
+ 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)
+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;
+ 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;
+ 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;
+ 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;
+ 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)
+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;
+ unsigned int i;
+ s << "[";
+ for (i = 0; i < N - 1; i++)
+ s << v[i] << ", ";
+ s << v[i] << "]";
+ return s;
}
//
@@ -887,93 +874,96 @@ inline std::ostream& operator<<(std::ostream& s, const Vec<T, N>& v)
//
/////////////////////////////////////////////////////////////////////////////
-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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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)
+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;
+ 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
+} // end of namespace VecMat
} /* namespace Freestyle */
-#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 44490f4bde5..811b10813d1 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.cpp
+++ b/source/blender/freestyle/intern/geometry/matrix_util.cpp
@@ -39,222 +39,222 @@ 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
-
- // back from Fortran 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;
- }
+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 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
+} // namespace MatrixUtil
-} // OGF namespace
+} // namespace OGF
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/matrix_util.h b/source/blender/freestyle/intern/geometry/matrix_util.h
index b587a9e5738..65e2fee84f3 100644
--- a/source/blender/freestyle/intern/geometry/matrix_util.h
+++ b/source/blender/freestyle/intern/geometry/matrix_util.h
@@ -40,25 +40,25 @@ namespace OGF {
namespace MatrixUtil {
- /**
- * computes the eigen values and eigen vectors of a semi definite symmetric matrix
- *
- * \param mat: The matrix 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_vec: (return) = { v1, v2, v3, ..., vn }
- * where vk = vk0, vk1, ..., vkn
- * size = n^2, must be allocated by caller
- *
- * \param eigen_val: (return) are in decreasing order
- * size = n, must be allocated by caller
- */
- void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
+/**
+ * computes the eigen values and eigen vectors of a semi definite symmetric matrix
+ *
+ * \param mat: The matrix 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_vec: (return) = { v1, v2, v3, ..., vn }
+ * where vk = vk0, vk1, ..., vkn
+ * size = n^2, must be allocated by caller
+ *
+ * \param eigen_val: (return) are in decreasing order
+ * size = n, must be allocated by caller
+ */
+void semi_definite_symmetric_eigen(const double *mat, int n, double *eigen_vec, double *eigen_val);
-} // MatrixUtil namespace
+} // namespace MatrixUtil
-} // OGF namespace
+} // namespace OGF
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.cpp b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
index e0ef1ddfe12..25a39619a04 100644
--- a/source/blender/freestyle/intern/geometry/normal_cycle.cpp
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.cpp
@@ -38,57 +38,56 @@ namespace OGF {
//_________________________________________________________
-
NormalCycle::NormalCycle()
{
}
void NormalCycle::begin()
{
- M_[0] = M_[1] = M_[2] = M_[3] = M_[4] = M_[5] = 0;
+ 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]);
- }
+ 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
+} // namespace OGF
} /* namespace Freestyle */
diff --git a/source/blender/freestyle/intern/geometry/normal_cycle.h b/source/blender/freestyle/intern/geometry/normal_cycle.h
index 275e5494962..a57bfdb953e 100644
--- a/source/blender/freestyle/intern/geometry/normal_cycle.h
+++ b/source/blender/freestyle/intern/geometry/normal_cycle.h
@@ -37,7 +37,7 @@
#include "../system/FreestyleConfig.h"
#ifdef WITH_CXX_GUARDEDALLOC
-#include "MEM_guardedalloc.h"
+# include "MEM_guardedalloc.h"
#endif
namespace Freestyle {
@@ -46,11 +46,11 @@ using namespace Geometry;
namespace OGF {
-template <class T> inline void ogf_swap(T& x, T& y)
+template<class T> inline void ogf_swap(T &x, T &y)
{
- T z = x ;
- x = y ;
- y = z ;
+ T z = x;
+ x = y;
+ y = z;
}
//_________________________________________________________
@@ -64,83 +64,85 @@ template <class T> inline void ogf_swap(T& x, T& y)
* SOCG 2003
*/
class 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:
- /* UNUSED */
- // real center_[3];
- Vec3r axis_[3];
- real eigen_value_[3];
- real M_[6];
- int i_[3];
+ 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:
+ /* UNUSED */
+ // real center_[3];
+ Vec3r axis_[3];
+ real eigen_value_[3];
+ real M_[6];
+ int i_[3];
#ifdef WITH_CXX_GUARDEDALLOC
- MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OGF:NormalCycle")
+ MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:OGF:NormalCycle")
#endif
};
-inline void NormalCycle::accumulate_dihedral_angle(const Vec3r& edge, const double beta, double neigh_area)
+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();
+ 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();
}
//_________________________________________________________
-} // OGF namespace
+} // namespace OGF
} /* namespace Freestyle */