Freestyle: Fix for destructive view map modifications during chaining operations.

The view map is mostly treated as a read-only data structure by line stylization
operations (i.e., selection, chaining, splitting, sorting and stroke creation).  The
only exception is the chaining operation in some cases where insertion of extra
FEdge objects is necessary to ensure the continuity of underlying FEdges from
which a chain is constructed.

The present revision addresses the removal of extra FEdges so to keep the view
map clean and suitable for reuse in subsequent render frames.
This commit is contained in:
2014-10-02 15:26:53 +09:00
parent c946a450ed
commit c47682d6ab
5 changed files with 80 additions and 4 deletions

View File

@@ -423,10 +423,15 @@ void Controller::DeleteViewMap(bool freeCache)
_DebugNode->addRef();
}
if ((freeCache || !_EnableViewMapCache) && NULL != _ViewMap) {
delete _ViewMap;
_ViewMap = NULL;
prevSceneHash = -1.0;
if (NULL != _ViewMap) {
if (freeCache || !_EnableViewMapCache) {
delete _ViewMap;
_ViewMap = NULL;
prevSceneHash = -1.0;
}
else {
_ViewMap->Clean();
}
}
}

View File

@@ -59,6 +59,7 @@ void Chain::push_viewedge_back(ViewEdge *iViewEdge, bool orientation)
CurvePoint *cp = _Vertices.back(); // assumed to be instantiated as new CurvePoint(iSVertex, 0, 0.f);
SVertex *sv_first = (*vfirst);
FEdge *fe = _fedgeB->duplicate();
fe->setTemporary(true);
fe->setVertexB(sv_first);
fe->vertexA()->shape()->AddEdge(fe);
fe->vertexA()->AddFEdge(fe);
@@ -119,6 +120,7 @@ void Chain::push_viewedge_front(ViewEdge *iViewEdge, bool orientation)
SVertex *sv_curr = (*v);
FEdge *fe = (orientation) ? iViewEdge->fedgeA() : iViewEdge->fedgeB();
FEdge *fe2 = fe->duplicate();
fe2->setTemporary(true);
fe2->setVertexA(sv_curr);
fe2->setVertexB(sv_last);
sv_last->AddFEdge(fe2);

View File

@@ -378,6 +378,17 @@ public:
_FEdges.push_back(iFEdge);
}
/*! Remove an FEdge from the list of edges emanating from this SVertex. */
inline void RemoveFEdge(FEdge *iFEdge)
{
for (vector<FEdge *>::iterator fe = _FEdges.begin(), fend = _FEdges.end(); fe != fend; fe++) {
if (iFEdge == (*fe)) {
_FEdges.erase(fe);
break;
}
}
}
/* replaces edge 1 by edge 2 in the list of edges */
inline void Replace(FEdge *e1, FEdge *e2)
{
@@ -441,6 +452,10 @@ public:
/*! angle in radians */
inline real curvature2d_as_angle() const;
#endif
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:SVertex")
#endif
};
/**********************************/
@@ -518,6 +533,8 @@ protected:
bool _isInImage;
bool _isTemporary;
public:
/*! A field that can be used by the user to store any data.
* This field must be reseted afterwards using ResetUserData().
@@ -538,6 +555,7 @@ public:
_occludeeEmpty = true;
_isSmooth = false;
_isInImage = true;
_isTemporary = false;
}
/*! Builds an FEdge going from vA to vB. */
@@ -554,6 +572,7 @@ public:
_occludeeEmpty = true;
_isSmooth = false;
_isInImage = true;
_isTemporary = false;
}
/*! Copy constructor */
@@ -573,6 +592,7 @@ public:
_occludeeEmpty = iBrother._occludeeEmpty;
_isSmooth = iBrother._isSmooth;
_isInImage = iBrother._isInImage;
_isTemporary = iBrother._isTemporary;
iBrother.userdata = this;
userdata = 0;
}
@@ -708,6 +728,11 @@ public:
return _isInImage;
}
inline bool isTemporary() const
{
return _isTemporary;
}
/* modifiers */
/*! Sets the first SVertex. */
inline void setVertexA(SVertex *vA)
@@ -803,6 +828,11 @@ public:
_isInImage = iFlag;
}
inline void setTemporary(bool iFlag)
{
_isTemporary = iFlag;
}
/* checks whether two FEdge have a common vertex.
* Returns a pointer on the common vertex if it exists, NULL otherwise.
*/
@@ -931,6 +961,10 @@ public:
* The sampling with which we want to iterate over points of this FEdge.
*/
virtual inline Interface0DIterator pointsEnd(float t = 0.0f);
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdge")
#endif
};
//
@@ -1241,6 +1275,10 @@ public:
{
_bFaceMark = iFaceMark;
}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSharp")
#endif
};
/*! Class defining a smooth edge. This kind of edge typically runs across a face of the input mesh. It can be
@@ -1353,6 +1391,10 @@ public:
{
_FrsMaterialIndex = i;
}
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:FEdgeSmooth")
#endif
};

View File

@@ -63,6 +63,30 @@ ViewMap::~ViewMap()
_VEdges.clear();
}
void ViewMap::Clean()
{
vector<FEdge*> tmpEdges;
for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) {
vector<FEdge*>& edges = (*vs)->sshape()->getEdgeList();
for (vector<FEdge*>::iterator it = edges.begin(), itend = edges.end(); it != itend; it++) {
if ((*it)->isTemporary()) {
(*it)->setTemporary(false); // avoid being counted multiple times
tmpEdges.push_back(*it);
}
}
}
for (vector<FEdge*>::iterator it = tmpEdges.begin(), itend = tmpEdges.end(); it != itend; it++) {
for (vector<ViewShape*>::iterator vs = _VShapes.begin(), vsend = _VShapes.end(); vs != vsend; vs++) {
(*vs)->sshape()->RemoveEdge(*it);
}
(*it)->vertexA()->RemoveFEdge(*it);
(*it)->vertexB()->RemoveFEdge(*it);
delete (*it);
}
}
ViewShape *ViewMap::viewShape(unsigned id)
{
int index = _shapeIdToIndex[id];

View File

@@ -236,6 +236,9 @@ public:
/* connects a FEdge to the graph trough a SVertex */
//FEdge *Connect(FEdge *ioEdge, SVertex *ioVertex);
/* Clean temporary FEdges created by chaining */
virtual void Clean();
#ifdef WITH_CXX_GUARDEDALLOC
MEM_CXX_CLASS_ALLOC_FUNCS("Freestyle:ViewMap")
#endif