Files
test/source/blender/freestyle/intern/winged_edge/WEdge.cpp

735 lines
18 KiB
C++
Raw Normal View History

/*
* 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 Classes to define a Winged Edge data structure.
*/
2008-04-30 15:41:54 +00:00
#include <iostream>
2008-04-30 15:41:54 +00:00
#include "WEdge.h"
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
namespace Freestyle {
2008-04-30 15:41:54 +00:00
/*! Temporary structures */
class vertexdata {
public:
WVertex *_copy;
2008-04-30 15:41:54 +00:00
};
class oedgedata {
public:
WOEdge *_copy;
2008-04-30 15:41:54 +00:00
};
class edgedata {
public:
WEdge *_copy;
2008-04-30 15:41:54 +00:00
};
class facedata {
public:
WFace *_copy;
2008-04-30 15:41:54 +00:00
};
/**********************************
* *
* *
* WVertex *
* *
* *
**********************************/
2008-04-30 15:41:54 +00:00
WVertex::WVertex(WVertex &iBrother)
2008-04-30 15:41:54 +00:00
{
_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;
2008-04-30 15:41:54 +00:00
}
WVertex *WVertex::duplicate()
2008-04-30 15:41:54 +00:00
{
WVertex *clone = new WVertex(*this);
return clone;
2008-04-30 15:41:54 +00:00
}
WOEdge *WVertex::incoming_edge_iterator::operator*()
{
return _current;
2008-04-30 15:41:54 +00:00
}
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 = NULL;
}
_current = next;
2008-04-30 15:41:54 +00:00
}
WFace *WVertex::face_iterator::operator*()
{
WOEdge *woedge = *_edge_it;
if (!woedge) {
return NULL;
}
return (woedge)->GetbFace();
2008-04-30 15:41:54 +00:00
}
#if 0
bool WVertex::isBoundary() const
{
return _Border;
}
#endif
bool WVertex::isBoundary()
{
if (_Border == 1) {
return true;
}
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 0
if (!(*it)->GetaOEdge()->GetaFace()) {
return true;
}
#endif
_Border = 0;
return false;
2008-04-30 15:41:54 +00:00
}
void WVertex::AddEdge(WEdge *iEdge)
{
_EdgeList.push_back(iEdge);
2008-04-30 15:41:54 +00:00
}
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);
2008-04-30 15:41:54 +00:00
}
#if 0
WOEdge **WVertex::incoming_edge_iterator::operator->()
{
WOEdge **ppaOEdge = (*_iter)->GetaOEdge();
if (aOEdge->GetbVertex() == _vertex) {
return ppaOEdge;
}
else {
WOEdge *bOEdge = (*_iter)->GetbOEdge();
return &bOEdge;
}
2008-04-30 15:41:54 +00:00
}
#endif
/**********************************
* *
* *
* WOEdge *
* *
* *
**********************************/
2008-04-30 15:41:54 +00:00
WOEdge::WOEdge(WOEdge &iBrother)
2008-04-30 15:41:54 +00:00
{
_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;
_vec = iBrother._vec;
_angle = iBrother._angle;
2008-04-30 15:41:54 +00:00
}
WOEdge *WOEdge::duplicate()
2008-04-30 15:41:54 +00:00
{
WOEdge *clone = new WOEdge(*this);
return clone;
2008-04-30 15:41:54 +00:00
}
WOEdge *WOEdge::twin()
2008-04-30 15:41:54 +00:00
{
return GetOwner()->GetOtherOEdge(this);
2008-04-30 15:41:54 +00:00
}
WOEdge *WOEdge::getPrevOnFace()
2008-04-30 15:41:54 +00:00
{
return _pbFace->GetPrevOEdge(this);
2008-04-30 15:41:54 +00:00
}
/**********************************
* *
* *
* WEdge *
* *
* *
**********************************/
2008-04-30 15:41:54 +00:00
WEdge::WEdge(WEdge &iBrother)
{
_paOEdge = NULL;
_pbOEdge = NULL;
WOEdge *aoedge = iBrother.GetaOEdge();
WOEdge *boedge = iBrother.GetbOEdge();
userdata = NULL;
if (aoedge) {
//_paOEdge = new WOEdge(*aoedge);
_paOEdge = aoedge->duplicate();
}
if (boedge) {
//_pbOEdge = new WOEdge(*boedge);
_pbOEdge = boedge->duplicate();
}
_nOEdges = iBrother.GetNumberOfOEdges();
_Id = iBrother.GetId();
iBrother.userdata = new edgedata;
((edgedata *)(iBrother.userdata))->_copy = this;
2008-04-30 15:41:54 +00:00
}
WEdge *WEdge::duplicate()
2008-04-30 15:41:54 +00:00
{
WEdge *clone = new WEdge(*this);
return clone;
2008-04-30 15:41:54 +00:00
}
/**********************************
* *
* *
* WFace *
* *
* *
**********************************/
2008-04-30 15:41:54 +00:00
WFace::WFace(WFace &iBrother)
{
_OEdgeList = iBrother.getEdgeList();
_Normal = iBrother.GetNormal();
_VerticesNormals = iBrother._VerticesNormals;
_VerticesTexCoords = iBrother._VerticesTexCoords;
_Id = iBrother.GetId();
_FrsMaterialIndex = iBrother._FrsMaterialIndex;
_Mark = iBrother._Mark;
userdata = NULL;
iBrother.userdata = new facedata;
((facedata *)(iBrother.userdata))->_copy = this;
2008-04-30 15:41:54 +00:00
}
WFace *WFace::duplicate()
2008-04-30 15:41:54 +00:00
{
WFace *clone = new WFace(*this);
return clone;
2008-04-30 15:41:54 +00:00
}
const FrsMaterial &WFace::frs_material()
{
return getShape()->frs_material(_FrsMaterialIndex);
2008-04-30 15:41:54 +00:00
}
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)) {
// The oriented edge already exists
cerr << "Warning: edge " << v1->GetId() << " - " << v2->GetId()
<< " appears twice, correcting" << endl;
// Adds the edge to the face
AddEdge(woea);
(*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges() + 1);
// sets these vertices as border:
v1->setBorder(true);
v2->setBorder(true);
return woea;
}
WOEdge *woeb = we->GetbOEdge();
if (woeb && (woeb->GetaVertex() == v1) && (woeb->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(woeb);
(*it1)->setNumberOfOEdges((*it1)->GetNumberOfOEdges() + 1);
// sets these vertices as border:
v1->setBorder(true);
v2->setBorder(true);
return woeb;
}
}
// the oriented edge we're about to build
WOEdge *pOEdge = new WOEdge;
// The edge containing the oriented edge.
WEdge *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;
2008-04-30 15:41:54 +00:00
}
bool WFace::getOppositeEdge(const WVertex *v, WOEdge *&e)
2008-04-30 15:41:54 +00:00
{
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;
}
return true;
2008-04-30 15:41:54 +00:00
}
float WFace::getArea()
2008-04-30 15:41:54 +00:00
{
vector<WOEdge *>::iterator it;
Vec3f origin = (*(_OEdgeList.begin()))->GetaVertex()->GetVertex();
it = _OEdgeList.begin();
float a = 0;
for (it = it++; it != _OEdgeList.end(); it++) {
Vec3f v1 = Vec3f((*it)->GetaVertex()->GetVertex() - origin);
Vec3f v2 = Vec3f((*it)->GetbVertex()->GetVertex() - origin);
a += (v1 ^ v2).norm() / 2.0f;
}
return a;
2008-04-30 15:41:54 +00:00
}
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;
}
2008-04-30 15:41:54 +00:00
WShape *WFace::getShape()
2008-04-30 15:41:54 +00:00
{
return GetVertex(0)->shape();
2008-04-30 15:41:54 +00:00
}
/**********************************
* *
* *
* WShape *
* *
* *
**********************************/
2008-04-30 15:41:54 +00:00
unsigned WShape::_SceneCurrentId = 0;
WShape *WShape::duplicate()
2008-04-30 15:41:54 +00:00
{
WShape *clone = new WShape(*this);
return clone;
2008-04-30 15:41:54 +00:00
}
WShape::WShape(WShape &iBrother)
2008-04-30 15:41:54 +00:00
{
_Id = iBrother.GetId();
_Name = iBrother._Name;
_LibraryPath = iBrother._LibraryPath;
_FrsMaterials = iBrother._FrsMaterials;
#if 0
_meanEdgeSize = iBrother._meanEdgeSize;
iBrother.bbox(_min, _max);
#endif
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 (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) {
boEdge->setaVertex(((vertexdata *)(boEdge->GetaVertex()->userdata))->_copy);
boEdge->setbVertex(((vertexdata *)(boEdge->GetbVertex()->userdata))->_copy);
if (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 int i;
const vector<WOEdge *> &oedgeList = (*f)->getEdgeList();
vector<WOEdge *> newoedgelist;
unsigned int 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 (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;
}
2008-04-30 15:41:54 +00:00
}
WFace *WShape::MakeFace(vector<WVertex *> &iVertexList,
vector<bool> &iFaceEdgeMarksList,
unsigned iMaterial)
2008-04-30 15:41:54 +00:00
{
// allocate the new face
WFace *face = instanciateFace();
2008-04-30 15:41:54 +00:00
WFace *result = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial, face);
if (!result) {
delete face;
}
return result;
}
2008-04-30 15:41:54 +00:00
WFace *WShape::MakeFace(vector<WVertex *> &iVertexList,
vector<Vec3f> &iNormalsList,
vector<Vec2f> &iTexCoordsList,
vector<bool> &iFaceEdgeMarksList,
unsigned iMaterial)
{
// allocate the new face
WFace *face = MakeFace(iVertexList, iFaceEdgeMarksList, iMaterial);
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
if (!face) {
return NULL;
}
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
// set the list of per-vertex normals
face->setNormalList(iNormalsList);
// set the list of per-vertex tex coords
face->setTexCoordsList(iTexCoordsList);
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
return face;
}
Optimized view map calculation by Alexander Beels. * View map calculation has been intensively optimized for speed by means of: 1) new spatial grid data structures (SphericalGrid for perspective cameras and BoxGrid for orthographic cameras; automatically switched based on the camera type); 2) a heuristic grid density calculation algorithm; and 3) new line visibility computation algorithms: A "traditional" algorithm for emulating old visibility algorithms, and a "cumulative" algorithm for improved, more consistent line visibility, both exploiting the new spatial grid data structures for fast ray casting. A new option "Raycasting Algorithm" was added to allow users to choose a ray casting (line visibility) algorithm. Available choices are: - Normal Ray Casting - Fast Ray Casting - Very Fast Ray Casting - Culled Traditional Visibility Detection - Unculled Traditional Visibility Detection - Culled Cumulative Visibility Detection - Unculled Cumulative Visibility Detection The first three algorithms are those available in the original Freestyle (the "normal" ray casting was used unconditionally, though). The "fast" and "very fast" ray casting algorithms achieve a faster calculation at the cost of less visibility accuracy. The last four are newly introduced optimized options. The culled versions of the new algorithms will exclude from visibility calculation those faces that lay outside the camera, which leads to a faster view map construction. The unculled counterparts will take all faces into account. The unculled visibility algorithms are useful when culling affects stroke chaining. The recommended options for users are the culled/unculled cumulative visibility algorithms. These options are meant to replace the old algorithms in the future. Performance improvements over the old algorithms depend on the scenes to be rendered. * Silhouette detection has also been considerably optimized for speed. Performance gains by this optimization do not depend on scenes. * Improper handling of error conditions in the view map construction was fixed.
2011-03-14 00:36:27 +00:00
WFace *WShape::MakeFace(vector<WVertex *> &iVertexList,
vector<bool> &iFaceEdgeMarksList,
unsigned iMaterial,
WFace *face)
{
int id = _FaceList.size();
face->setFrsMaterialIndex(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 NULL;
}
}
vector<WVertex *>::iterator it;
// compute the face normal (v1v2 ^ v1v3)
// Double precision numbers are used here to avoid truncation errors [T47705]
Vec3r v1, v2, v3;
it = iVertexList.begin();
v1 = (*it)->GetVertex();
it++;
v2 = (*it)->GetVertex();
it++;
v3 = (*it)->GetVertex();
Vec3r vector1(v2 - v1);
Vec3r vector2(v3 - v1);
Vec3r normal(vector1 ^ vector2);
normal.normalize();
face->setNormal(normal);
vector<bool>::iterator mit = iFaceEdgeMarksList.begin();
face->setMark(*mit);
mit++;
// vertex pointers used to build each edge
vector<WVertex *>::iterator va, vb;
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) {
return NULL;
}
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);
#if 0
// compute the mean edge value:
_meanEdgeSize += edge->GetaOEdge()->GetVec().norm();
#endif
}
edge->setMark(*mit);
++mit;
}
// Add the face to the shape's faces list:
face->setId(id);
AddFace(face);
2008-04-30 15:41:54 +00:00
return face;
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
}
real WShape::ComputeMeanEdgeSize() const
{
real meanEdgeSize = 0.0;
for (vector<WEdge *>::const_iterator it = _EdgeList.begin(), itend = _EdgeList.end();
it != itend;
it++) {
meanEdgeSize += (*it)->GetaOEdge()->GetVec().norm();
}
return meanEdgeSize / (real)_EdgeList.size();
}
Attempt to fix a potential name conflict between Freestyle and the compositor. A crash in the Freestyle renderer was reported by Ton on IRC with a stack trace below. Note that #2 is in Freestyle, whereas #1 is in the compositor. The problem was observed in a debug build on OS X 10.7 (gcc 4.2, openmp disabled, no llvm). ---------------------------------------------------------------------- Program received signal EXC_BAD_ACCESS, Could not access memory. Reason: 13 at address: 0x0000000000000000 [Switching to process 72386 thread 0xf303] 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 43 delete (this->m_outputsockets.back()); Current language: auto; currently c++ (gdb) where #0 0x0000000100c129f3 in NodeBase::~NodeBase (this=0x10e501c80) at COM_NodeBase.cpp:43 #1 0x0000000100c29066 in Node::~Node (this=0x10e501c80) at COM_Node.h:49 #2 0x000000010089c273 in NodeShape::~NodeShape (this=0x10e501c80) at NodeShape.cpp:43 #3 0x000000010089910b in NodeGroup::destroy (this=0x10e501da0) at NodeGroup.cpp:61 #4 0x00000001008990cd in NodeGroup::destroy (this=0x10e5014b0) at NodeGroup.cpp:59 #5 0x00000001008990cd in NodeGroup::destroy (this=0x114e18da0) at NodeGroup.cpp:59 #6 0x00000001007e6602 in Controller::ClearRootNode (this=0x114e19640) at Controller.cpp:329 #7 0x00000001007ea52e in Controller::LoadMesh (this=0x114e19640, re=0x10aba4638, srl=0x1140f5258) at Controller.cpp:302 #8 0x00000001008030ad in prepare (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:302 #9 0x000000010080457a in FRS_do_stroke_rendering (re=0x10aba4638, srl=0x1140f5258) at FRS_freestyle.cpp:600 #10 0x00000001006aeb9d in add_freestyle (re=0x10aba4638) at pipeline.c:1584 #11 0x00000001006aceb7 in do_render_3d (re=0x10aba4638) at pipeline.c:1094 #12 0x00000001006ae061 in do_render_fields_blur_3d (re=0x10aba4638) at pipeline.c:1367 #13 0x00000001006afa16 in do_render_composite_fields_blur_3d (re=0x10aba4638) at pipeline.c:1815 #14 0x00000001006b04e4 in do_render_all_options (re=0x10aba4638) at pipeline.c:2021 ---------------------------------------------------------------------- Apparently a name conflict between the two Blender modules is taking place. The present commit hence intends to address it by putting all the Freestyle C++ classes in the namespace 'Freestyle'. This revision will also prevent potential name conflicts with other Blender modules in the future. Special thanks to Lukas Toenne for the help with C++ namespace.
2013-04-09 00:46:49 +00:00
} /* namespace Freestyle */