diff options
author | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:17:24 +0300 |
---|---|---|
committer | Campbell Barton <ideasman42@gmail.com> | 2019-04-17 07:21:24 +0300 |
commit | e12c08e8d170b7ca40f204a5b0423c23a9fbc2c1 (patch) | |
tree | 8cf3453d12edb177a218ef8009357518ec6cab6a /source/blender/freestyle/intern/geometry | |
parent | b3dabc200a4b0399ec6b81f2ff2730d07b44fcaa (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')
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 ¤t_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 ¤t_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 */ |