IMPORTANT: The setters functions' names were normalized due to constant confusion regarding capitalization. All the function names start with set... instead of Set.... This convention was changed all throughout Freestyle. To use Freestyle as an external renderer, the SWIG library MUST be regenerated.
733 lines
18 KiB
C++
Executable File
733 lines
18 KiB
C++
Executable File
|
|
//
|
|
// Copyright (C) : Please refer to the COPYRIGHT file distributed
|
|
// with this source distribution.
|
|
//
|
|
// This program is free software; you can redistribute it and/or
|
|
// modify it under the terms of the GNU General Public License
|
|
// as published by the Free Software Foundation; either version 2
|
|
// of the License, or (at your option) any later version.
|
|
//
|
|
// This program is distributed in the hope that it will be useful,
|
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
// GNU General Public License for more details.
|
|
//
|
|
// You should have received a copy of the GNU General Public License
|
|
// along with this program; if not, write to the Free Software
|
|
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
//
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
#include <iostream>
|
|
#include "WEdge.h"
|
|
|
|
/*! Temporary structures */
|
|
class vertexdata
|
|
{
|
|
public:
|
|
WVertex *_copy;
|
|
};
|
|
|
|
class oedgedata
|
|
{
|
|
public:
|
|
WOEdge *_copy;
|
|
};
|
|
|
|
class edgedata
|
|
{
|
|
public:
|
|
WEdge *_copy;
|
|
};
|
|
|
|
class facedata
|
|
{
|
|
public:
|
|
WFace *_copy;
|
|
};
|
|
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* WVertex */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
WVertex::WVertex(WVertex& iBrother)
|
|
{
|
|
_Id = iBrother._Id;
|
|
_Vertex = iBrother._Vertex;
|
|
_EdgeList = iBrother._EdgeList;
|
|
|
|
_Shape = iBrother._Shape;
|
|
_Smooth = iBrother._Smooth;
|
|
_Border = iBrother._Border;
|
|
userdata = NULL;
|
|
iBrother.userdata = new vertexdata;
|
|
((vertexdata*)(iBrother.userdata))->_copy = this;
|
|
}
|
|
|
|
WVertex* WVertex::duplicate()
|
|
{
|
|
WVertex *clone = new WVertex(*this);
|
|
return clone;
|
|
}
|
|
|
|
|
|
WOEdge* WVertex::incoming_edge_iterator::operator*()
|
|
|
|
{
|
|
return _current;
|
|
}
|
|
void WVertex::incoming_edge_iterator::increment(){
|
|
WOEdge *twin = _current->twin();
|
|
if(!twin){
|
|
// we reached a hole
|
|
_current = 0;
|
|
return;
|
|
}
|
|
WOEdge *next = twin->getPrevOnFace();
|
|
if(next == _begin){
|
|
next = 0;
|
|
}
|
|
_current = next;
|
|
}
|
|
|
|
WFace* WVertex::face_iterator::operator*(){
|
|
WOEdge * woedge = *_edge_it;
|
|
if(woedge == 0)
|
|
return 0;
|
|
return (woedge)->GetbFace();
|
|
}
|
|
|
|
//bool WVertex::isBoundary () const{
|
|
// return _Border;
|
|
//}
|
|
bool WVertex::isBoundary ()
|
|
{
|
|
if(_Border == 1)
|
|
return true;
|
|
else if(_Border == 0)
|
|
return false;
|
|
|
|
vector<WEdge *>::const_iterator it;
|
|
for(it=_EdgeList.begin(); it!=_EdgeList.end(); it++){
|
|
if((*it)->GetNumberOfOEdges() == 1){
|
|
_Border = 1;
|
|
return true;
|
|
}
|
|
}
|
|
//if (!(*it)->GetaOEdge()->GetaFace()) return true;
|
|
_Border = 0;
|
|
return false;
|
|
}
|
|
|
|
void WVertex::AddEdge(WEdge *iEdge) {
|
|
_EdgeList.push_back(iEdge);
|
|
}
|
|
|
|
WVertex::incoming_edge_iterator WVertex::incoming_edges_begin(){
|
|
WOEdge *begin;
|
|
WEdge * wedge = _EdgeList.front();
|
|
WOEdge* aOEdge = wedge->GetaOEdge();
|
|
if(aOEdge->GetbVertex() == this)
|
|
begin = aOEdge;
|
|
else
|
|
begin = _EdgeList.front()->GetbOEdge();
|
|
return incoming_edge_iterator(this, begin, begin);
|
|
}
|
|
WVertex::incoming_edge_iterator WVertex::incoming_edges_end(){
|
|
WOEdge *begin;
|
|
WOEdge* aOEdge = _EdgeList.front()->GetaOEdge();
|
|
if(aOEdge->GetbVertex() == this)
|
|
begin = aOEdge;
|
|
else
|
|
begin = _EdgeList.front()->GetbOEdge();
|
|
return incoming_edge_iterator(this, begin, 0);
|
|
}
|
|
//WOEdge** WVertex::incoming_edge_iterator::operator->()
|
|
//{
|
|
// WOEdge ** ppaOEdge = (*_iter)->GetaOEdge();
|
|
// if(aOEdge->GetbVertex() == _vertex)
|
|
// return ppaOEdge;
|
|
// else
|
|
// {
|
|
// WOEdge *bOEdge = (*_iter)->GetbOEdge();
|
|
// return &bOEdge;
|
|
// }
|
|
//
|
|
//}
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* WOEdge */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
WOEdge::WOEdge(WOEdge& iBrother)
|
|
{
|
|
_paVertex = iBrother.GetaVertex();
|
|
_pbVertex = iBrother.GetbVertex();
|
|
_paFace = iBrother.GetaFace();
|
|
_pbFace = iBrother.GetbFace();
|
|
_pOwner = iBrother.GetOwner();
|
|
userdata = NULL;
|
|
iBrother.userdata = new oedgedata;
|
|
((oedgedata*)(iBrother.userdata))->_copy = this;
|
|
}
|
|
|
|
WOEdge * WOEdge::duplicate()
|
|
{
|
|
WOEdge *clone = new WOEdge(*this);
|
|
return clone;
|
|
}
|
|
|
|
Vec3r
|
|
WOEdge::getVec3r ()
|
|
{
|
|
return Vec3r(_pbVertex->GetVertex() - _paVertex->GetVertex());
|
|
}
|
|
|
|
WOEdge * WOEdge::twin ()
|
|
{
|
|
return GetOwner()->GetOtherOEdge(this);
|
|
}
|
|
|
|
WOEdge *
|
|
WOEdge::getPrevOnFace()
|
|
{
|
|
return _pbFace->GetPrevOEdge(this);
|
|
}
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* WEdge */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
WEdge::WEdge(WEdge& iBrother)
|
|
{
|
|
_paOEdge = NULL;
|
|
_pbOEdge = NULL;
|
|
WOEdge *aoedge = iBrother.GetaOEdge();
|
|
WOEdge *boedge = iBrother.GetbOEdge();
|
|
userdata = NULL;
|
|
|
|
if(NULL != aoedge)
|
|
//_paOEdge = new WOEdge(*aoedge);
|
|
_paOEdge = aoedge->duplicate();
|
|
if(NULL != boedge)
|
|
//_pbOEdge = new WOEdge(*boedge);
|
|
_pbOEdge = boedge->duplicate();
|
|
|
|
_nOEdges = iBrother.GetNumberOfOEdges();
|
|
_Id = iBrother.GetId();
|
|
iBrother.userdata = new edgedata;
|
|
((edgedata*)(iBrother.userdata))->_copy = this;
|
|
}
|
|
|
|
WEdge * WEdge::duplicate()
|
|
{
|
|
WEdge *clone = new WEdge(*this);
|
|
return clone;
|
|
}
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* WFace */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
|
|
WFace::WFace(WFace& iBrother)
|
|
{
|
|
_OEdgeList = iBrother.GetEdgeList();
|
|
_Normal = iBrother.GetNormal();
|
|
_VerticesNormals = iBrother._VerticesNormals;
|
|
_VerticesTexCoords = iBrother._VerticesTexCoords;
|
|
_Id = iBrother.GetId();
|
|
_MaterialIndex = iBrother._MaterialIndex;
|
|
userdata = NULL;
|
|
iBrother.userdata = new facedata;
|
|
((facedata*)(iBrother.userdata))->_copy = this;
|
|
}
|
|
|
|
WFace * WFace::duplicate()
|
|
{
|
|
WFace * clone = new WFace(*this);
|
|
return clone;
|
|
}
|
|
|
|
const Material& WFace::material() {
|
|
return getShape()->material(_MaterialIndex);
|
|
}
|
|
|
|
WOEdge * WFace::MakeEdge(WVertex *v1, WVertex *v2)
|
|
{
|
|
// First check whether the same oriented edge already exists
|
|
// or not:
|
|
vector<WEdge *>& v1Edges = v1->GetEdges();
|
|
for(vector<WEdge*>::iterator it1=v1Edges.begin(), end=v1Edges.end();
|
|
it1!=end;
|
|
it1++)
|
|
{
|
|
|
|
WEdge *we=(*it1);
|
|
|
|
WOEdge *woea = we->GetaOEdge();
|
|
|
|
if((woea->GetaVertex() == v1) && (woea->GetbVertex() == v2))
|
|
//if((*it1)->GetbVertex() == v2)
|
|
{
|
|
// The oriented edge already exists
|
|
cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
|
|
// Adds the edge to the face
|
|
//AddEdge((*it1)->GetaOEdge());
|
|
AddEdge(woea);
|
|
(*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
|
|
//sets these vertices as border:
|
|
v1->setBorder(true);
|
|
v2->setBorder(true);
|
|
//return (*it1)->GetaOEdge();
|
|
return woea;
|
|
}
|
|
|
|
WOEdge *woeb = we->GetbOEdge();
|
|
if((woeb != 0) && (woeb->GetaVertex() == v1) && (woeb->GetbVertex() == v2))
|
|
|
|
//if((*it1)->GetbVertex() == v2)
|
|
|
|
{
|
|
// The oriented edge already exists
|
|
cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId() << " appears twice, correcting" << endl;
|
|
// Adds the edge to the face
|
|
//AddEdge((*it1)->GetaOEdge());
|
|
AddEdge(woeb);
|
|
(*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges()+1);
|
|
//sets these vertices as border:
|
|
v1->setBorder(true);
|
|
v2->setBorder(true);
|
|
//return (*it1)->GetaOEdge();
|
|
return woeb;
|
|
}
|
|
}
|
|
|
|
// the oriented edge we're about to build
|
|
WOEdge *pOEdge = new WOEdge;
|
|
|
|
WEdge * edge; // The edge containing the oriented edge.
|
|
|
|
// checks whether this edge already exists or not
|
|
// If it exists, it points outward v2
|
|
|
|
bool exist = false;
|
|
WOEdge *pInvertEdge = NULL; // The inverted edge if it exists
|
|
vector<WEdge *>& v2Edges = v2->GetEdges();
|
|
vector<WEdge *>::iterator it;
|
|
for(it=v2Edges.begin(); it!=v2Edges.end(); it++)
|
|
{
|
|
if((*it)->GetbVertex() == v1)
|
|
{
|
|
// The invert edge already exists
|
|
exist = true;
|
|
pInvertEdge = (*it)->GetaOEdge();
|
|
break;
|
|
}
|
|
}
|
|
|
|
//DEBUG:
|
|
|
|
|
|
if(true == exist) // The invert edge already exists
|
|
{
|
|
// Retrieves the corresponding edge
|
|
edge = pInvertEdge->GetOwner();
|
|
|
|
// Sets the a Face (retrieved from pInvertEdge
|
|
pOEdge->setaFace(pInvertEdge->GetbFace());
|
|
|
|
// Updates the invert edge:
|
|
pInvertEdge->setaFace(this);
|
|
}
|
|
else // The invert edge does not exist yet
|
|
{
|
|
// we must create a new edge
|
|
//edge = new WEdge;
|
|
edge = instanciateEdge();
|
|
|
|
// updates the a,b vertex edges list:
|
|
v1->AddEdge(edge);
|
|
v2->AddEdge(edge);
|
|
|
|
}
|
|
|
|
pOEdge->setOwner(edge);
|
|
// Add the vertices:
|
|
pOEdge->setaVertex(v1);
|
|
pOEdge->setbVertex(v2);
|
|
|
|
// Debug:
|
|
if(v1->GetId() == v2->GetId())
|
|
cerr << "Warning: edge " << this << " null with vertex " << v1->GetId() << endl;
|
|
|
|
edge->AddOEdge(pOEdge);
|
|
//edge->setNumberOfOEdges(edge->GetNumberOfOEdges()+1);
|
|
|
|
// Add this face (the b face)
|
|
pOEdge->setbFace(this);
|
|
|
|
// Adds the edge to the face
|
|
AddEdge(pOEdge);
|
|
|
|
return pOEdge;
|
|
}
|
|
|
|
|
|
bool
|
|
WFace::getOppositeEdge (const WVertex *v, WOEdge* &e)
|
|
{
|
|
if (_OEdgeList.size()!=3) return false;
|
|
|
|
vector<WOEdge *>::iterator it;
|
|
e=NULL;
|
|
for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
|
|
if ((*it)->GetaVertex()==v) e=*it;
|
|
if (!e) return false;
|
|
e=NULL;
|
|
for(it=_OEdgeList.begin(); it!=_OEdgeList.end(); it++)
|
|
if (((*it)->GetaVertex()!=v) && ((*it)->GetbVertex()!=v)) e=*it;
|
|
if (!e) return false;
|
|
else return true;
|
|
}
|
|
|
|
real
|
|
WFace::getArea ()
|
|
{
|
|
vector<WOEdge *>::iterator it;
|
|
Vec3r origin=(*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
|
|
it=_OEdgeList.begin();
|
|
real a=0;
|
|
for (it=it++; it!=_OEdgeList.end(); it++) {
|
|
Vec3r v1=Vec3r((*it)->GetaVertex()->GetVertex() - origin);
|
|
Vec3r v2=Vec3r((*it)->GetbVertex()->GetVertex() - origin);
|
|
a += (v1 ^ v2).norm() / 2.0;
|
|
}
|
|
return a;
|
|
}
|
|
|
|
|
|
WOEdge*
|
|
WFace::GetPrevOEdge(WOEdge* iOEdge)
|
|
{
|
|
vector<WOEdge*>::iterator woe,woend, woefirst;
|
|
woefirst = _OEdgeList.begin();
|
|
woend=_OEdgeList.end();
|
|
WOEdge *prev =*woefirst;
|
|
woe=woefirst;
|
|
woe++;
|
|
for(;
|
|
woe!=woend;
|
|
woe++)
|
|
{
|
|
if((*woe) == iOEdge)
|
|
return prev;
|
|
prev= *woe;
|
|
}
|
|
// We left the loop. That means that the first
|
|
// OEdge was the good one:
|
|
if((*woefirst)==iOEdge)
|
|
return prev;
|
|
|
|
return NULL;
|
|
}
|
|
|
|
WShape * WFace::getShape()
|
|
{
|
|
return GetVertex(0)->shape();
|
|
}
|
|
|
|
/**********************************/
|
|
/* */
|
|
/* */
|
|
/* WShape */
|
|
/* */
|
|
/* */
|
|
/**********************************/
|
|
|
|
|
|
LIB_WINGED_EDGE_EXPORT
|
|
unsigned WShape::_SceneCurrentId = 0;
|
|
|
|
WShape * WShape::duplicate()
|
|
{
|
|
WShape *clone = new WShape(*this);
|
|
return clone;
|
|
}
|
|
|
|
WShape::WShape(WShape& iBrother)
|
|
{
|
|
_Id = iBrother.GetId();
|
|
_Materials = iBrother._Materials;
|
|
_meanEdgeSize = iBrother._meanEdgeSize;
|
|
iBrother.bbox(_min, _max);
|
|
vector<WVertex*>& vertexList = iBrother.GetVertexList();
|
|
vector<WVertex*>::iterator v=vertexList.begin(), vend=vertexList.end();
|
|
for(;
|
|
v!=vend;
|
|
v++)
|
|
{
|
|
//WVertex *newVertex = new WVertex(*(*v));
|
|
WVertex *newVertex = (*v)->duplicate();
|
|
|
|
newVertex->setShape(this);
|
|
AddVertex(newVertex);
|
|
}
|
|
|
|
vector<WEdge*>& edgeList = iBrother.GetEdgeList();
|
|
vector<WEdge*>::iterator e=edgeList.begin(), eend=edgeList.end();
|
|
for(;
|
|
e!=eend;
|
|
e++)
|
|
{
|
|
//WEdge *newEdge = new WEdge(*(*e));
|
|
WEdge *newEdge = (*e)->duplicate();
|
|
AddEdge(newEdge);
|
|
}
|
|
|
|
vector<WFace*>& faceList = iBrother.GetFaceList();
|
|
vector<WFace*>::iterator f=faceList.begin(), fend=faceList.end();
|
|
for(;
|
|
f!=fend;
|
|
f++)
|
|
{
|
|
//WFace *newFace = new WFace(*(*f));
|
|
WFace *newFace = (*f)->duplicate();
|
|
AddFace(newFace);
|
|
}
|
|
|
|
// update all pointed addresses thanks to the newly created objects:
|
|
vend=_VertexList.end();
|
|
for(v=_VertexList.begin();
|
|
v!=vend;
|
|
v++)
|
|
{
|
|
const vector<WEdge*>& vedgeList = (*v)->GetEdges();
|
|
vector<WEdge*> newvedgelist;
|
|
unsigned int i;
|
|
for(i=0; i<vedgeList.size(); i++)
|
|
{
|
|
WEdge *current = vedgeList[i];
|
|
edgedata * currentvedata = (edgedata*)current->userdata;
|
|
newvedgelist.push_back(currentvedata->_copy);
|
|
}
|
|
(*v)->setEdges(newvedgelist);
|
|
}
|
|
|
|
eend = _EdgeList.end();
|
|
for(e=_EdgeList.begin();
|
|
e!=eend;
|
|
e++)
|
|
{
|
|
// update aOedge:
|
|
WOEdge *aoEdge = (*e)->GetaOEdge();
|
|
aoEdge->setaVertex(((vertexdata*)(aoEdge->GetaVertex()->userdata))->_copy);
|
|
aoEdge->setbVertex(((vertexdata*)(aoEdge->GetbVertex()->userdata))->_copy);
|
|
if(NULL != aoEdge->GetaFace())
|
|
aoEdge->setaFace(((facedata*)(aoEdge->GetaFace()->userdata))->_copy);
|
|
aoEdge->setbFace(((facedata*)(aoEdge->GetbFace()->userdata))->_copy);
|
|
aoEdge->setOwner(((edgedata*)(aoEdge->GetOwner()->userdata))->_copy);
|
|
// update bOedge:
|
|
|
|
WOEdge *boEdge = (*e)->GetbOEdge();
|
|
if(boEdge != 0)
|
|
{
|
|
boEdge->setaVertex(((vertexdata*)(boEdge->GetaVertex()->userdata))->_copy);
|
|
boEdge->setbVertex(((vertexdata*)(boEdge->GetbVertex()->userdata))->_copy);
|
|
if(NULL != boEdge->GetaFace())
|
|
boEdge->setaFace(((facedata*)(boEdge->GetaFace()->userdata))->_copy);
|
|
boEdge->setbFace(((facedata*)(boEdge->GetbFace()->userdata))->_copy);
|
|
boEdge->setOwner(((edgedata*)(boEdge->GetOwner()->userdata))->_copy);
|
|
}
|
|
}
|
|
|
|
fend = _FaceList.end();
|
|
for(f=_FaceList.begin();
|
|
f!=fend;
|
|
f++)
|
|
{
|
|
unsigned i;
|
|
const vector<WOEdge*>& oedgeList = (*f)->GetEdgeList();
|
|
vector<WOEdge*> newoedgelist;
|
|
|
|
unsigned n = oedgeList.size();
|
|
for(i=0; i<n; i++)
|
|
{
|
|
WOEdge *current = oedgeList[i];
|
|
oedgedata * currentoedata = (oedgedata*)current->userdata;
|
|
newoedgelist.push_back(currentoedata->_copy);
|
|
//oedgeList[i] = currentoedata->_copy;
|
|
//oedgeList[i] = ((oedgedata*)(oedgeList[i]->userdata))->_copy;
|
|
}
|
|
(*f)->setEdgeList(newoedgelist);
|
|
}
|
|
|
|
// Free all memory (arghh!)
|
|
// Vertex
|
|
vend = iBrother.GetVertexList().end();
|
|
for(v=iBrother.GetVertexList().begin();
|
|
v!=vend;
|
|
v++)
|
|
{
|
|
delete (vertexdata*)((*v)->userdata);
|
|
(*v)->userdata = NULL;
|
|
}
|
|
|
|
// Edges and OEdges:
|
|
eend = iBrother.GetEdgeList().end();
|
|
for(e=iBrother.GetEdgeList().begin();
|
|
e!=eend;
|
|
e++)
|
|
{
|
|
delete (edgedata*)((*e)->userdata);
|
|
(*e)->userdata = NULL;
|
|
// OEdge a :
|
|
delete (oedgedata*)((*e)->GetaOEdge()->userdata);
|
|
(*e)->GetaOEdge()->userdata = NULL;
|
|
// OEdge b:
|
|
WOEdge* oedgeb = (*e)->GetbOEdge();
|
|
if(NULL != oedgeb)
|
|
{
|
|
delete (oedgedata*)(oedgeb->userdata);
|
|
oedgeb->userdata = NULL;
|
|
}
|
|
}
|
|
// Faces
|
|
fend = iBrother.GetFaceList().end();
|
|
for(f=iBrother.GetFaceList().begin();
|
|
f!=fend;
|
|
f++)
|
|
{
|
|
delete (facedata*)((*f)->userdata);
|
|
(*f)->userdata = NULL;
|
|
}
|
|
}
|
|
|
|
WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial)
|
|
{
|
|
// allocate the new face
|
|
WFace *face = instanciateFace();
|
|
|
|
return MakeFace(iVertexList, iMaterial, face);
|
|
}
|
|
|
|
WFace * WShape::MakeFace(vector<WVertex*>& iVertexList, vector<Vec3r>& iNormalsList, vector<Vec2r>& iTexCoordsList, unsigned iMaterial)
|
|
{
|
|
// allocate the new face
|
|
WFace *face = MakeFace(iVertexList, iMaterial);
|
|
|
|
if(0 == face)
|
|
|
|
return 0;
|
|
|
|
// set the list of per-vertex normals
|
|
face->setNormalList(iNormalsList);
|
|
// set the list of per-vertex tex coords
|
|
face->setTexCoordsList(iTexCoordsList);
|
|
|
|
return face;
|
|
}
|
|
|
|
WFace* WShape::MakeFace(vector<WVertex*>& iVertexList, unsigned iMaterial, WFace *face)
|
|
{
|
|
|
|
int id = _FaceList.size();
|
|
|
|
face->setMaterialIndex(iMaterial);
|
|
|
|
// Check whether we have a degenerated face:
|
|
|
|
// LET'S HACK IT FOR THE TRIANGLE CASE:
|
|
|
|
if(3 == iVertexList.size())
|
|
|
|
{
|
|
|
|
if((iVertexList[0] == iVertexList[1])
|
|
|
|
|| (iVertexList[0] == iVertexList[2])
|
|
|
|
|| (iVertexList[2] == iVertexList[1]))
|
|
|
|
{
|
|
|
|
cerr << "Warning: degenerated triangle detected, correcting" << endl;
|
|
return 0;
|
|
|
|
}
|
|
|
|
}
|
|
// vertex pointers used to build each edge
|
|
vector<WVertex*>::iterator va, vb, it;
|
|
|
|
va = iVertexList.begin();
|
|
vb = va;
|
|
for(; va != iVertexList.end(); va = vb)
|
|
{
|
|
vb++;
|
|
// Adds va to the vertex list:
|
|
//face->AddVertex(*va);
|
|
|
|
WOEdge * oedge;
|
|
if(*va == iVertexList.back())
|
|
oedge = face->MakeEdge(*va, iVertexList.front()); //for the last (closing) edge
|
|
else
|
|
oedge = face->MakeEdge(*va, *vb);
|
|
|
|
|
|
if(oedge == 0)
|
|
return 0;
|
|
|
|
|
|
WEdge *edge = oedge->GetOwner();
|
|
if(1 == edge->GetNumberOfOEdges())
|
|
{
|
|
// means that we just created a new edge and that we must add it to the
|
|
// shape's edges list
|
|
edge->setId(_EdgeList.size());
|
|
AddEdge(edge);
|
|
// compute the mean edge value:
|
|
_meanEdgeSize += edge->GetaOEdge()->getVec3r().norm();
|
|
}
|
|
}
|
|
|
|
// compute the face normal (v1v2 ^ v1v3)
|
|
WVertex *v1, *v2, *v3;
|
|
it = iVertexList.begin();
|
|
v1 = *it;
|
|
it++;
|
|
v2 = *it;
|
|
it++;
|
|
v3 = *it;
|
|
|
|
Vec3r vector1(v2->GetVertex()-v1->GetVertex());
|
|
Vec3r vector2(v3->GetVertex()-v1->GetVertex());
|
|
|
|
Vec3r normal(vector1 ^ vector2);
|
|
normal.normalize();
|
|
face->setNormal(normal);
|
|
|
|
// Add the face to the shape's faces list:
|
|
face->setId(id);
|
|
AddFace(face);
|
|
|
|
return face;
|
|
}
|