1311 lines
27 KiB
C++
1311 lines
27 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 Functions to manage I/O for the view map
|
|
*/
|
|
|
|
#include <limits.h>
|
|
|
|
#include "ViewMapIO.h"
|
|
|
|
#ifdef IRIX
|
|
# define WRITE(n) Internal::write<sizeof((n))>(out, (const char *)(&(n)))
|
|
# define READ(n) Internal::read<sizeof((n))>(in, (char *)(&(n)))
|
|
#else
|
|
# define WRITE(n) out.write((const char *)(&(n)), sizeof((n)))
|
|
# define READ(n) in.read((char *)(&(n)), sizeof((n)))
|
|
#endif
|
|
|
|
#define WRITE_IF_NON_NULL(ptr) \
|
|
if (ptr) { \
|
|
WRITE((ptr)->userdata); \
|
|
} \
|
|
else { \
|
|
WRITE(ZERO); \
|
|
} \
|
|
(void)0
|
|
|
|
#define READ_IF_NON_NULL(ptr, array) \
|
|
READ(tmp); \
|
|
if (tmp) { \
|
|
(ptr) = (array)[tmp]; \
|
|
} \
|
|
else { \
|
|
(ptr) = NULL; \
|
|
} \
|
|
(void)0
|
|
|
|
namespace Freestyle {
|
|
|
|
namespace ViewMapIO {
|
|
|
|
namespace Internal {
|
|
|
|
static ViewMap *g_vm;
|
|
|
|
//////////////////// 'load' Functions ////////////////////
|
|
|
|
inline int load(istream &in, Vec3r &v)
|
|
{
|
|
if (Options::getFlags() & Options::FLOAT_VECTORS) {
|
|
float tmp;
|
|
READ(tmp);
|
|
v[0] = tmp;
|
|
READ(tmp);
|
|
v[1] = tmp;
|
|
READ(tmp);
|
|
v[2] = tmp;
|
|
}
|
|
else {
|
|
Vec3r::value_type tmp;
|
|
READ(tmp);
|
|
v[0] = tmp;
|
|
READ(tmp);
|
|
v[1] = tmp;
|
|
READ(tmp);
|
|
v[2] = tmp;
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int load(istream &in, Polygon3r &p)
|
|
{
|
|
unsigned tmp;
|
|
|
|
// Id
|
|
READ(tmp);
|
|
p.setId(tmp);
|
|
|
|
// vertices (List)
|
|
vector<Vec3r> tmp_vec;
|
|
Vec3r v;
|
|
READ(tmp);
|
|
for (unsigned int i = 0; i < tmp; i++) {
|
|
load(in, v);
|
|
tmp_vec.push_back(v);
|
|
}
|
|
p.setVertices(tmp_vec);
|
|
|
|
// min & max
|
|
// Already computed (in the SetVertices() method)
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline int load(istream &in, FrsMaterial &m)
|
|
{
|
|
float tmp_array[4];
|
|
int i;
|
|
|
|
// Diffuse
|
|
for (i = 0; i < 4; i++) {
|
|
READ(tmp_array[i]);
|
|
}
|
|
m.setDiffuse(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
|
|
|
|
// Specular
|
|
for (i = 0; i < 4; i++) {
|
|
READ(tmp_array[i]);
|
|
}
|
|
m.setSpecular(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
|
|
|
|
// Ambient
|
|
for (i = 0; i < 4; i++) {
|
|
READ(tmp_array[i]);
|
|
}
|
|
m.setAmbient(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
|
|
|
|
// Emission
|
|
for (i = 0; i < 4; i++) {
|
|
READ(tmp_array[i]);
|
|
}
|
|
m.setEmission(tmp_array[0], tmp_array[1], tmp_array[2], tmp_array[3]);
|
|
|
|
// Shininess
|
|
READ(tmp_array[0]);
|
|
m.setShininess(tmp_array[0]);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load(istream &in, ViewShape *vs)
|
|
{
|
|
if (!vs || !vs->sshape()) {
|
|
return 1;
|
|
}
|
|
|
|
// SShape
|
|
|
|
// -> Id
|
|
Id::id_type id1, id2;
|
|
READ(id1);
|
|
READ(id2);
|
|
vs->sshape()->setId(Id(id1, id2));
|
|
|
|
// -> Importance
|
|
float importance;
|
|
READ(importance);
|
|
vs->sshape()->setImportance(importance);
|
|
|
|
// -> BBox
|
|
// Not necessary (only used during view map computatiom)
|
|
|
|
unsigned i, size, tmp;
|
|
|
|
// -> Material
|
|
READ(size);
|
|
vector<FrsMaterial> frs_materials;
|
|
FrsMaterial m;
|
|
for (i = 0; i < size; ++i) {
|
|
load(in, m);
|
|
frs_materials.push_back(m);
|
|
}
|
|
vs->sshape()->setFrsMaterials(frs_materials);
|
|
|
|
// -> VerticesList (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
SVertex *sv;
|
|
READ_IF_NON_NULL(sv, g_vm->SVertices());
|
|
vs->sshape()->AddNewVertex(sv);
|
|
}
|
|
|
|
// -> Chains (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
FEdge *fe;
|
|
READ_IF_NON_NULL(fe, g_vm->FEdges());
|
|
vs->sshape()->AddChain(fe);
|
|
}
|
|
|
|
// -> EdgesList (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
FEdge *fe;
|
|
READ_IF_NON_NULL(fe, g_vm->FEdges());
|
|
vs->sshape()->AddEdge(fe);
|
|
}
|
|
|
|
// ViewEdges (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
ViewEdge *ve;
|
|
READ_IF_NON_NULL(ve, g_vm->ViewEdges());
|
|
vs->AddEdge(ve);
|
|
}
|
|
|
|
// ViewVertices (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
ViewVertex *vv;
|
|
READ_IF_NON_NULL(vv, g_vm->ViewVertices());
|
|
vs->AddVertex(vv);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load(istream &in, FEdge *fe)
|
|
{
|
|
if (!fe) {
|
|
return 1;
|
|
}
|
|
|
|
bool b;
|
|
|
|
FEdgeSmooth *fesmooth = NULL;
|
|
FEdgeSharp *fesharp = NULL;
|
|
if (fe->isSmooth()) {
|
|
fesmooth = dynamic_cast<FEdgeSmooth *>(fe);
|
|
}
|
|
else {
|
|
fesharp = dynamic_cast<FEdgeSharp *>(fe);
|
|
}
|
|
|
|
// Id
|
|
Id::id_type id1, id2;
|
|
READ(id1);
|
|
READ(id2);
|
|
fe->setId(Id(id1, id2));
|
|
|
|
// Nature
|
|
Nature::EdgeNature nature;
|
|
READ(nature);
|
|
fe->setNature(nature);
|
|
|
|
#if 0 // hasVisibilityPoint
|
|
bool b;
|
|
READ(b);
|
|
fe->setHasVisibilityPoint(b);
|
|
#endif
|
|
|
|
Vec3r v;
|
|
unsigned int matindex;
|
|
|
|
#if 0
|
|
// VisibilityPointA
|
|
load(in, v);
|
|
fe->setVisibilityPointA(v);
|
|
|
|
// VisibilityPointB
|
|
load(in, v);
|
|
fe->setVisibilityPointB(v);
|
|
#endif
|
|
|
|
if (fe->isSmooth()) {
|
|
// Normal
|
|
load(in, v);
|
|
fesmooth->setNormal(v);
|
|
|
|
// Material
|
|
READ(matindex);
|
|
fesmooth->setFrsMaterialIndex(matindex);
|
|
}
|
|
else {
|
|
// aNormal
|
|
load(in, v);
|
|
fesharp->setNormalA(v);
|
|
|
|
// bNormal
|
|
load(in, v);
|
|
fesharp->setNormalB(v);
|
|
|
|
// Materials
|
|
READ(matindex);
|
|
fesharp->setaFrsMaterialIndex(matindex);
|
|
READ(matindex);
|
|
fesharp->setbFrsMaterialIndex(matindex);
|
|
}
|
|
|
|
unsigned tmp;
|
|
|
|
// VertexA
|
|
SVertex *sva;
|
|
READ_IF_NON_NULL(sva, g_vm->SVertices());
|
|
fe->setVertexA(sva);
|
|
|
|
// VertexB
|
|
SVertex *svb;
|
|
READ_IF_NON_NULL(svb, g_vm->SVertices());
|
|
fe->setVertexB(svb);
|
|
|
|
// NextEdge
|
|
FEdge *nfe;
|
|
READ_IF_NON_NULL(nfe, g_vm->FEdges());
|
|
fe->setNextEdge(nfe);
|
|
|
|
// PreviousEdge
|
|
FEdge *pfe;
|
|
READ_IF_NON_NULL(pfe, g_vm->FEdges());
|
|
fe->setPreviousEdge(pfe);
|
|
|
|
// ViewEdge
|
|
ViewEdge *ve;
|
|
READ_IF_NON_NULL(ve, g_vm->ViewEdges());
|
|
fe->setViewEdge(ve);
|
|
|
|
// Face
|
|
// Not necessary (only used during view map computatiom)
|
|
|
|
Polygon3r p;
|
|
|
|
// aFace
|
|
load(in, p);
|
|
fe->setaFace(p);
|
|
|
|
// occludeeEmpty
|
|
READ(b);
|
|
fe->setOccludeeEmpty(b);
|
|
|
|
// occludeeIntersection
|
|
load(in, v);
|
|
fe->setOccludeeIntersection(v);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load(istream &in, SVertex *sv)
|
|
{
|
|
if (!sv) {
|
|
return 1;
|
|
}
|
|
|
|
// Id
|
|
Id::id_type id1, id2;
|
|
READ(id1);
|
|
READ(id2);
|
|
sv->setId(Id(id1, id2));
|
|
|
|
Vec3r v;
|
|
|
|
// Point3D
|
|
load(in, v);
|
|
sv->setPoint3D(v);
|
|
|
|
// Point2D
|
|
load(in, v);
|
|
sv->setPoint2D(v);
|
|
|
|
unsigned tmp;
|
|
|
|
// Shape
|
|
ViewShape *vs;
|
|
READ_IF_NON_NULL(vs, g_vm->ViewShapes());
|
|
sv->setShape(vs->sshape());
|
|
|
|
// pViewVertex
|
|
ViewVertex *vv;
|
|
READ_IF_NON_NULL(vv, g_vm->ViewVertices());
|
|
sv->setViewVertex(vv);
|
|
|
|
unsigned i, size;
|
|
|
|
// Normals (List)
|
|
READ(size);
|
|
for (i = 0; i < size; i++) {
|
|
load(in, v);
|
|
sv->AddNormal(v);
|
|
}
|
|
|
|
// FEdges (List)
|
|
READ(size);
|
|
FEdge *fe;
|
|
for (i = 0; i < size; i++) {
|
|
READ_IF_NON_NULL(fe, g_vm->FEdges());
|
|
sv->AddFEdge(fe);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load(istream &in, ViewEdge *ve)
|
|
{
|
|
if (!ve) {
|
|
return 1;
|
|
}
|
|
|
|
unsigned tmp;
|
|
|
|
// Id
|
|
Id::id_type id1, id2;
|
|
READ(id1);
|
|
READ(id2);
|
|
ve->setId(Id(id1, id2));
|
|
|
|
// Nature
|
|
Nature::EdgeNature nature;
|
|
READ(nature);
|
|
ve->setNature(nature);
|
|
|
|
// QI
|
|
READ(tmp);
|
|
ve->setQI(tmp);
|
|
|
|
// Shape
|
|
ViewShape *vs;
|
|
READ_IF_NON_NULL(vs, g_vm->ViewShapes());
|
|
ve->setShape(vs);
|
|
|
|
// aShape
|
|
ViewShape *avs;
|
|
READ_IF_NON_NULL(avs, g_vm->ViewShapes());
|
|
ve->setaShape(avs);
|
|
|
|
// FEdgeA
|
|
FEdge *fea;
|
|
READ_IF_NON_NULL(fea, g_vm->FEdges());
|
|
ve->setFEdgeA(fea);
|
|
|
|
// FEdgeB
|
|
FEdge *feb;
|
|
READ_IF_NON_NULL(feb, g_vm->FEdges());
|
|
ve->setFEdgeB(feb);
|
|
|
|
// A
|
|
ViewVertex *vva;
|
|
READ_IF_NON_NULL(vva, g_vm->ViewVertices());
|
|
ve->setA(vva);
|
|
|
|
// B
|
|
ViewVertex *vvb;
|
|
READ_IF_NON_NULL(vvb, g_vm->ViewVertices());
|
|
ve->setB(vvb);
|
|
|
|
// Occluders (List)
|
|
if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
|
|
unsigned size;
|
|
READ(size);
|
|
ViewShape *vso;
|
|
for (unsigned int i = 0; i < size; i++) {
|
|
READ_IF_NON_NULL(vso, g_vm->ViewShapes());
|
|
ve->AddOccluder(vso);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int load(istream &in, ViewVertex *vv)
|
|
{
|
|
if (!vv) {
|
|
return 1;
|
|
}
|
|
|
|
unsigned tmp;
|
|
bool b;
|
|
|
|
// Nature
|
|
Nature::VertexNature nature;
|
|
READ(nature);
|
|
vv->setNature(nature);
|
|
|
|
if (vv->getNature() & Nature::T_VERTEX) {
|
|
TVertex *tv = dynamic_cast<TVertex *>(vv);
|
|
|
|
// Id
|
|
Id::id_type id1, id2;
|
|
READ(id1);
|
|
READ(id2);
|
|
tv->setId(Id(id1, id2));
|
|
|
|
// FrontSVertex
|
|
SVertex *fsv;
|
|
READ_IF_NON_NULL(fsv, g_vm->SVertices());
|
|
tv->setFrontSVertex(fsv);
|
|
|
|
// BackSVertex
|
|
SVertex *bsv;
|
|
READ_IF_NON_NULL(bsv, g_vm->SVertices());
|
|
tv->setBackSVertex(bsv);
|
|
|
|
// FrontEdgeA
|
|
ViewEdge *fea;
|
|
READ_IF_NON_NULL(fea, g_vm->ViewEdges());
|
|
READ(b);
|
|
tv->setFrontEdgeA(fea, b);
|
|
|
|
// FrontEdgeB
|
|
ViewEdge *feb;
|
|
READ_IF_NON_NULL(feb, g_vm->ViewEdges());
|
|
READ(b);
|
|
tv->setFrontEdgeB(feb, b);
|
|
|
|
// BackEdgeA
|
|
ViewEdge *bea;
|
|
READ_IF_NON_NULL(bea, g_vm->ViewEdges());
|
|
READ(b);
|
|
tv->setBackEdgeA(bea, b);
|
|
|
|
// BackEdgeB
|
|
ViewEdge *beb;
|
|
READ_IF_NON_NULL(beb, g_vm->ViewEdges());
|
|
READ(b);
|
|
tv->setBackEdgeB(beb, b);
|
|
}
|
|
else if (vv->getNature() & Nature::NON_T_VERTEX) {
|
|
NonTVertex *ntv = dynamic_cast<NonTVertex *>(vv);
|
|
|
|
// SVertex
|
|
SVertex *sv;
|
|
READ_IF_NON_NULL(sv, g_vm->SVertices());
|
|
ntv->setSVertex(sv);
|
|
|
|
// ViewEdges (List)
|
|
unsigned size;
|
|
READ(size);
|
|
ViewEdge *ve;
|
|
for (unsigned int i = 0; i < size; i++) {
|
|
READ_IF_NON_NULL(ve, g_vm->ViewEdges());
|
|
READ(b);
|
|
ntv->AddViewEdge(ve, b);
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
//////////////////// 'save' Functions ////////////////////
|
|
|
|
inline int save(ostream &out, const Vec3r &v)
|
|
{
|
|
if (Options::getFlags() & Options::FLOAT_VECTORS) {
|
|
float tmp;
|
|
|
|
tmp = v[0];
|
|
WRITE(tmp);
|
|
tmp = v[1];
|
|
WRITE(tmp);
|
|
tmp = v[2];
|
|
WRITE(tmp);
|
|
}
|
|
else {
|
|
Vec3r::value_type tmp;
|
|
|
|
tmp = v[0];
|
|
WRITE(tmp);
|
|
tmp = v[1];
|
|
WRITE(tmp);
|
|
tmp = v[2];
|
|
WRITE(tmp);
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
inline int save(ostream &out, const Polygon3r &p)
|
|
{
|
|
unsigned tmp;
|
|
|
|
// Id
|
|
tmp = p.getId();
|
|
WRITE(tmp);
|
|
|
|
// vertices (List)
|
|
tmp = p.getVertices().size();
|
|
WRITE(tmp);
|
|
for (vector<Vec3r>::const_iterator i = p.getVertices().begin(); i != p.getVertices().end();
|
|
i++) {
|
|
save(out, *i);
|
|
}
|
|
|
|
// min & max
|
|
// Do not need to be saved
|
|
|
|
return 0;
|
|
}
|
|
|
|
inline int save(ostream &out, const FrsMaterial &m)
|
|
{
|
|
unsigned i;
|
|
|
|
// Diffuse
|
|
for (i = 0; i < 4; i++) {
|
|
WRITE(m.diffuse()[i]);
|
|
}
|
|
|
|
// Specular
|
|
for (i = 0; i < 4; i++) {
|
|
WRITE(m.specular()[i]);
|
|
}
|
|
|
|
// Ambient
|
|
for (i = 0; i < 4; i++) {
|
|
WRITE(m.ambient()[i]);
|
|
}
|
|
|
|
// Emission
|
|
for (i = 0; i < 4; i++) {
|
|
WRITE(m.emission()[i]);
|
|
}
|
|
|
|
// Shininess
|
|
float shininess = m.shininess();
|
|
WRITE(shininess);
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int save(ostream &out, ViewShape *vs)
|
|
{
|
|
if (!vs || !vs->sshape()) {
|
|
cerr << "Warning: null ViewShape" << endl;
|
|
return 1;
|
|
}
|
|
|
|
unsigned tmp;
|
|
|
|
// SShape
|
|
|
|
// -> Id
|
|
Id::id_type id = vs->sshape()->getId().getFirst();
|
|
WRITE(id);
|
|
id = vs->sshape()->getId().getSecond();
|
|
WRITE(id);
|
|
|
|
// -> Importance
|
|
float importance = vs->sshape()->importance();
|
|
WRITE(importance);
|
|
|
|
// -> BBox
|
|
// Not necessary (only used during view map computatiom)
|
|
|
|
// -> Material
|
|
unsigned int size = vs->sshape()->frs_materials().size();
|
|
WRITE(size);
|
|
for (unsigned int i = 0; i < size; ++i) {
|
|
save(out, vs->sshape()->frs_material(i));
|
|
}
|
|
|
|
// -> VerticesList (List)
|
|
tmp = vs->sshape()->getVertexList().size();
|
|
WRITE(tmp);
|
|
for (vector<SVertex *>::const_iterator i1 = vs->sshape()->getVertexList().begin();
|
|
i1 != vs->sshape()->getVertexList().end();
|
|
i1++) {
|
|
WRITE_IF_NON_NULL(*i1);
|
|
}
|
|
|
|
// -> Chains (List)
|
|
tmp = vs->sshape()->getChains().size();
|
|
WRITE(tmp);
|
|
for (vector<FEdge *>::const_iterator i2 = vs->sshape()->getChains().begin();
|
|
i2 != vs->sshape()->getChains().end();
|
|
i2++) {
|
|
WRITE_IF_NON_NULL(*i2);
|
|
}
|
|
|
|
// -> EdgesList (List)
|
|
tmp = vs->sshape()->getEdgeList().size();
|
|
WRITE(tmp);
|
|
for (vector<FEdge *>::const_iterator i3 = vs->sshape()->getEdgeList().begin();
|
|
i3 != vs->sshape()->getEdgeList().end();
|
|
i3++) {
|
|
WRITE_IF_NON_NULL(*i3);
|
|
}
|
|
|
|
// ViewEdges (List)
|
|
tmp = vs->edges().size();
|
|
WRITE(tmp);
|
|
for (vector<ViewEdge *>::const_iterator i4 = vs->edges().begin(); i4 != vs->edges().end();
|
|
i4++) {
|
|
WRITE_IF_NON_NULL(*i4);
|
|
}
|
|
|
|
// ViewVertices (List)
|
|
tmp = vs->vertices().size();
|
|
WRITE(tmp);
|
|
for (vector<ViewVertex *>::const_iterator i5 = vs->vertices().begin();
|
|
i5 != vs->vertices().end();
|
|
i5++) {
|
|
WRITE_IF_NON_NULL(*i5);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int save(ostream &out, FEdge *fe)
|
|
{
|
|
if (!fe) {
|
|
cerr << "Warning: null FEdge" << endl;
|
|
return 1;
|
|
}
|
|
|
|
FEdgeSmooth *fesmooth = dynamic_cast<FEdgeSmooth *>(fe);
|
|
FEdgeSharp *fesharp = dynamic_cast<FEdgeSharp *>(fe);
|
|
|
|
// Id
|
|
Id::id_type id = fe->getId().getFirst();
|
|
WRITE(id);
|
|
id = fe->getId().getSecond();
|
|
WRITE(id);
|
|
|
|
// Nature
|
|
Nature::EdgeNature nature = fe->getNature();
|
|
WRITE(nature);
|
|
|
|
bool b;
|
|
|
|
#if 0
|
|
// hasVisibilityPoint
|
|
b = fe->hasVisibilityPoint();
|
|
WRITE(b);
|
|
|
|
// VisibilityPointA
|
|
save(out, fe->visibilityPointA());
|
|
|
|
// VisibilityPointB
|
|
save(out, fe->visibilityPointB());
|
|
#endif
|
|
|
|
unsigned index;
|
|
if (fe->isSmooth()) {
|
|
// normal
|
|
save(out, fesmooth->normal());
|
|
// material
|
|
index = fesmooth->frs_materialIndex();
|
|
WRITE(index);
|
|
}
|
|
else {
|
|
// aNormal
|
|
save(out, fesharp->normalA());
|
|
// bNormal
|
|
save(out, fesharp->normalB());
|
|
// aMaterial
|
|
index = fesharp->aFrsMaterialIndex();
|
|
WRITE(index);
|
|
// bMaterial
|
|
index = fesharp->bFrsMaterialIndex();
|
|
WRITE(index);
|
|
}
|
|
|
|
// VertexA
|
|
WRITE_IF_NON_NULL(fe->vertexA());
|
|
|
|
// VertexB
|
|
WRITE_IF_NON_NULL(fe->vertexB());
|
|
|
|
// NextEdge
|
|
WRITE_IF_NON_NULL(fe->nextEdge());
|
|
|
|
// PreviousEdge
|
|
WRITE_IF_NON_NULL(fe->previousEdge());
|
|
|
|
// ViewEdge
|
|
WRITE_IF_NON_NULL(fe->viewedge());
|
|
|
|
// Face
|
|
// Not necessary (only used during view map computatiom)
|
|
|
|
// aFace
|
|
save(out, (Polygon3r &)fe->aFace());
|
|
|
|
// occludeeEmpty
|
|
b = fe->getOccludeeEmpty();
|
|
WRITE(b);
|
|
|
|
// occludeeIntersection
|
|
save(out, fe->getOccludeeIntersection());
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int save(ostream &out, SVertex *sv)
|
|
{
|
|
if (!sv) {
|
|
cerr << "Warning: null SVertex" << endl;
|
|
return 1;
|
|
}
|
|
|
|
unsigned tmp;
|
|
|
|
// Id
|
|
Id::id_type id = sv->getId().getFirst();
|
|
WRITE(id);
|
|
id = sv->getId().getSecond();
|
|
WRITE(id);
|
|
|
|
Vec3r v;
|
|
|
|
// Point3D
|
|
v = sv->point3D();
|
|
save(out, sv->point3D());
|
|
|
|
// Point2D
|
|
v = sv->point2D();
|
|
save(out, v);
|
|
|
|
// Shape
|
|
WRITE_IF_NON_NULL(sv->shape());
|
|
|
|
// pViewVertex
|
|
WRITE_IF_NON_NULL(sv->viewvertex());
|
|
|
|
// Normals (List)
|
|
// Note: the 'size()' method of a set doesn't seem to return the actual size of the given set, so
|
|
// we have to hack it...
|
|
set<Vec3r>::const_iterator i;
|
|
for (i = sv->normals().begin(), tmp = 0; i != sv->normals().end(); i++, tmp++) {
|
|
/* pass */
|
|
}
|
|
WRITE(tmp);
|
|
for (i = sv->normals().begin(); i != sv->normals().end(); i++) {
|
|
save(out, *i);
|
|
}
|
|
|
|
// FEdges (List)
|
|
tmp = sv->fedges().size();
|
|
WRITE(tmp);
|
|
for (vector<FEdge *>::const_iterator j = sv->fedges_begin(); j != sv->fedges_end(); j++) {
|
|
WRITE_IF_NON_NULL(*j);
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int save(ostream &out, ViewEdge *ve)
|
|
{
|
|
if (!ve) {
|
|
cerr << "Warning: null ViewEdge" << endl;
|
|
return 1;
|
|
}
|
|
|
|
unsigned tmp;
|
|
|
|
// Id
|
|
Id::id_type id = ve->getId().getFirst();
|
|
WRITE(id);
|
|
id = ve->getId().getSecond();
|
|
WRITE(id);
|
|
|
|
// Nature
|
|
Nature::EdgeNature nature = ve->getNature();
|
|
WRITE(nature);
|
|
|
|
// QI
|
|
unsigned qi = ve->qi();
|
|
WRITE(qi);
|
|
|
|
// Shape
|
|
WRITE_IF_NON_NULL(ve->shape());
|
|
|
|
// aShape
|
|
WRITE_IF_NON_NULL(ve->aShape());
|
|
|
|
// FEdgeA
|
|
WRITE_IF_NON_NULL(ve->fedgeA());
|
|
|
|
// FEdgeB
|
|
WRITE_IF_NON_NULL(ve->fedgeB());
|
|
|
|
// A
|
|
WRITE_IF_NON_NULL(ve->A());
|
|
|
|
// B
|
|
WRITE_IF_NON_NULL(ve->B());
|
|
|
|
// Occluders (List)
|
|
if (!(Options::getFlags() & Options::NO_OCCLUDERS)) {
|
|
tmp = ve->occluders().size();
|
|
WRITE(tmp);
|
|
for (vector<ViewShape *>::const_iterator i = ve->occluders().begin();
|
|
i != ve->occluders().end();
|
|
i++) {
|
|
WRITE_IF_NON_NULL((*i));
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int save(ostream &out, ViewVertex *vv)
|
|
{
|
|
if (!vv) {
|
|
cerr << "Warning: null ViewVertex" << endl;
|
|
return 1;
|
|
}
|
|
|
|
// Nature
|
|
Nature::VertexNature nature = vv->getNature();
|
|
WRITE(nature);
|
|
|
|
if (vv->getNature() & Nature::T_VERTEX) {
|
|
TVertex *tv = dynamic_cast<TVertex *>(vv);
|
|
|
|
// Id
|
|
Id::id_type id = tv->getId().getFirst();
|
|
WRITE(id);
|
|
id = tv->getId().getSecond();
|
|
WRITE(id);
|
|
|
|
// FrontSVertex
|
|
WRITE_IF_NON_NULL(tv->frontSVertex());
|
|
|
|
// BackSVertex
|
|
WRITE_IF_NON_NULL(tv->backSVertex());
|
|
|
|
// FrontEdgeA
|
|
WRITE_IF_NON_NULL(tv->frontEdgeA().first);
|
|
WRITE(tv->frontEdgeA().second);
|
|
|
|
// FrontEdgeB
|
|
WRITE_IF_NON_NULL(tv->frontEdgeB().first);
|
|
WRITE(tv->frontEdgeB().second);
|
|
|
|
// BackEdgeA
|
|
WRITE_IF_NON_NULL(tv->backEdgeA().first);
|
|
WRITE(tv->backEdgeA().second);
|
|
|
|
// BackEdgeB
|
|
WRITE_IF_NON_NULL(tv->backEdgeB().first);
|
|
WRITE(tv->backEdgeB().second);
|
|
}
|
|
else if (vv->getNature() & Nature::NON_T_VERTEX) {
|
|
NonTVertex *ntv = dynamic_cast<NonTVertex *>(vv);
|
|
|
|
// SVertex
|
|
WRITE_IF_NON_NULL(ntv->svertex());
|
|
|
|
// ViewEdges (List)
|
|
unsigned size = ntv->viewedges().size();
|
|
WRITE(size);
|
|
vector<ViewVertex::directedViewEdge>::const_iterator i = ntv->viewedges().begin();
|
|
for (; i != ntv->viewedges().end(); i++) {
|
|
WRITE_IF_NON_NULL(i->first);
|
|
WRITE(i->second);
|
|
}
|
|
}
|
|
else {
|
|
cerr << "Warning: unexpected ViewVertex nature" << endl;
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
} // End of namespace Internal
|
|
|
|
//////////////////// "Public" 'load' and 'save' functions ////////////////////
|
|
|
|
#define SET_PROGRESS(n) \
|
|
if (pb) { \
|
|
pb->setProgress((n)); \
|
|
} \
|
|
(void)0
|
|
|
|
int load(istream &in, ViewMap *vm, ProgressBar *pb)
|
|
{
|
|
if (!vm) {
|
|
return 1;
|
|
}
|
|
|
|
// soc unused - unsigned tmp;
|
|
int err = 0;
|
|
Internal::g_vm = vm;
|
|
|
|
// Management of the progress bar (if present)
|
|
if (pb) {
|
|
pb->reset();
|
|
pb->setLabelText("Loading View Map...");
|
|
pb->setTotalSteps(6);
|
|
pb->setProgress(0);
|
|
}
|
|
|
|
// Read and set the options
|
|
unsigned char flags;
|
|
READ(flags);
|
|
Options::setFlags(flags);
|
|
|
|
// Read the size of the five ViewMap's lists (with some extra information for the ViewVertices)
|
|
// and instantiate them (with default costructors)
|
|
unsigned vs_s, fe_s, fe_rle1, fe_rle2, sv_s, ve_s, vv_s, vv_rle1, vv_rle2;
|
|
READ(vs_s);
|
|
READ(fe_s);
|
|
|
|
if (fe_s) {
|
|
bool b;
|
|
READ(b);
|
|
for (READ(fe_rle1), fe_rle2 = 0; fe_rle1 <= fe_s; fe_rle2 = fe_rle1, READ(fe_rle1)) {
|
|
if (b) {
|
|
for (unsigned int i = fe_rle2; i < fe_rle1; i++) {
|
|
FEdgeSmooth *fes = new FEdgeSmooth;
|
|
vm->AddFEdge(fes);
|
|
}
|
|
b = !b;
|
|
}
|
|
else if (!b) {
|
|
for (unsigned int i = fe_rle2; i < fe_rle1; i++) {
|
|
FEdgeSharp *fes = new FEdgeSharp;
|
|
vm->AddFEdge(fes);
|
|
}
|
|
b = !b;
|
|
}
|
|
}
|
|
}
|
|
|
|
READ(sv_s);
|
|
READ(ve_s);
|
|
READ(vv_s);
|
|
|
|
if (vv_s) {
|
|
Nature::VertexNature nature;
|
|
READ(nature);
|
|
for (READ(vv_rle1), vv_rle2 = 0; vv_rle1 <= vv_s; vv_rle2 = vv_rle1, READ(vv_rle1)) {
|
|
if (nature & Nature::T_VERTEX) {
|
|
for (unsigned int i = vv_rle2; i < vv_rle1; i++) {
|
|
TVertex *tv = new TVertex();
|
|
vm->AddViewVertex(tv);
|
|
}
|
|
nature = Nature::NON_T_VERTEX;
|
|
}
|
|
else if (nature & Nature::NON_T_VERTEX) {
|
|
for (unsigned int i = vv_rle2; i < vv_rle1; i++) {
|
|
NonTVertex *ntv = new NonTVertex();
|
|
vm->AddViewVertex(ntv);
|
|
}
|
|
nature = Nature::T_VERTEX;
|
|
}
|
|
}
|
|
}
|
|
|
|
for (unsigned int i0 = 0; i0 < vs_s; i0++) {
|
|
SShape *ss = new SShape();
|
|
ViewShape *vs = new ViewShape();
|
|
vs->setSShape(ss);
|
|
ss->setViewShape(vs);
|
|
vm->AddViewShape(vs);
|
|
}
|
|
#if 0
|
|
for (unsigned int i1 = 0; i1 < fe_s; i1++) {
|
|
FEdge *fe = new FEdge();
|
|
vm->AddFEdge(fe);
|
|
}
|
|
#endif
|
|
for (unsigned int i2 = 0; i2 < sv_s; i2++) {
|
|
SVertex *sv = new SVertex();
|
|
vm->AddSVertex(sv);
|
|
}
|
|
for (unsigned int i3 = 0; i3 < ve_s; i3++) {
|
|
ViewEdge *ve = new ViewEdge();
|
|
vm->AddViewEdge(ve);
|
|
}
|
|
|
|
// Read the values for all the objects created above
|
|
SET_PROGRESS(1);
|
|
for (vector<ViewShape *>::const_iterator i4 = vm->ViewShapes().begin();
|
|
i4 != vm->ViewShapes().end();
|
|
i4++) {
|
|
err += Internal::load(in, *i4);
|
|
}
|
|
SET_PROGRESS(2);
|
|
for (vector<FEdge *>::const_iterator i5 = vm->FEdges().begin(); i5 != vm->FEdges().end(); i5++) {
|
|
err += Internal::load(in, *i5);
|
|
}
|
|
SET_PROGRESS(3);
|
|
for (vector<SVertex *>::const_iterator i6 = vm->SVertices().begin(); i6 != vm->SVertices().end();
|
|
i6++) {
|
|
err += Internal::load(in, *i6);
|
|
}
|
|
SET_PROGRESS(4);
|
|
for (vector<ViewEdge *>::const_iterator i7 = vm->ViewEdges().begin();
|
|
i7 != vm->ViewEdges().end();
|
|
i7++) {
|
|
err += Internal::load(in, *i7);
|
|
}
|
|
SET_PROGRESS(5);
|
|
for (vector<ViewVertex *>::const_iterator i8 = vm->ViewVertices().begin();
|
|
i8 != vm->ViewVertices().end();
|
|
i8++) {
|
|
err += Internal::load(in, *i8);
|
|
}
|
|
SET_PROGRESS(6);
|
|
|
|
// Read the shape id to index mapping
|
|
unsigned map_s;
|
|
READ(map_s);
|
|
unsigned id, index;
|
|
for (unsigned int i4 = 0; i4 < map_s; ++i4) {
|
|
READ(id);
|
|
READ(index);
|
|
vm->shapeIdToIndexMap()[id] = index;
|
|
}
|
|
|
|
return err;
|
|
}
|
|
|
|
int save(ostream &out, ViewMap *vm, ProgressBar *pb)
|
|
{
|
|
if (!vm) {
|
|
return 1;
|
|
}
|
|
|
|
int err = 0;
|
|
|
|
// Management of the progress bar (if present)
|
|
if (pb) {
|
|
pb->reset();
|
|
pb->setLabelText("Saving View Map...");
|
|
pb->setTotalSteps(6);
|
|
pb->setProgress(0);
|
|
}
|
|
|
|
// For every object, initialize its userdata member to its index in the ViewMap list
|
|
for (unsigned int i0 = 0; i0 < vm->ViewShapes().size(); i0++) {
|
|
vm->ViewShapes()[i0]->userdata = POINTER_FROM_UINT(i0);
|
|
vm->ViewShapes()[i0]->sshape()->userdata = POINTER_FROM_UINT(i0);
|
|
}
|
|
for (unsigned int i1 = 0; i1 < vm->FEdges().size(); i1++) {
|
|
vm->FEdges()[i1]->userdata = POINTER_FROM_UINT(i1);
|
|
}
|
|
for (unsigned int i2 = 0; i2 < vm->SVertices().size(); i2++) {
|
|
vm->SVertices()[i2]->userdata = POINTER_FROM_UINT(i2);
|
|
}
|
|
for (unsigned int i3 = 0; i3 < vm->ViewEdges().size(); i3++) {
|
|
vm->ViewEdges()[i3]->userdata = POINTER_FROM_UINT(i3);
|
|
}
|
|
for (unsigned int i4 = 0; i4 < vm->ViewVertices().size(); i4++) {
|
|
vm->ViewVertices()[i4]->userdata = POINTER_FROM_UINT(i4);
|
|
}
|
|
|
|
// Write the current options
|
|
unsigned char flags = Options::getFlags();
|
|
WRITE(flags);
|
|
|
|
// Write the size of the five lists (with some extra information for the ViewVertices)
|
|
unsigned size;
|
|
size = vm->ViewShapes().size();
|
|
WRITE(size);
|
|
size = vm->FEdges().size();
|
|
WRITE(size);
|
|
if (size) {
|
|
bool b = vm->FEdges()[0]->isSmooth();
|
|
WRITE(b);
|
|
for (unsigned int i = 0; i < size; i++) {
|
|
while (i < size && (vm->FEdges()[i]->isSmooth() == b)) {
|
|
i++;
|
|
}
|
|
if (i < size) {
|
|
WRITE(i);
|
|
b = !b;
|
|
}
|
|
}
|
|
WRITE(size);
|
|
size++;
|
|
WRITE(size);
|
|
}
|
|
size = vm->SVertices().size();
|
|
WRITE(size);
|
|
size = vm->ViewEdges().size();
|
|
WRITE(size);
|
|
size = vm->ViewVertices().size();
|
|
WRITE(size);
|
|
if (size) {
|
|
Nature::VertexNature nature = vm->ViewVertices()[0]->getNature();
|
|
WRITE(nature);
|
|
nature &= ~Nature::VIEW_VERTEX;
|
|
for (unsigned int i = 0; i < size; i++) {
|
|
while (i < size && (vm->ViewVertices()[i]->getNature() & nature)) {
|
|
i++;
|
|
}
|
|
if (i < size) {
|
|
WRITE(i);
|
|
nature = vm->ViewVertices()[i]->getNature() & ~Nature::VIEW_VERTEX;
|
|
}
|
|
}
|
|
WRITE(size);
|
|
size++;
|
|
WRITE(size);
|
|
}
|
|
|
|
// Write all the elts of the ViewShapes List
|
|
SET_PROGRESS(1);
|
|
for (vector<ViewShape *>::const_iterator i5 = vm->ViewShapes().begin();
|
|
i5 != vm->ViewShapes().end();
|
|
i5++) {
|
|
err += Internal::save(out, *i5);
|
|
}
|
|
SET_PROGRESS(2);
|
|
for (vector<FEdge *>::const_iterator i6 = vm->FEdges().begin(); i6 != vm->FEdges().end(); i6++) {
|
|
err += Internal::save(out, *i6);
|
|
}
|
|
SET_PROGRESS(3);
|
|
for (vector<SVertex *>::const_iterator i7 = vm->SVertices().begin(); i7 != vm->SVertices().end();
|
|
i7++) {
|
|
err += Internal::save(out, *i7);
|
|
}
|
|
SET_PROGRESS(4);
|
|
for (vector<ViewEdge *>::const_iterator i8 = vm->ViewEdges().begin();
|
|
i8 != vm->ViewEdges().end();
|
|
i8++) {
|
|
err += Internal::save(out, *i8);
|
|
}
|
|
SET_PROGRESS(5);
|
|
for (vector<ViewVertex *>::const_iterator i9 = vm->ViewVertices().begin();
|
|
i9 != vm->ViewVertices().end();
|
|
i9++) {
|
|
err += Internal::save(out, *i9);
|
|
}
|
|
|
|
// Write the shape id to index mapping
|
|
size = vm->shapeIdToIndexMap().size();
|
|
WRITE(size);
|
|
unsigned int id, index;
|
|
for (ViewMap::id_to_index_map::iterator mit = vm->shapeIdToIndexMap().begin(),
|
|
mitend = vm->shapeIdToIndexMap().end();
|
|
mit != mitend;
|
|
++mit) {
|
|
id = mit->first;
|
|
index = mit->second;
|
|
WRITE(id);
|
|
WRITE(index);
|
|
}
|
|
|
|
// Reset 'userdata' members
|
|
for (vector<ViewShape *>::const_iterator j0 = vm->ViewShapes().begin();
|
|
j0 != vm->ViewShapes().end();
|
|
j0++) {
|
|
(*j0)->userdata = NULL;
|
|
(*j0)->sshape()->userdata = NULL;
|
|
}
|
|
for (vector<FEdge *>::const_iterator j1 = vm->FEdges().begin(); j1 != vm->FEdges().end(); j1++) {
|
|
(*j1)->userdata = NULL;
|
|
}
|
|
for (vector<SVertex *>::const_iterator j2 = vm->SVertices().begin(); j2 != vm->SVertices().end();
|
|
j2++) {
|
|
(*j2)->userdata = NULL;
|
|
}
|
|
for (vector<ViewEdge *>::const_iterator j3 = vm->ViewEdges().begin();
|
|
j3 != vm->ViewEdges().end();
|
|
j3++) {
|
|
(*j3)->userdata = NULL;
|
|
}
|
|
for (vector<ViewVertex *>::const_iterator j4 = vm->ViewVertices().begin();
|
|
j4 != vm->ViewVertices().end();
|
|
j4++) {
|
|
(*j4)->userdata = NULL;
|
|
}
|
|
SET_PROGRESS(6);
|
|
|
|
return err;
|
|
}
|
|
|
|
//////////////////// Options ////////////////////
|
|
|
|
namespace Options {
|
|
|
|
namespace Internal {
|
|
|
|
static unsigned char g_flags = 0;
|
|
static string g_models_path;
|
|
|
|
} // End of namespace Internal
|
|
|
|
void setFlags(const unsigned char flags)
|
|
{
|
|
Internal::g_flags = flags;
|
|
}
|
|
|
|
void addFlags(const unsigned char flags)
|
|
{
|
|
Internal::g_flags |= flags;
|
|
}
|
|
|
|
void rmFlags(const unsigned char flags)
|
|
{
|
|
Internal::g_flags &= ~flags;
|
|
}
|
|
|
|
unsigned char getFlags()
|
|
{
|
|
return Internal::g_flags;
|
|
}
|
|
|
|
void setModelsPath(const string &path)
|
|
{
|
|
Internal::g_models_path = path;
|
|
}
|
|
|
|
string getModelsPath()
|
|
{
|
|
return Internal::g_models_path;
|
|
}
|
|
|
|
} // namespace Options
|
|
|
|
} // End of namespace ViewMapIO
|
|
|
|
} /* namespace Freestyle */
|