This replaces header include guards with `#pragma once`. A couple of include guards are not removed yet (e.g. `__RNA_TYPES_H__`), because they are used in other places. This patch has been generated by P1561 followed by `make format`. Differential Revision: https://developer.blender.org/D8466
1430 lines
30 KiB
C++
1430 lines
30 KiB
C++
/*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* as published by the Free Software Foundation; either version 2
|
|
* of the License, or (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
|
|
*/
|
|
|
|
#pragma once
|
|
|
|
/** \file
|
|
* \ingroup freestyle
|
|
* \brief Classes to define a Winged Edge data structure.
|
|
*/
|
|
|
|
#include <iterator>
|
|
#include <vector>
|
|
|
|
#include "../geometry/Geom.h"
|
|
|
|
#include "../scene_graph/FrsMaterial.h"
|
|
|
|
#include "../system/FreestyleConfig.h"
|
|
|
|
#include "BLI_math.h"
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
# include "MEM_guardedalloc.h"
|
|
#endif
|
|
|
|
using namespace std;
|
|
|
|
namespace Freestyle {
|
|
|
|
using namespace Geometry;
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WVertex *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WOEdge;
|
|
class WEdge;
|
|
class WShape;
|
|
class WFace;
|
|
|
|
class WVertex {
|
|
protected:
|
|
int _Id; // an identificator
|
|
Vec3f _Vertex;
|
|
vector<WEdge *> _EdgeList;
|
|
WShape *_Shape; // the shape to which the vertex belongs
|
|
bool _Smooth; // flag to indicate whether the Vertex belongs to a smooth edge or not
|
|
short _Border; // 1 -> border, 0 -> no border, -1 -> not set
|
|
|
|
public:
|
|
void *userdata; // designed to store specific user data
|
|
inline WVertex(const Vec3f &v)
|
|
{
|
|
_Id = 0;
|
|
_Vertex = v;
|
|
userdata = NULL;
|
|
_Shape = NULL;
|
|
_Smooth = true;
|
|
_Border = -1;
|
|
}
|
|
|
|
/*! Copy constructor */
|
|
WVertex(WVertex &iBrother);
|
|
virtual WVertex *duplicate();
|
|
virtual ~WVertex()
|
|
{
|
|
}
|
|
|
|
/*! accessors */
|
|
inline Vec3f &GetVertex()
|
|
{
|
|
return _Vertex;
|
|
}
|
|
|
|
inline vector<WEdge *> &GetEdges()
|
|
{
|
|
return _EdgeList;
|
|
}
|
|
|
|
inline int GetId()
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
inline WShape *shape() const
|
|
{
|
|
return _Shape;
|
|
}
|
|
|
|
inline bool isSmooth() const
|
|
{
|
|
return _Smooth;
|
|
}
|
|
|
|
bool isBoundary();
|
|
|
|
/*! modifiers */
|
|
inline void setVertex(const Vec3f &v)
|
|
{
|
|
_Vertex = v;
|
|
}
|
|
|
|
inline void setEdges(const vector<WEdge *> &iEdgeList)
|
|
{
|
|
_EdgeList = iEdgeList;
|
|
}
|
|
|
|
inline void setId(int id)
|
|
{
|
|
_Id = id;
|
|
}
|
|
|
|
inline void setShape(WShape *iShape)
|
|
{
|
|
_Shape = iShape;
|
|
}
|
|
|
|
inline void setSmooth(bool b)
|
|
{
|
|
_Smooth = b;
|
|
}
|
|
|
|
inline void setBorder(bool b)
|
|
{
|
|
if (b) {
|
|
_Border = 1;
|
|
}
|
|
else {
|
|
_Border = 0;
|
|
}
|
|
}
|
|
|
|
/*! Adds an edge to the edges list */
|
|
void AddEdge(WEdge *iEdge);
|
|
|
|
virtual void ResetUserData()
|
|
{
|
|
userdata = NULL;
|
|
}
|
|
|
|
public:
|
|
/*! Iterator to iterate over a vertex incoming edges in the CCW order*/
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
class incoming_edge_iterator : public input_iterator<WOEdge *, ptrdiff_t>
|
|
#else
|
|
class incoming_edge_iterator : public iterator<input_iterator_tag, WOEdge *, ptrdiff_t>
|
|
#endif
|
|
{
|
|
private:
|
|
WVertex *_vertex;
|
|
//
|
|
WOEdge *_begin;
|
|
WOEdge *_current;
|
|
|
|
public:
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
inline incoming_edge_iterator() : input_iterator<WOEdge *, ptrdiff_t>()
|
|
{
|
|
}
|
|
#else
|
|
inline incoming_edge_iterator() : iterator<input_iterator_tag, WOEdge *, ptrdiff_t>()
|
|
{
|
|
}
|
|
#endif
|
|
virtual ~incoming_edge_iterator(){}; // soc
|
|
|
|
protected:
|
|
friend class WVertex;
|
|
inline incoming_edge_iterator(WVertex *iVertex, WOEdge *iBegin, WOEdge *iCurrent)
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
: input_iterator<WOEdge *, ptrdiff_t>()
|
|
#else
|
|
: iterator<input_iterator_tag, WOEdge *, ptrdiff_t>()
|
|
#endif
|
|
{
|
|
_vertex = iVertex;
|
|
_begin = iBegin;
|
|
_current = iCurrent;
|
|
}
|
|
|
|
public:
|
|
inline incoming_edge_iterator(const incoming_edge_iterator &iBrother)
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
: input_iterator<WOEdge *, ptrdiff_t>(iBrother)
|
|
#else
|
|
: iterator<input_iterator_tag, WOEdge *, ptrdiff_t>(iBrother)
|
|
#endif
|
|
{
|
|
_vertex = iBrother._vertex;
|
|
_begin = iBrother._begin;
|
|
_current = iBrother._current;
|
|
}
|
|
|
|
public:
|
|
// operators
|
|
// operator corresponding to ++i
|
|
virtual incoming_edge_iterator &operator++()
|
|
{
|
|
increment();
|
|
return *this;
|
|
}
|
|
|
|
// operator corresponding to i++
|
|
virtual incoming_edge_iterator operator++(int)
|
|
{
|
|
incoming_edge_iterator tmp = *this;
|
|
increment();
|
|
return tmp;
|
|
}
|
|
|
|
// comparibility
|
|
virtual bool operator!=(const incoming_edge_iterator &b) const
|
|
{
|
|
return ((_current) != (b._current));
|
|
}
|
|
|
|
virtual bool operator==(const incoming_edge_iterator &b) const
|
|
{
|
|
return ((_current) == (b._current));
|
|
}
|
|
|
|
// dereferencing
|
|
virtual WOEdge *operator*();
|
|
// virtual WOEdge **operator->();
|
|
protected:
|
|
virtual void increment();
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex:incoming_edge_iterator")
|
|
#endif
|
|
};
|
|
|
|
/*! Iterator to iterate over a vertex faces in the CCW order */
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
class face_iterator : public input_iterator<WFace *, ptrdiff_t>
|
|
#else
|
|
class face_iterator : public iterator<input_iterator_tag, WFace *, ptrdiff_t>
|
|
#endif
|
|
{
|
|
private:
|
|
incoming_edge_iterator _edge_it;
|
|
|
|
public:
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
inline face_iterator() : input_iterator<WFace *, ptrdiff_t>()
|
|
{
|
|
}
|
|
#else
|
|
inline face_iterator() : iterator<input_iterator_tag, WFace *, ptrdiff_t>()
|
|
{
|
|
}
|
|
#endif
|
|
virtual ~face_iterator(){}; // soc
|
|
|
|
protected:
|
|
friend class WVertex;
|
|
inline face_iterator(incoming_edge_iterator it)
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
: input_iterator<WFace *, ptrdiff_t>()
|
|
#else
|
|
: iterator<input_iterator_tag, WFace *, ptrdiff_t>()
|
|
#endif
|
|
{
|
|
_edge_it = it;
|
|
}
|
|
|
|
public:
|
|
inline face_iterator(const face_iterator &iBrother)
|
|
#if defined(__GNUC__) && (__GNUC__ < 3)
|
|
: input_iterator<WFace *, ptrdiff_t>(iBrother)
|
|
#else
|
|
: iterator<input_iterator_tag, WFace *, ptrdiff_t>(iBrother)
|
|
#endif
|
|
{
|
|
_edge_it = iBrother._edge_it;
|
|
}
|
|
|
|
public:
|
|
// operators
|
|
// operator corresponding to ++i
|
|
virtual face_iterator &operator++()
|
|
{
|
|
increment();
|
|
return *this;
|
|
}
|
|
|
|
// operator corresponding to i++
|
|
virtual face_iterator operator++(int)
|
|
{
|
|
face_iterator tmp = *this;
|
|
increment();
|
|
return tmp;
|
|
}
|
|
|
|
// comparibility
|
|
virtual bool operator!=(const face_iterator &b) const
|
|
{
|
|
return ((_edge_it) != (b._edge_it));
|
|
}
|
|
|
|
virtual bool operator==(const face_iterator &b) const
|
|
{
|
|
return ((_edge_it) == (b._edge_it));
|
|
}
|
|
|
|
// dereferencing
|
|
virtual WFace *operator*();
|
|
// virtual WOEdge **operator->();
|
|
|
|
protected:
|
|
inline void increment()
|
|
{
|
|
++_edge_it;
|
|
}
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex:face_iterator")
|
|
#endif
|
|
};
|
|
|
|
public:
|
|
/*! iterators access */
|
|
virtual incoming_edge_iterator incoming_edges_begin();
|
|
virtual incoming_edge_iterator incoming_edges_end();
|
|
|
|
virtual face_iterator faces_begin()
|
|
{
|
|
return face_iterator(incoming_edges_begin());
|
|
}
|
|
|
|
virtual face_iterator faces_end()
|
|
{
|
|
return face_iterator(incoming_edges_end());
|
|
}
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WVertex")
|
|
#endif
|
|
};
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WOEdge *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WFace;
|
|
class WEdge;
|
|
|
|
class WOEdge {
|
|
protected:
|
|
#if 0
|
|
WOEdge *_paCWEdge; // edge reached when traveling clockwise on aFace from the edge
|
|
WOEdge *_pbCWEdge; // edge reached when traveling clockwise on bFace from the edge
|
|
WOEdge *_paCCWEdge; // edge reached when traveling counterclockwise on aFace from the edge
|
|
WOEdge *_pbCCWEdge; // edge reached when traveling counterclockwise on bFace from the edge
|
|
#endif
|
|
WVertex *_paVertex; // starting vertex
|
|
WVertex *_pbVertex; // ending vertex
|
|
WFace *_paFace; // when following the edge, face on the right
|
|
WFace *_pbFace; // when following the edge, face on the left
|
|
WEdge *_pOwner; // Edge
|
|
|
|
Vec3f _vec;
|
|
float _angle;
|
|
|
|
public:
|
|
void *userdata;
|
|
|
|
inline WOEdge()
|
|
{
|
|
#if 0
|
|
_paCWEdge = NULL;
|
|
_pbCWEdge = NULL;
|
|
_paCCWEdge = NULL;
|
|
_pbCCWEdge = NULL;
|
|
#endif
|
|
_paVertex = NULL;
|
|
_pbVertex = NULL;
|
|
_paFace = NULL;
|
|
_pbFace = NULL;
|
|
_pOwner = NULL;
|
|
userdata = NULL;
|
|
}
|
|
|
|
virtual ~WOEdge(){}; // soc
|
|
|
|
/*! copy constructor */
|
|
WOEdge(WOEdge &iBrother);
|
|
virtual WOEdge *duplicate();
|
|
|
|
/*! accessors */
|
|
#if 0
|
|
inline WOEdge *GetaCWEdge()
|
|
{
|
|
return _paCWEdge;
|
|
}
|
|
|
|
inline WOEdge *GetbCWEdge()
|
|
{
|
|
return _pbCWEdge;
|
|
}
|
|
|
|
inline WOEdge *GetaCCWEdge()
|
|
{
|
|
return _paCCWEdge;
|
|
}
|
|
|
|
inline WOEdge *GetbCCWEdge()
|
|
{
|
|
return _pbCCWEdge;
|
|
}
|
|
#endif
|
|
|
|
inline WVertex *GetaVertex()
|
|
{
|
|
return _paVertex;
|
|
}
|
|
|
|
inline WVertex *GetbVertex()
|
|
{
|
|
return _pbVertex;
|
|
}
|
|
|
|
inline WFace *GetaFace()
|
|
{
|
|
return _paFace;
|
|
}
|
|
|
|
inline WFace *GetbFace()
|
|
{
|
|
return _pbFace;
|
|
}
|
|
|
|
inline WEdge *GetOwner()
|
|
{
|
|
return _pOwner;
|
|
}
|
|
|
|
inline const Vec3f &GetVec()
|
|
{
|
|
return _vec;
|
|
}
|
|
|
|
inline const float GetAngle()
|
|
{
|
|
return _angle;
|
|
}
|
|
|
|
/*! modifiers */
|
|
#if 0
|
|
inline void SetaCWEdge(WOEdge *pe)
|
|
{
|
|
_paCWEdge = pe;
|
|
}
|
|
|
|
inline void SetbCWEdge(WOEdge *pe)
|
|
{
|
|
_pbCWEdge = pe;
|
|
}
|
|
|
|
inline void SetaCCWEdge(WOEdge *pe)
|
|
{
|
|
_paCCWEdge = pe;
|
|
}
|
|
|
|
inline void SetbCCCWEdge(WOEdge *pe)
|
|
{
|
|
_pbCCWEdge = pe;
|
|
}
|
|
#endif
|
|
|
|
inline void setVecAndAngle();
|
|
|
|
inline void setaVertex(WVertex *pv)
|
|
{
|
|
_paVertex = pv;
|
|
setVecAndAngle();
|
|
}
|
|
|
|
inline void setbVertex(WVertex *pv)
|
|
{
|
|
_pbVertex = pv;
|
|
setVecAndAngle();
|
|
}
|
|
|
|
inline void setaFace(WFace *pf)
|
|
{
|
|
_paFace = pf;
|
|
setVecAndAngle();
|
|
}
|
|
|
|
inline void setbFace(WFace *pf)
|
|
{
|
|
_pbFace = pf;
|
|
setVecAndAngle();
|
|
}
|
|
|
|
inline void setOwner(WEdge *pe)
|
|
{
|
|
_pOwner = pe;
|
|
}
|
|
|
|
/*! Retrieves the list of edges in CW order */
|
|
inline void RetrieveCWOrderedEdges(vector<WEdge *> &oEdges);
|
|
|
|
WOEdge *twin();
|
|
WOEdge *getPrevOnFace();
|
|
|
|
virtual void ResetUserData()
|
|
{
|
|
userdata = NULL;
|
|
}
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WOEdge")
|
|
#endif
|
|
};
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WEdge *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WEdge {
|
|
protected:
|
|
WOEdge *_paOEdge; // first oriented edge
|
|
WOEdge *_pbOEdge; // second oriented edge
|
|
short _nOEdges; // number of oriented edges associated with this edge. (1 means border edge)
|
|
bool _Mark; // user-specified edge mark for feature edge detection
|
|
int _Id; // Identifier for the edge
|
|
|
|
public:
|
|
void *userdata; // designed to store specific user data
|
|
|
|
inline WEdge()
|
|
{
|
|
_paOEdge = NULL;
|
|
_pbOEdge = NULL;
|
|
_nOEdges = 0;
|
|
userdata = NULL;
|
|
}
|
|
|
|
inline WEdge(WOEdge *iOEdge)
|
|
{
|
|
_paOEdge = iOEdge;
|
|
_pbOEdge = NULL;
|
|
_nOEdges = 1;
|
|
userdata = NULL;
|
|
}
|
|
|
|
inline WEdge(WOEdge *iaOEdge, WOEdge *ibOEdge)
|
|
{
|
|
_paOEdge = iaOEdge;
|
|
_pbOEdge = ibOEdge;
|
|
_nOEdges = 2;
|
|
userdata = NULL;
|
|
}
|
|
|
|
/*! Copy constructor */
|
|
WEdge(WEdge &iBrother);
|
|
virtual WEdge *duplicate();
|
|
|
|
virtual ~WEdge()
|
|
{
|
|
if (_paOEdge) {
|
|
delete _paOEdge;
|
|
_paOEdge = NULL;
|
|
}
|
|
|
|
if (_pbOEdge) {
|
|
delete _pbOEdge;
|
|
_pbOEdge = NULL;
|
|
}
|
|
}
|
|
|
|
/*! checks whether two WEdge have a common vertex.
|
|
* Returns a pointer on the common vertex if it exists, NULL otherwise.
|
|
*/
|
|
static inline WVertex *CommonVertex(WEdge *iEdge1, WEdge *iEdge2)
|
|
{
|
|
if (!iEdge1 || !iEdge2) {
|
|
return NULL;
|
|
}
|
|
|
|
WVertex *wv1 = iEdge1->GetaOEdge()->GetaVertex();
|
|
WVertex *wv2 = iEdge1->GetaOEdge()->GetbVertex();
|
|
WVertex *wv3 = iEdge2->GetaOEdge()->GetaVertex();
|
|
WVertex *wv4 = iEdge2->GetaOEdge()->GetbVertex();
|
|
|
|
if ((wv1 == wv3) || (wv1 == wv4)) {
|
|
return wv1;
|
|
}
|
|
else if ((wv2 == wv3) || (wv2 == wv4)) {
|
|
return wv2;
|
|
}
|
|
return NULL;
|
|
}
|
|
|
|
/*! accessors */
|
|
inline WOEdge *GetaOEdge()
|
|
{
|
|
return _paOEdge;
|
|
}
|
|
|
|
inline WOEdge *GetbOEdge()
|
|
{
|
|
return _pbOEdge;
|
|
}
|
|
|
|
inline short GetNumberOfOEdges()
|
|
{
|
|
return _nOEdges;
|
|
}
|
|
|
|
inline bool GetMark()
|
|
{
|
|
return _Mark;
|
|
}
|
|
|
|
inline int GetId()
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
inline WVertex *GetaVertex()
|
|
{
|
|
return _paOEdge->GetaVertex();
|
|
}
|
|
|
|
inline WVertex *GetbVertex()
|
|
{
|
|
return _paOEdge->GetbVertex();
|
|
}
|
|
|
|
inline WFace *GetaFace()
|
|
{
|
|
return _paOEdge->GetaFace();
|
|
}
|
|
|
|
inline WFace *GetbFace()
|
|
{
|
|
return _paOEdge->GetbFace();
|
|
}
|
|
|
|
inline WOEdge *GetOtherOEdge(WOEdge *iOEdge)
|
|
{
|
|
if (iOEdge == _paOEdge) {
|
|
return _pbOEdge;
|
|
}
|
|
else {
|
|
return _paOEdge;
|
|
}
|
|
}
|
|
|
|
/*! modifiers */
|
|
inline void setaOEdge(WOEdge *iEdge)
|
|
{
|
|
_paOEdge = iEdge;
|
|
}
|
|
|
|
inline void setbOEdge(WOEdge *iEdge)
|
|
{
|
|
_pbOEdge = iEdge;
|
|
}
|
|
|
|
inline void AddOEdge(WOEdge *iEdge)
|
|
{
|
|
if (!_paOEdge) {
|
|
_paOEdge = iEdge;
|
|
_nOEdges++;
|
|
return;
|
|
}
|
|
if (!_pbOEdge) {
|
|
_pbOEdge = iEdge;
|
|
_nOEdges++;
|
|
return;
|
|
}
|
|
}
|
|
|
|
inline void setNumberOfOEdges(short n)
|
|
{
|
|
_nOEdges = n;
|
|
}
|
|
|
|
inline void setMark(bool mark)
|
|
{
|
|
_Mark = mark;
|
|
}
|
|
|
|
inline void setId(int id)
|
|
{
|
|
_Id = id;
|
|
}
|
|
|
|
virtual void ResetUserData()
|
|
{
|
|
userdata = NULL;
|
|
}
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WEdge")
|
|
#endif
|
|
};
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WFace *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WFace {
|
|
protected:
|
|
vector<WOEdge *> _OEdgeList; // list of oriented edges of bording the face
|
|
Vec3f _Normal; // normal to the face
|
|
// in case there is a normal per vertex.
|
|
// The normal number i corresponds to the aVertex of the oedge number i, for that face
|
|
vector<Vec3f> _VerticesNormals;
|
|
vector<Vec2f> _VerticesTexCoords;
|
|
|
|
int _Id;
|
|
unsigned _FrsMaterialIndex;
|
|
bool _Mark; // Freestyle face mark (if true, feature edges on this face are ignored)
|
|
|
|
public:
|
|
void *userdata;
|
|
inline WFace()
|
|
{
|
|
userdata = NULL;
|
|
_FrsMaterialIndex = 0;
|
|
}
|
|
|
|
/*! copy constructor */
|
|
WFace(WFace &iBrother);
|
|
virtual WFace *duplicate();
|
|
virtual ~WFace()
|
|
{
|
|
}
|
|
|
|
/*! accessors */
|
|
inline const vector<WOEdge *> &getEdgeList()
|
|
{
|
|
return _OEdgeList;
|
|
}
|
|
|
|
inline WOEdge *GetOEdge(int i)
|
|
{
|
|
return _OEdgeList[i];
|
|
}
|
|
|
|
inline Vec3f &GetNormal()
|
|
{
|
|
return _Normal;
|
|
}
|
|
|
|
inline int GetId()
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
inline unsigned frs_materialIndex() const
|
|
{
|
|
return _FrsMaterialIndex;
|
|
}
|
|
|
|
inline bool GetMark() const
|
|
{
|
|
return _Mark;
|
|
}
|
|
|
|
const FrsMaterial &frs_material();
|
|
|
|
/*! The vertex of index i corresponds to the a vertex of the edge of index i */
|
|
inline WVertex *GetVertex(unsigned int index)
|
|
{
|
|
#if 0
|
|
if (index >= _OEdgeList.size()) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
return _OEdgeList[index]->GetaVertex();
|
|
}
|
|
|
|
/*! returns the index at which iVertex is stored in the array.
|
|
* returns -1 if iVertex doesn't belong to the face.
|
|
*/
|
|
inline int GetIndex(WVertex *iVertex)
|
|
{
|
|
int index = 0;
|
|
for (vector<WOEdge *>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end();
|
|
woe != woend;
|
|
woe++) {
|
|
if ((*woe)->GetaVertex() == iVertex) {
|
|
return index;
|
|
}
|
|
++index;
|
|
}
|
|
return -1;
|
|
}
|
|
|
|
inline void RetrieveVertexList(vector<WVertex *> &oVertices)
|
|
{
|
|
for (vector<WOEdge *>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end();
|
|
woe != woend;
|
|
woe++) {
|
|
oVertices.push_back((*woe)->GetaVertex());
|
|
}
|
|
}
|
|
|
|
inline void RetrieveBorderFaces(vector<const WFace *> &oWFaces)
|
|
{
|
|
for (vector<WOEdge *>::iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end();
|
|
woe != woend;
|
|
woe++) {
|
|
WFace *af;
|
|
if ((af = (*woe)->GetaFace())) {
|
|
oWFaces.push_back(af);
|
|
}
|
|
}
|
|
}
|
|
|
|
inline WFace *GetBordingFace(int index)
|
|
{
|
|
#if 0
|
|
if (index >= _OEdgeList.size()) {
|
|
return NULL;
|
|
}
|
|
#endif
|
|
return _OEdgeList[index]->GetaFace();
|
|
}
|
|
|
|
inline WFace *GetBordingFace(WOEdge *iOEdge)
|
|
{
|
|
return iOEdge->GetaFace();
|
|
}
|
|
|
|
inline vector<Vec3f> &GetPerVertexNormals()
|
|
{
|
|
return _VerticesNormals;
|
|
}
|
|
|
|
inline vector<Vec2f> &GetPerVertexTexCoords()
|
|
{
|
|
return _VerticesTexCoords;
|
|
}
|
|
|
|
/*! Returns the normal of the vertex of index index */
|
|
inline Vec3f &GetVertexNormal(int index)
|
|
{
|
|
return _VerticesNormals[index];
|
|
}
|
|
|
|
/*! Returns the tex coords of the vertex of index index */
|
|
inline Vec2f &GetVertexTexCoords(int index)
|
|
{
|
|
return _VerticesTexCoords[index];
|
|
}
|
|
|
|
/*! Returns the normal of the vertex iVertex for that face */
|
|
inline Vec3f &GetVertexNormal(WVertex *iVertex)
|
|
{
|
|
int i = 0;
|
|
int index = 0;
|
|
for (vector<WOEdge *>::const_iterator woe = _OEdgeList.begin(), woend = _OEdgeList.end();
|
|
woe != woend;
|
|
woe++) {
|
|
if ((*woe)->GetaVertex() == iVertex) {
|
|
index = i;
|
|
break;
|
|
}
|
|
++i;
|
|
}
|
|
|
|
return _VerticesNormals[index];
|
|
}
|
|
|
|
inline WOEdge *GetNextOEdge(WOEdge *iOEdge)
|
|
{
|
|
bool found = false;
|
|
vector<WOEdge *>::iterator woe, woend, woefirst;
|
|
woefirst = _OEdgeList.begin();
|
|
for (woe = woefirst, woend = _OEdgeList.end(); woe != woend; ++woe) {
|
|
if (found) {
|
|
return (*woe);
|
|
}
|
|
|
|
if ((*woe) == iOEdge) {
|
|
found = true;
|
|
}
|
|
}
|
|
|
|
// We left the loop. That means that the first OEdge was the good one:
|
|
if (found) {
|
|
return (*woefirst);
|
|
}
|
|
|
|
return NULL;
|
|
}
|
|
|
|
WOEdge *GetPrevOEdge(WOEdge *iOEdge);
|
|
|
|
inline int numberOfEdges() const
|
|
{
|
|
return _OEdgeList.size();
|
|
}
|
|
|
|
inline int numberOfVertices() const
|
|
{
|
|
return _OEdgeList.size();
|
|
}
|
|
|
|
/*! Returns true if the face has one ot its edge which is a border edge */
|
|
inline bool isBorder() const
|
|
{
|
|
for (vector<WOEdge *>::const_iterator woe = _OEdgeList.begin(), woeend = _OEdgeList.end();
|
|
woe != woeend;
|
|
++woe) {
|
|
if ((*woe)->GetOwner()->GetbOEdge() == 0) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/*! modifiers */
|
|
inline void setEdgeList(const vector<WOEdge *> &iEdgeList)
|
|
{
|
|
_OEdgeList = iEdgeList;
|
|
}
|
|
|
|
inline void setNormal(const Vec3f &iNormal)
|
|
{
|
|
_Normal = iNormal;
|
|
}
|
|
|
|
inline void setNormalList(const vector<Vec3f> &iNormalsList)
|
|
{
|
|
_VerticesNormals = iNormalsList;
|
|
}
|
|
|
|
inline void setTexCoordsList(const vector<Vec2f> &iTexCoordsList)
|
|
{
|
|
_VerticesTexCoords = iTexCoordsList;
|
|
}
|
|
|
|
inline void setId(int id)
|
|
{
|
|
_Id = id;
|
|
}
|
|
|
|
inline void setFrsMaterialIndex(unsigned iMaterialIndex)
|
|
{
|
|
_FrsMaterialIndex = iMaterialIndex;
|
|
}
|
|
|
|
inline void setMark(bool iMark)
|
|
{
|
|
_Mark = iMark;
|
|
}
|
|
|
|
/*! designed to build a specialized WEdge for use in MakeEdge */
|
|
virtual WEdge *instanciateEdge() const
|
|
{
|
|
return new WEdge;
|
|
}
|
|
|
|
/*! Builds an oriented edge
|
|
* Returns the built edge.
|
|
* v1, v2
|
|
* Vertices at the edge's extremities
|
|
* The edge is oriented from v1 to v2.
|
|
*/
|
|
virtual WOEdge *MakeEdge(WVertex *v1, WVertex *v2);
|
|
|
|
/*! Adds an edge to the edges list */
|
|
inline void AddEdge(WOEdge *iEdge)
|
|
{
|
|
_OEdgeList.push_back(iEdge);
|
|
}
|
|
|
|
/*! For triangles, returns the edge opposite to the vertex in e.
|
|
* returns false if the face is not a triangle or if the vertex is not found
|
|
*/
|
|
bool getOppositeEdge(const WVertex *v, WOEdge *&e);
|
|
|
|
/*! compute the area of the face */
|
|
float getArea();
|
|
|
|
WShape *getShape();
|
|
virtual void ResetUserData()
|
|
{
|
|
userdata = NULL;
|
|
}
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WFace")
|
|
#endif
|
|
};
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WShape *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WShape {
|
|
protected:
|
|
vector<WVertex *> _VertexList;
|
|
vector<WEdge *> _EdgeList;
|
|
vector<WFace *> _FaceList;
|
|
int _Id;
|
|
string _Name;
|
|
string _LibraryPath;
|
|
static unsigned _SceneCurrentId;
|
|
#if 0
|
|
Vec3f _min;
|
|
Vec3f _max;
|
|
#endif
|
|
vector<FrsMaterial> _FrsMaterials;
|
|
#if 0
|
|
float _meanEdgeSize;
|
|
#endif
|
|
|
|
public:
|
|
inline WShape()
|
|
{
|
|
#if 0
|
|
_meanEdgeSize = 0;
|
|
#endif
|
|
_Id = _SceneCurrentId;
|
|
_SceneCurrentId++;
|
|
}
|
|
|
|
/*! copy constructor */
|
|
WShape(WShape &iBrother);
|
|
virtual WShape *duplicate();
|
|
|
|
virtual ~WShape()
|
|
{
|
|
if (_EdgeList.size() != 0) {
|
|
vector<WEdge *>::iterator e;
|
|
for (e = _EdgeList.begin(); e != _EdgeList.end(); ++e) {
|
|
delete (*e);
|
|
}
|
|
_EdgeList.clear();
|
|
}
|
|
|
|
if (_VertexList.size() != 0) {
|
|
vector<WVertex *>::iterator v;
|
|
for (v = _VertexList.begin(); v != _VertexList.end(); ++v) {
|
|
delete (*v);
|
|
}
|
|
_VertexList.clear();
|
|
}
|
|
|
|
if (_FaceList.size() != 0) {
|
|
vector<WFace *>::iterator f;
|
|
for (f = _FaceList.begin(); f != _FaceList.end(); ++f) {
|
|
delete (*f);
|
|
}
|
|
_FaceList.clear();
|
|
}
|
|
}
|
|
|
|
/*! accessors */
|
|
inline vector<WEdge *> &getEdgeList()
|
|
{
|
|
return _EdgeList;
|
|
}
|
|
|
|
inline vector<WVertex *> &getVertexList()
|
|
{
|
|
return _VertexList;
|
|
}
|
|
|
|
inline vector<WFace *> &GetFaceList()
|
|
{
|
|
return _FaceList;
|
|
}
|
|
|
|
inline unsigned GetId()
|
|
{
|
|
return _Id;
|
|
}
|
|
|
|
#if 0
|
|
inline void bbox(Vec3f &min, Vec3f &max)
|
|
{
|
|
min = _min;
|
|
max = _max;
|
|
}
|
|
#endif
|
|
|
|
inline const FrsMaterial &frs_material(unsigned i) const
|
|
{
|
|
return _FrsMaterials[i];
|
|
}
|
|
|
|
inline const vector<FrsMaterial> &frs_materials() const
|
|
{
|
|
return _FrsMaterials;
|
|
}
|
|
|
|
#if 0
|
|
inline const float getMeanEdgeSize() const
|
|
{
|
|
return _meanEdgeSize;
|
|
}
|
|
#endif
|
|
|
|
inline const string &getName() const
|
|
{
|
|
return _Name;
|
|
}
|
|
|
|
inline const string &getLibraryPath() const
|
|
{
|
|
return _LibraryPath;
|
|
}
|
|
|
|
/*! modifiers */
|
|
static inline void setCurrentId(const unsigned id)
|
|
{
|
|
_SceneCurrentId = id;
|
|
}
|
|
|
|
inline void setEdgeList(const vector<WEdge *> &iEdgeList)
|
|
{
|
|
_EdgeList = iEdgeList;
|
|
}
|
|
|
|
inline void setVertexList(const vector<WVertex *> &iVertexList)
|
|
{
|
|
_VertexList = iVertexList;
|
|
}
|
|
|
|
inline void setFaceList(const vector<WFace *> &iFaceList)
|
|
{
|
|
_FaceList = iFaceList;
|
|
}
|
|
|
|
inline void setId(int id)
|
|
{
|
|
_Id = id;
|
|
}
|
|
|
|
#if 0
|
|
inline void setBBox(const Vec3f &min, const Vec3f &max)
|
|
{
|
|
_min = min;
|
|
_max = max;
|
|
}
|
|
#endif
|
|
|
|
inline void setFrsMaterial(const FrsMaterial &frs_material, unsigned i)
|
|
{
|
|
_FrsMaterials[i] = frs_material;
|
|
}
|
|
|
|
inline void setFrsMaterials(const vector<FrsMaterial> &iMaterials)
|
|
{
|
|
_FrsMaterials = iMaterials;
|
|
}
|
|
|
|
inline void setName(const string &name)
|
|
{
|
|
_Name = name;
|
|
}
|
|
|
|
inline void setLibraryPath(const string &path)
|
|
{
|
|
_LibraryPath = path;
|
|
}
|
|
|
|
/*! designed to build a specialized WFace for use in MakeFace */
|
|
virtual WFace *instanciateFace() const
|
|
{
|
|
return new WFace;
|
|
}
|
|
|
|
/*! adds a new face to the shape
|
|
* returns the built face.
|
|
* iVertexList
|
|
* List of face's vertices. These vertices are not added to the WShape vertex list; they are
|
|
* supposed to be already stored when calling MakeFace. The order in which the vertices are
|
|
* stored in the list determines the face's edges orientation and (so) the face orientation.
|
|
* iMaterialIndex
|
|
* The material index for this face
|
|
*/
|
|
virtual WFace *MakeFace(vector<WVertex *> &iVertexList,
|
|
vector<bool> &iFaceEdgeMarksList,
|
|
unsigned iMaterialIndex);
|
|
|
|
/*! adds a new face to the shape. The difference with the previous method is that this one is
|
|
* designed to build a WingedEdge structure for which there are per vertex normals, opposed to
|
|
* per face normals. returns the built face. iVertexList List of face's vertices. These vertices
|
|
* are not added to the WShape vertex list; they are supposed to be already stored when calling
|
|
* MakeFace. The order in which the vertices are stored in the list determines the face's edges
|
|
* orientation and (so) the face orientation. iMaterialIndex The materialIndex for this face
|
|
* iNormalsList
|
|
* The list of normals, iNormalsList[i] corresponding to the normal of the vertex
|
|
* iVertexList[i] for that face. iTexCoordsList The list of tex coords, iTexCoordsList[i]
|
|
* corresponding to the normal of the vertex iVertexList[i] for that face.
|
|
*/
|
|
virtual WFace *MakeFace(vector<WVertex *> &iVertexList,
|
|
vector<Vec3f> &iNormalsList,
|
|
vector<Vec2f> &iTexCoordsList,
|
|
vector<bool> &iFaceEdgeMarksList,
|
|
unsigned iMaterialIndex);
|
|
|
|
inline void AddEdge(WEdge *iEdge)
|
|
{
|
|
_EdgeList.push_back(iEdge);
|
|
}
|
|
|
|
inline void AddFace(WFace *iFace)
|
|
{
|
|
_FaceList.push_back(iFace);
|
|
}
|
|
|
|
inline void AddVertex(WVertex *iVertex)
|
|
{
|
|
iVertex->setShape(this);
|
|
_VertexList.push_back(iVertex);
|
|
}
|
|
|
|
inline void ResetUserData()
|
|
{
|
|
for (vector<WVertex *>::iterator v = _VertexList.begin(), vend = _VertexList.end(); v != vend;
|
|
v++) {
|
|
(*v)->ResetUserData();
|
|
}
|
|
|
|
for (vector<WEdge *>::iterator e = _EdgeList.begin(), eend = _EdgeList.end(); e != eend; e++) {
|
|
(*e)->ResetUserData();
|
|
// manages WOEdge:
|
|
WOEdge *oe = (*e)->GetaOEdge();
|
|
if (oe) {
|
|
oe->ResetUserData();
|
|
}
|
|
oe = (*e)->GetbOEdge();
|
|
if (oe) {
|
|
oe->ResetUserData();
|
|
}
|
|
}
|
|
|
|
for (vector<WFace *>::iterator f = _FaceList.begin(), fend = _FaceList.end(); f != fend; f++) {
|
|
(*f)->ResetUserData();
|
|
}
|
|
}
|
|
|
|
#if 0
|
|
inline void ComputeBBox()
|
|
{
|
|
_min = _VertexList[0]->GetVertex();
|
|
_max = _VertexList[0]->GetVertex();
|
|
|
|
Vec3f v;
|
|
for (vector<WVertex *>::iterator wv = _VertexList.begin(), wvend = _VertexList.end();
|
|
wv != wvend;
|
|
wv++) {
|
|
for (unsigned int i = 0; i < 3; i++) {
|
|
v = (*wv)->GetVertex();
|
|
if (v[i] < _min[i]) {
|
|
_min[i] = v[i];
|
|
}
|
|
if (v[i] > _max[i]) {
|
|
_max[i] = v[i];
|
|
}
|
|
}
|
|
}
|
|
}
|
|
#endif
|
|
|
|
#if 0
|
|
inline float ComputeMeanEdgeSize()
|
|
{
|
|
_meanEdgeSize = _meanEdgeSize / _EdgeList.size();
|
|
return _meanEdgeSize;
|
|
}
|
|
#else
|
|
real ComputeMeanEdgeSize() const;
|
|
#endif
|
|
|
|
protected:
|
|
/*!
|
|
* Builds the face passed as argument (which as already been allocated)
|
|
* - iVertexList
|
|
* List of face's vertices. These vertices are not added to the WShape vertex list;
|
|
* they are supposed to be already stored when calling MakeFace.
|
|
* The order in which the vertices are stored in the list determines
|
|
* the face's edges orientation and (so) the face orientation.
|
|
* - iMaterialIndex
|
|
* The material index for this face
|
|
* - face
|
|
* The Face that is filled in
|
|
*/
|
|
virtual WFace *MakeFace(vector<WVertex *> &iVertexList,
|
|
vector<bool> &iFaceEdgeMarksList,
|
|
unsigned iMaterialIndex,
|
|
WFace *face);
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WShape")
|
|
#endif
|
|
};
|
|
|
|
/**********************************
|
|
* *
|
|
* *
|
|
* WingedEdge *
|
|
* *
|
|
* *
|
|
**********************************/
|
|
|
|
class WingedEdge {
|
|
public:
|
|
WingedEdge()
|
|
{
|
|
_numFaces = 0;
|
|
}
|
|
|
|
~WingedEdge()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
for (vector<WShape *>::iterator it = _wshapes.begin(); it != _wshapes.end(); it++) {
|
|
delete *it;
|
|
}
|
|
_wshapes.clear();
|
|
_numFaces = 0;
|
|
}
|
|
|
|
void addWShape(WShape *wshape)
|
|
{
|
|
_wshapes.push_back(wshape);
|
|
_numFaces += wshape->GetFaceList().size();
|
|
}
|
|
|
|
vector<WShape *> &getWShapes()
|
|
{
|
|
return _wshapes;
|
|
}
|
|
|
|
unsigned getNumFaces()
|
|
{
|
|
return _numFaces;
|
|
}
|
|
|
|
private:
|
|
vector<WShape *> _wshapes;
|
|
unsigned _numFaces;
|
|
|
|
#ifdef WITH_CXX_GUARDEDALLOC
|
|
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:WingedEdge")
|
|
#endif
|
|
};
|
|
|
|
/*
|
|
* #############################################
|
|
* #############################################
|
|
* #############################################
|
|
* ###### ######
|
|
* ###### I M P L E M E N T A T I O N ######
|
|
* ###### ######
|
|
* #############################################
|
|
* #############################################
|
|
* #############################################
|
|
*/
|
|
/* for inline functions */
|
|
void WOEdge::RetrieveCWOrderedEdges(vector<WEdge *> &oEdges)
|
|
{
|
|
WOEdge *currentOEdge = this;
|
|
do {
|
|
WOEdge *nextOEdge = currentOEdge->GetbFace()->GetNextOEdge(currentOEdge);
|
|
oEdges.push_back(nextOEdge->GetOwner());
|
|
currentOEdge = nextOEdge->GetOwner()->GetOtherOEdge(nextOEdge);
|
|
} while (currentOEdge && (currentOEdge->GetOwner() != GetOwner()));
|
|
}
|
|
|
|
inline void WOEdge::setVecAndAngle()
|
|
{
|
|
if (_paVertex && _pbVertex) {
|
|
_vec = _pbVertex->GetVertex() - _paVertex->GetVertex();
|
|
if (_paFace && _pbFace) {
|
|
float sine = (_pbFace->GetNormal() ^ _paFace->GetNormal()) * _vec / _vec.norm();
|
|
if (sine >= 1.0) {
|
|
_angle = M_PI / 2.0;
|
|
return;
|
|
}
|
|
if (sine <= -1.0) {
|
|
_angle = -M_PI / 2.0;
|
|
return;
|
|
}
|
|
_angle = ::asin(sine);
|
|
}
|
|
}
|
|
}
|
|
|
|
} /* namespace Freestyle */
|