This repository has been archived on 2023-10-09. You can view files and clone it. You cannot open issues or pull requests or push a commit.
Files
blender-archive/source/blender/freestyle/intern/view_map/ViewEdgeXBuilder.cpp

814 lines
23 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.
*/
/** \file
* \ingroup freestyle
* \brief Class to build view edges and the underlying chains of feature edges...
*/
#include <list>
#include "SilhouetteGeomEngine.h"
#include "ViewEdgeXBuilder.h"
#include "ViewMap.h"
#include "../winged_edge/WXEdge.h"
using namespace std;
namespace Freestyle {
void ViewEdgeXBuilder::Init(ViewShape *oVShape)
{
if (NULL == oVShape) {
return;
}
// for design convenience, we store the current SShape.
_pCurrentSShape = oVShape->sshape();
if (0 == _pCurrentSShape) {
return;
}
_pCurrentVShape = oVShape;
// Reset previous data
//--------------------
if (!_SVertexMap.empty()) {
_SVertexMap.clear();
}
}
void ViewEdgeXBuilder::BuildViewEdges(WXShape *iWShape,
ViewShape *oVShape,
vector<ViewEdge *> &ioVEdges,
vector<ViewVertex *> &ioVVertices,
vector<FEdge *> &ioFEdges,
vector<SVertex *> &ioSVertices)
{
// Reinit structures
Init(oVShape);
/* ViewEdge *vedge; */ /* UNUSED */
// Let us build the smooth stuff
//----------------------------------------
// We parse all faces to find the ones that contain smooth edges
vector<WFace *> &wfaces = iWShape->GetFaceList();
vector<WFace *>::iterator wf, wfend;
WXFace *wxf;
for (wf = wfaces.begin(), wfend = wfaces.end(); wf != wfend; wf++) {
wxf = dynamic_cast<WXFace *>(*wf);
if (false == ((wxf))->hasSmoothEdges()) { // does it contain at least one smooth edge ?
continue;
}
// parse all smooth layers:
vector<WXFaceLayer *> &smoothLayers = wxf->getSmoothLayers();
for (vector<WXFaceLayer *>::iterator sl = smoothLayers.begin(), slend = smoothLayers.end();
sl != slend;
++sl) {
if (!(*sl)->hasSmoothEdge()) {
continue;
}
if (stopSmoothViewEdge((*sl))) { // has it been parsed already ?
continue;
}
// here we know that we're dealing with a face layer that has not been processed yet and that
// contains a smooth edge.
/* vedge =*//* UNUSED */ BuildSmoothViewEdge(OWXFaceLayer(*sl, true));
}
}
// Now let's build sharp view edges:
//----------------------------------
// Reset all userdata for WXEdge structure
//----------------------------------------
// iWShape->ResetUserData();
WXEdge *wxe;
vector<WEdge *> &wedges = iWShape->getEdgeList();
//------------------------------
for (vector<WEdge *>::iterator we = wedges.begin(), weend = wedges.end(); we != weend; we++) {
wxe = dynamic_cast<WXEdge *>(*we);
if (Nature::NO_FEATURE == wxe->nature()) {
continue;
}
if (!stopSharpViewEdge(wxe)) {
bool b = true;
if (wxe->order() == -1) {
b = false;
}
BuildSharpViewEdge(OWXEdge(wxe, b));
}
}
// Reset all userdata for WXEdge structure
//----------------------------------------
iWShape->ResetUserData();
// Add all these new edges to the scene's feature edges list:
//-----------------------------------------------------------
vector<FEdge *> &newedges = _pCurrentSShape->getEdgeList();
vector<SVertex *> &newVertices = _pCurrentSShape->getVertexList();
vector<ViewVertex *> &newVVertices = _pCurrentVShape->vertices();
vector<ViewEdge *> &newVEdges = _pCurrentVShape->edges();
// inserts in ioFEdges, at its end, all the edges of newedges
ioFEdges.insert(ioFEdges.end(), newedges.begin(), newedges.end());
ioSVertices.insert(ioSVertices.end(), newVertices.begin(), newVertices.end());
ioVVertices.insert(ioVVertices.end(), newVVertices.begin(), newVVertices.end());
ioVEdges.insert(ioVEdges.end(), newVEdges.begin(), newVEdges.end());
}
ViewEdge *ViewEdgeXBuilder::BuildSmoothViewEdge(const OWXFaceLayer &iFaceLayer)
{
// Find first edge:
OWXFaceLayer first = iFaceLayer;
OWXFaceLayer currentFace = first;
// bidirectional chaining.
// first direction
list<OWXFaceLayer> facesChain;
unsigned size = 0;
while (!stopSmoothViewEdge(currentFace.fl)) {
facesChain.push_back(currentFace);
++size;
currentFace.fl->userdata = (void *)1; // processed
// Find the next edge!
currentFace = FindNextFaceLayer(currentFace);
}
OWXFaceLayer end = facesChain.back();
// second direction
currentFace = FindPreviousFaceLayer(first);
while (!stopSmoothViewEdge(currentFace.fl)) {
facesChain.push_front(currentFace);
++size;
currentFace.fl->userdata = (void *)1; // processed
// Find the previous edge!
currentFace = FindPreviousFaceLayer(currentFace);
}
first = facesChain.front();
if (iFaceLayer.fl->nature() & Nature::RIDGE) {
if (size < 4) {
return 0;
}
}
// Start a new chain edges
ViewEdge *newVEdge = new ViewEdge;
newVEdge->setId(_currentViewId);
++_currentViewId;
_pCurrentVShape->AddEdge(newVEdge);
// build FEdges
FEdge *feprevious = NULL;
FEdge *fefirst = NULL;
FEdge *fe = NULL;
for (list<OWXFaceLayer>::iterator fl = facesChain.begin(), flend = facesChain.end(); fl != flend;
++fl) {
fe = BuildSmoothFEdge(feprevious, (*fl));
if (feprevious && fe == feprevious) {
continue;
}
fe->setViewEdge(newVEdge);
if (!fefirst) {
fefirst = fe;
}
feprevious = fe;
}
// Store the chain starting edge:
_pCurrentSShape->AddChain(fefirst);
newVEdge->setNature(iFaceLayer.fl->nature());
newVEdge->setFEdgeA(fefirst);
newVEdge->setFEdgeB(fe);
// is it a closed loop ?
if ((first == end) && (size != 1)) {
fefirst->setPreviousEdge(fe);
fe->setNextEdge(fefirst);
newVEdge->setA(0);
newVEdge->setB(0);
}
else {
ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
ViewVertex *vvb = MakeViewVertex(fe->vertexB());
((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
newVEdge->setA(vva);
newVEdge->setB(vvb);
}
return newVEdge;
}
ViewEdge *ViewEdgeXBuilder::BuildSharpViewEdge(const OWXEdge &iWEdge)
{
// Start a new sharp chain edges
ViewEdge *newVEdge = new ViewEdge;
newVEdge->setId(_currentViewId);
++_currentViewId;
unsigned size = 0;
_pCurrentVShape->AddEdge(newVEdge);
// Find first edge:
OWXEdge firstWEdge = iWEdge;
/* OWXEdge previousWEdge = firstWEdge; */ /* UNUSED */
OWXEdge currentWEdge = firstWEdge;
list<OWXEdge> edgesChain;
#if 0 /* TK 02-Sep-2012 Experimental fix for incorrect view edge visibility. */
// bidirectional chaining
// first direction:
while (!stopSharpViewEdge(currentWEdge.e)) {
edgesChain.push_back(currentWEdge);
++size;
currentWEdge.e->userdata = (void *)1; // processed
// Find the next edge!
currentWEdge = FindNextWEdge(currentWEdge);
}
OWXEdge endWEdge = edgesChain.back();
// second direction
currentWEdge = FindPreviousWEdge(firstWEdge);
while (!stopSharpViewEdge(currentWEdge.e)) {
edgesChain.push_front(currentWEdge);
++size;
currentWEdge.e->userdata = (void *)1; // processed
// Find the previous edge!
currentWEdge = FindPreviousWEdge(currentWEdge);
}
#else
edgesChain.push_back(currentWEdge);
++size;
currentWEdge.e->userdata = (void *)1; // processed
OWXEdge endWEdge = edgesChain.back();
#endif
firstWEdge = edgesChain.front();
// build FEdges
FEdge *feprevious = NULL;
FEdge *fefirst = NULL;
FEdge *fe = NULL;
for (list<OWXEdge>::iterator we = edgesChain.begin(), weend = edgesChain.end(); we != weend;
++we) {
fe = BuildSharpFEdge(feprevious, (*we));
fe->setViewEdge(newVEdge);
if (!fefirst) {
fefirst = fe;
}
feprevious = fe;
}
// Store the chain starting edge:
_pCurrentSShape->AddChain(fefirst);
newVEdge->setNature(iWEdge.e->nature());
newVEdge->setFEdgeA(fefirst);
newVEdge->setFEdgeB(fe);
// is it a closed loop ?
if ((firstWEdge == endWEdge) && (size != 1)) {
fefirst->setPreviousEdge(fe);
fe->setNextEdge(fefirst);
newVEdge->setA(0);
newVEdge->setB(0);
}
else {
ViewVertex *vva = MakeViewVertex(fefirst->vertexA());
ViewVertex *vvb = MakeViewVertex(fe->vertexB());
((NonTVertex *)vva)->AddOutgoingViewEdge(newVEdge);
((NonTVertex *)vvb)->AddIncomingViewEdge(newVEdge);
newVEdge->setA(vva);
newVEdge->setB(vvb);
}
return newVEdge;
}
OWXFaceLayer ViewEdgeXBuilder::FindNextFaceLayer(const OWXFaceLayer &iFaceLayer)
{
WXFace *nextFace = NULL;
WOEdge *woeend;
real tend;
if (iFaceLayer.order) {
woeend = iFaceLayer.fl->getSmoothEdge()->woeb();
tend = iFaceLayer.fl->getSmoothEdge()->tb();
}
else {
woeend = iFaceLayer.fl->getSmoothEdge()->woea();
tend = iFaceLayer.fl->getSmoothEdge()->ta();
}
// special case of EDGE_VERTEX config:
if ((tend == 0.0) || (tend == 1.0)) {
WVertex *nextVertex;
if (tend == 0.0) {
nextVertex = woeend->GetaVertex();
}
else {
nextVertex = woeend->GetbVertex();
}
if (nextVertex->isBoundary()) { // if it's a non-manifold vertex -> ignore
return OWXFaceLayer(0, true);
}
bool found = false;
WVertex::face_iterator f = nextVertex->faces_begin();
WVertex::face_iterator fend = nextVertex->faces_end();
while ((!found) && (f != fend)) {
nextFace = dynamic_cast<WXFace *>(*f);
if ((0 != nextFace) && (nextFace != iFaceLayer.fl->getFace())) {
vector<WXFaceLayer *> sameNatureLayers;
nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
// don't know... Maybe should test whether this face has also a vertex_edge configuration.
if (sameNatureLayers.size() == 1) {
WXFaceLayer *winner = sameNatureLayers[0];
// check face mark continuity
if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
return OWXFaceLayer(NULL, true);
}
if (woeend == winner->getSmoothEdge()->woea()->twin()) {
return OWXFaceLayer(winner, true);
}
else {
return OWXFaceLayer(winner, false);
}
}
}
++f;
}
}
else {
nextFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woeend));
if (!nextFace) {
return OWXFaceLayer(NULL, true);
}
// if the next face layer has either no smooth edge or no smooth edge of same nature, no next
// face
if (!nextFace->hasSmoothEdges()) {
return OWXFaceLayer(NULL, true);
}
vector<WXFaceLayer *> sameNatureLayers;
nextFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
// don't know how to deal with several edges of same nature on a single face
if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
return OWXFaceLayer(NULL, true);
}
else {
WXFaceLayer *winner = sameNatureLayers[0];
// check face mark continuity
if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
return OWXFaceLayer(NULL, true);
}
if (woeend == winner->getSmoothEdge()->woea()->twin()) {
return OWXFaceLayer(winner, true);
}
else {
return OWXFaceLayer(winner, false);
}
}
}
return OWXFaceLayer(NULL, true);
}
OWXFaceLayer ViewEdgeXBuilder::FindPreviousFaceLayer(const OWXFaceLayer &iFaceLayer)
{
WXFace *previousFace = NULL;
WOEdge *woebegin;
real tend;
if (iFaceLayer.order) {
woebegin = iFaceLayer.fl->getSmoothEdge()->woea();
tend = iFaceLayer.fl->getSmoothEdge()->ta();
}
else {
woebegin = iFaceLayer.fl->getSmoothEdge()->woeb();
tend = iFaceLayer.fl->getSmoothEdge()->tb();
}
// special case of EDGE_VERTEX config:
if ((tend == 0.0) || (tend == 1.0)) {
WVertex *previousVertex;
if (tend == 0.0) {
previousVertex = woebegin->GetaVertex();
}
else {
previousVertex = woebegin->GetbVertex();
}
if (previousVertex->isBoundary()) { // if it's a non-manifold vertex -> ignore
return OWXFaceLayer(NULL, true);
}
bool found = false;
WVertex::face_iterator f = previousVertex->faces_begin();
WVertex::face_iterator fend = previousVertex->faces_end();
for (; (!found) && (f != fend); ++f) {
previousFace = dynamic_cast<WXFace *>(*f);
if ((0 != previousFace) && (previousFace != iFaceLayer.fl->getFace())) {
vector<WXFaceLayer *> sameNatureLayers;
previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
// don't know... Maybe should test whether this face has also a vertex_edge configuration
if (sameNatureLayers.size() == 1) {
WXFaceLayer *winner = sameNatureLayers[0];
// check face mark continuity
if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
return OWXFaceLayer(NULL, true);
}
if (woebegin == winner->getSmoothEdge()->woeb()->twin()) {
return OWXFaceLayer(winner, true);
}
else {
return OWXFaceLayer(winner, false);
}
}
}
}
}
else {
previousFace = dynamic_cast<WXFace *>(iFaceLayer.fl->getFace()->GetBordingFace(woebegin));
if (0 == previousFace) {
return OWXFaceLayer(NULL, true);
}
// if the next face layer has either no smooth edge or no smooth edge of same nature, no next
// face
if (!previousFace->hasSmoothEdges()) {
return OWXFaceLayer(NULL, true);
}
vector<WXFaceLayer *> sameNatureLayers;
previousFace->retrieveSmoothEdgesLayers(iFaceLayer.fl->nature(), sameNatureLayers);
// don't know how to deal with several edges of same nature on a single face
if ((sameNatureLayers.empty()) || (sameNatureLayers.size() != 1)) {
return OWXFaceLayer(NULL, true);
}
else {
WXFaceLayer *winner = sameNatureLayers[0];
// check face mark continuity
if (winner->getFace()->GetMark() != iFaceLayer.fl->getFace()->GetMark()) {
return OWXFaceLayer(NULL, true);
}
if (woebegin == winner->getSmoothEdge()->woeb()->twin()) {
return OWXFaceLayer(winner, true);
}
else {
return OWXFaceLayer(winner, false);
}
}
}
return OWXFaceLayer(NULL, true);
}
FEdge *ViewEdgeXBuilder::BuildSmoothFEdge(FEdge *feprevious, const OWXFaceLayer &ifl)
{
WOEdge *woea, *woeb;
real ta, tb;
SVertex *va, *vb;
FEdgeSmooth *fe;
// retrieve exact silhouette data
WXSmoothEdge *se = ifl.fl->getSmoothEdge();
if (ifl.order) {
woea = se->woea();
woeb = se->woeb();
ta = se->ta();
tb = se->tb();
}
else {
woea = se->woeb();
woeb = se->woea();
ta = se->tb();
tb = se->ta();
}
Vec3r normal;
// Make the 2 Svertices
if (feprevious == 0) { // that means that we don't have any vertex already built for that face
Vec3r A1(woea->GetaVertex()->GetVertex());
Vec3r A2(woea->GetbVertex()->GetVertex());
Vec3r A(A1 + ta * (A2 - A1));
va = MakeSVertex(A, false);
// Set normal:
Vec3r NA1(ifl.fl->getFace()->GetVertexNormal(woea->GetaVertex()));
Vec3r NA2(ifl.fl->getFace()->GetVertexNormal(woea->GetbVertex()));
Vec3r na((1 - ta) * NA1 + ta * NA2);
na.normalize();
va->AddNormal(na);
normal = na;
// Set CurvatureInfo
CurvatureInfo *curvature_info_a = new CurvatureInfo(
*(dynamic_cast<WXVertex *>(woea->GetaVertex())->curvatures()),
*(dynamic_cast<WXVertex *>(woea->GetbVertex())->curvatures()),
ta);
va->setCurvatureInfo(curvature_info_a);
}
else {
va = feprevious->vertexB();
}
Vec3r B1(woeb->GetaVertex()->GetVertex());
Vec3r B2(woeb->GetbVertex()->GetVertex());
Vec3r B(B1 + tb * (B2 - B1));
if (feprevious && (B - va->point3D()).norm() < 1.0e-6) {
return feprevious;
}
vb = MakeSVertex(B, false);
// Set normal:
Vec3r NB1(ifl.fl->getFace()->GetVertexNormal(woeb->GetaVertex()));
Vec3r NB2(ifl.fl->getFace()->GetVertexNormal(woeb->GetbVertex()));
Vec3r nb((1 - tb) * NB1 + tb * NB2);
nb.normalize();
normal += nb;
vb->AddNormal(nb);
// Set CurvatureInfo
CurvatureInfo *curvature_info_b = new CurvatureInfo(
*(dynamic_cast<WXVertex *>(woeb->GetaVertex())->curvatures()),
*(dynamic_cast<WXVertex *>(woeb->GetbVertex())->curvatures()),
tb);
vb->setCurvatureInfo(curvature_info_b);
// Creates the corresponding feature edge
fe = new FEdgeSmooth(va, vb);
fe->setNature(ifl.fl->nature());
fe->setId(_currentFId);
fe->setFrsMaterialIndex(ifl.fl->getFace()->frs_materialIndex());
fe->setFace(ifl.fl->getFace());
fe->setFaceMark(ifl.fl->getFace()->GetMark());
if (feprevious == 0) {
normal.normalize();
}
fe->setNormal(normal);
fe->setPreviousEdge(feprevious);
if (feprevious) {
feprevious->setNextEdge(fe);
}
_pCurrentSShape->AddEdge(fe);
va->AddFEdge(fe);
vb->AddFEdge(fe);
++_currentFId;
ifl.fl->userdata = fe;
return fe;
}
bool ViewEdgeXBuilder::stopSmoothViewEdge(WXFaceLayer *iFaceLayer)
{
if (NULL == iFaceLayer) {
return true;
}
if (iFaceLayer->userdata == 0) {
return false;
}
return true;
}
int ViewEdgeXBuilder::retrieveFaceMarks(WXEdge *iEdge)
{
WFace *aFace = iEdge->GetaFace();
WFace *bFace = iEdge->GetbFace();
int result = 0;
if (aFace && aFace->GetMark()) {
result += 1;
}
if (bFace && bFace->GetMark()) {
result += 2;
}
return result;
}
OWXEdge ViewEdgeXBuilder::FindNextWEdge(const OWXEdge &iEdge)
{
if (Nature::NO_FEATURE == iEdge.e->nature()) {
return OWXEdge(NULL, true);
}
WVertex *v;
if (true == iEdge.order) {
v = iEdge.e->GetbVertex();
}
else {
v = iEdge.e->GetaVertex();
}
if (((WXVertex *)v)->isFeature()) {
return 0; /* XXX eeek? NULL? OWXEdge(NULL, true/false)?*/
}
int faceMarks = retrieveFaceMarks(iEdge.e);
vector<WEdge *> &vEdges = (v)->GetEdges();
for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
WXEdge *wxe = dynamic_cast<WXEdge *>(*ve);
if (wxe == iEdge.e) {
continue; // same edge as the one processed
}
if (wxe->nature() != iEdge.e->nature()) {
continue;
}
// check face mark continuity
if (retrieveFaceMarks(wxe) != faceMarks) {
continue;
}
if (wxe->GetaVertex() == v) {
// That means that the face necessarily lies on the edge left.
// So the vertex order is OK.
return OWXEdge(wxe, true);
}
else {
// That means that the face necessarily lies on the edge left.
// So the vertex order is OK.
return OWXEdge(wxe, false);
}
}
// we did not find:
return OWXEdge(NULL, true);
}
OWXEdge ViewEdgeXBuilder::FindPreviousWEdge(const OWXEdge &iEdge)
{
if (Nature::NO_FEATURE == iEdge.e->nature()) {
return OWXEdge(NULL, true);
}
WVertex *v;
if (true == iEdge.order) {
v = iEdge.e->GetaVertex();
}
else {
v = iEdge.e->GetbVertex();
}
if (((WXVertex *)v)->isFeature()) {
return 0;
}
int faceMarks = retrieveFaceMarks(iEdge.e);
vector<WEdge *> &vEdges = (v)->GetEdges();
for (vector<WEdge *>::iterator ve = vEdges.begin(), veend = vEdges.end(); ve != veend; ve++) {
WXEdge *wxe = dynamic_cast<WXEdge *>(*ve);
if (wxe == iEdge.e) {
continue; // same edge as the one processed
}
if (wxe->nature() != iEdge.e->nature()) {
continue;
}
// check face mark continuity
if (retrieveFaceMarks(wxe) != faceMarks) {
continue;
}
if (wxe->GetbVertex() == v) {
return OWXEdge(wxe, true);
}
else {
return OWXEdge(wxe, false);
}
}
// we did not find:
return OWXEdge(NULL, true);
}
FEdge *ViewEdgeXBuilder::BuildSharpFEdge(FEdge *feprevious, const OWXEdge &iwe)
{
SVertex *va, *vb;
FEdgeSharp *fe;
Vec3r vA, vB;
if (iwe.order) {
vA = iwe.e->GetaVertex()->GetVertex();
vB = iwe.e->GetbVertex()->GetVertex();
}
else {
vA = iwe.e->GetbVertex()->GetVertex();
vB = iwe.e->GetaVertex()->GetVertex();
}
// Make the 2 SVertex
va = MakeSVertex(vA, true);
vb = MakeSVertex(vB, true);
// get the faces normals and the material indices
Vec3r normalA, normalB;
unsigned matA(0), matB(0);
bool faceMarkA = false, faceMarkB = false;
if (iwe.order) {
normalB = (iwe.e->GetbFace()->GetNormal());
matB = (iwe.e->GetbFace()->frs_materialIndex());
faceMarkB = (iwe.e->GetbFace()->GetMark());
if (!(iwe.e->nature() & Nature::BORDER)) {
normalA = (iwe.e->GetaFace()->GetNormal());
matA = (iwe.e->GetaFace()->frs_materialIndex());
faceMarkA = (iwe.e->GetaFace()->GetMark());
}
}
else {
normalA = (iwe.e->GetbFace()->GetNormal());
matA = (iwe.e->GetbFace()->frs_materialIndex());
faceMarkA = (iwe.e->GetbFace()->GetMark());
if (!(iwe.e->nature() & Nature::BORDER)) {
normalB = (iwe.e->GetaFace()->GetNormal());
matB = (iwe.e->GetaFace()->frs_materialIndex());
faceMarkB = (iwe.e->GetaFace()->GetMark());
}
}
// Creates the corresponding feature edge
fe = new FEdgeSharp(va, vb);
fe->setNature(iwe.e->nature());
fe->setId(_currentFId);
fe->setaFrsMaterialIndex(matA);
fe->setbFrsMaterialIndex(matB);
fe->setaFaceMark(faceMarkA);
fe->setbFaceMark(faceMarkB);
fe->setNormalA(normalA);
fe->setNormalB(normalB);
fe->setPreviousEdge(feprevious);
if (feprevious) {
feprevious->setNextEdge(fe);
}
_pCurrentSShape->AddEdge(fe);
va->AddFEdge(fe);
vb->AddFEdge(fe);
// Add normals:
va->AddNormal(normalA);
va->AddNormal(normalB);
vb->AddNormal(normalA);
vb->AddNormal(normalB);
++_currentFId;
iwe.e->userdata = fe;
return fe;
}
bool ViewEdgeXBuilder::stopSharpViewEdge(WXEdge *iEdge)
{
if (NULL == iEdge) {
return true;
}
if (iEdge->userdata == 0) {
return false;
}
return true;
}
SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint)
{
SVertex *va = new SVertex(iPoint, _currentSVertexId);
SilhouetteGeomEngine::ProjectSilhouette(va);
++_currentSVertexId;
// Add the svertex to the SShape svertex list:
_pCurrentSShape->AddNewVertex(va);
return va;
}
SVertex *ViewEdgeXBuilder::MakeSVertex(Vec3r &iPoint, bool shared)
{
SVertex *va;
if (!shared) {
va = MakeSVertex(iPoint);
}
else {
// Check whether the iPoint is already in the table
SVertexMap::const_iterator found = _SVertexMap.find(iPoint);
if (shared && found != _SVertexMap.end()) {
va = (*found).second;
}
else {
va = MakeSVertex(iPoint);
// Add the svertex into the table using iPoint as the key
_SVertexMap[iPoint] = va;
}
}
return va;
}
ViewVertex *ViewEdgeXBuilder::MakeViewVertex(SVertex *iSVertex)
{
ViewVertex *vva = iSVertex->viewvertex();
if (vva) {
return vva;
}
vva = new NonTVertex(iSVertex);
// Add the view vertex to the ViewShape svertex list:
_pCurrentVShape->AddVertex(vva);
return vva;
}
} /* namespace Freestyle */