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:
@@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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
|
||||
|
||||
Reference in New Issue
Block a user