Initial commit
This commit is contained in:
parent
e6a05ea921
commit
3bd184ced5
|
@ -0,0 +1,46 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004 \/)\/ *
|
||||||
|
* Visual Computing Lab /\/| *
|
||||||
|
* ISTI - Italian National Research Council | *
|
||||||
|
* \ *
|
||||||
|
* All rights reserved. *
|
||||||
|
* *
|
||||||
|
* 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||||
|
* for more details. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
History
|
||||||
|
|
||||||
|
$Log: not supported by cvs2svn $
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __VCGLIB_CALLBACK
|
||||||
|
#define __VCGLIB_CALLBACK
|
||||||
|
|
||||||
|
namespace vcg {
|
||||||
|
// Generic Callback function:
|
||||||
|
// Used to make algorithms interumpable
|
||||||
|
// Return value: true continue, false break
|
||||||
|
// The second callback is to know where we are (useful for progress bar)
|
||||||
|
typedef bool CallBack( const char * str );
|
||||||
|
typedef bool CallBackPos(const int pos, const char * str );
|
||||||
|
|
||||||
|
inline bool DummyCallBack( const char * ) {return true;}
|
||||||
|
inline bool DummyCallBackPos(const int pos, const char * ) {return true;}
|
||||||
|
|
||||||
|
} // End namespace
|
||||||
|
|
||||||
|
|
||||||
|
#endif
|
|
@ -0,0 +1,851 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004 \/)\/ *
|
||||||
|
* Visual Computing Lab /\/| *
|
||||||
|
* ISTI - Italian National Research Council | *
|
||||||
|
* \ *
|
||||||
|
* All rights reserved. *
|
||||||
|
* *
|
||||||
|
* 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||||
|
* for more details. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
History
|
||||||
|
|
||||||
|
$Log: not supported by cvs2svn $
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
@name Load and Save in Ply format
|
||||||
|
*/
|
||||||
|
//@{
|
||||||
|
#include<wrap/callback.h>
|
||||||
|
#include<wrap/ply/plylib.h>
|
||||||
|
#include<wrap/io_trimesh/io_mask.h>
|
||||||
|
|
||||||
|
|
||||||
|
namespace vcg {
|
||||||
|
namespace tri {
|
||||||
|
namespace io {
|
||||||
|
|
||||||
|
template <class TYPE>
|
||||||
|
int PlyType () { return 0;}
|
||||||
|
|
||||||
|
//template <class OpenMeshType>
|
||||||
|
template <> int PlyType <float >() { return ply::T_FLOAT; }
|
||||||
|
template <> int PlyType <double>() { return ply::T_DOUBLE; }
|
||||||
|
template <> int PlyType <int >() { return ply::T_INT; }
|
||||||
|
template <> int PlyType <short >() { return ply::T_SHORT; }
|
||||||
|
template <> int PlyType <unsigned char >() { return ply::T_UCHAR; }
|
||||||
|
|
||||||
|
template <class OpenMeshType>
|
||||||
|
class ImporterPLY
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
typedef ::vcg::ply::PropDescriptor PropDescriptor ;
|
||||||
|
typedef typename OpenMeshType::VertexPointer VertexPointer;
|
||||||
|
typedef typename OpenMeshType::ScalarType ScalarType;
|
||||||
|
typedef typename OpenMeshType::VertexType VertexType;
|
||||||
|
typedef typename OpenMeshType::FaceType FaceType;
|
||||||
|
typedef typename OpenMeshType::VertexIterator VertexIterator;
|
||||||
|
typedef typename OpenMeshType::FaceIterator FaceIterator;
|
||||||
|
|
||||||
|
class PlyInfo
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
PlyInfo()
|
||||||
|
{
|
||||||
|
status=0;
|
||||||
|
mask=0;
|
||||||
|
cb=0;
|
||||||
|
vdn=fdn=0;
|
||||||
|
VertexData=FaceData=0;
|
||||||
|
}
|
||||||
|
int status;
|
||||||
|
int mask; // it overwritten by Open and used by Save
|
||||||
|
CallBackPos *cb;
|
||||||
|
|
||||||
|
int vdn;
|
||||||
|
PropDescriptor *VertexData;
|
||||||
|
int fdn;
|
||||||
|
PropDescriptor *FaceData;
|
||||||
|
std::string header;
|
||||||
|
};
|
||||||
|
|
||||||
|
enum Error
|
||||||
|
{
|
||||||
|
|
||||||
|
// Funzioni superiori
|
||||||
|
E_NO_VERTEX, // 14
|
||||||
|
E_NO_FACE, // 15
|
||||||
|
E_SHORTFILE, // 16
|
||||||
|
E_NO_3VERTINFACE, // 17
|
||||||
|
E_BAD_VERT_INDEX, // 18
|
||||||
|
E_NO_6TCOORD, // 19
|
||||||
|
E_DIFFER_COLORS, // 20
|
||||||
|
};
|
||||||
|
|
||||||
|
//template <class T> int PlyType () { assert(0); return 0;}
|
||||||
|
|
||||||
|
// Si occupa di convertire da un tipo all'altro.
|
||||||
|
// usata nella saveply per matchare i tipi tra stotype e memtype.
|
||||||
|
// Ad es se in memoria c'e' un int e voglio salvare un float
|
||||||
|
// src sara in effetti un puntatore a int il cui valore deve
|
||||||
|
// essere convertito al tipo di ritorno desiderato (stotype)
|
||||||
|
|
||||||
|
template <class StoType>
|
||||||
|
void PlyConv(int mem_type, void *src, StoType &dest)
|
||||||
|
{
|
||||||
|
// float tf; int ti;short ts; char tc;
|
||||||
|
switch (mem_type){
|
||||||
|
case ply::T_FLOAT : dest = (StoType) (* ((float *) src)); break;
|
||||||
|
case T_DOUBLE : dest = (StoType) (* ((double *) src)); break;
|
||||||
|
case T_INT : dest = (StoType) (* ((int *) src)); break;
|
||||||
|
case T_SHORT : dest = (StoType) (* ((short *) src)); break;
|
||||||
|
case T_CHAR : dest = (StoType) (* ((char *) src)); break;
|
||||||
|
case T_UCHAR : dest = (StoType) (* ((unsigned char *)src)); break;
|
||||||
|
default : assert(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#define MAX_USER_DATA 256
|
||||||
|
// Struttura ausiliaria per la lettura del file ply
|
||||||
|
struct LoadPly_FaceAux
|
||||||
|
{
|
||||||
|
unsigned char size;
|
||||||
|
int v[512];
|
||||||
|
int flags;
|
||||||
|
float q;
|
||||||
|
float tcoord[32];
|
||||||
|
unsigned char ntcoord;
|
||||||
|
int tcoordind;
|
||||||
|
float colors[32];
|
||||||
|
unsigned char ncolors;
|
||||||
|
|
||||||
|
unsigned char r;
|
||||||
|
unsigned char g;
|
||||||
|
unsigned char b;
|
||||||
|
|
||||||
|
unsigned char data[MAX_USER_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
|
struct LoadPly_TristripAux
|
||||||
|
{
|
||||||
|
int size;
|
||||||
|
int *v;
|
||||||
|
unsigned char data[MAX_USER_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Struttura ausiliaria per la lettura del file ply
|
||||||
|
template<class S>
|
||||||
|
struct LoadPly_VertAux
|
||||||
|
{
|
||||||
|
S p[3];
|
||||||
|
int flags;
|
||||||
|
float q;
|
||||||
|
unsigned char r;
|
||||||
|
unsigned char g;
|
||||||
|
unsigned char b;
|
||||||
|
unsigned char data[MAX_USER_DATA];
|
||||||
|
};
|
||||||
|
|
||||||
|
// Struttura ausiliaria caricamento camera
|
||||||
|
struct LoadPly_Camera
|
||||||
|
{
|
||||||
|
float view_px;
|
||||||
|
float view_py;
|
||||||
|
float view_pz;
|
||||||
|
float x_axisx;
|
||||||
|
float x_axisy;
|
||||||
|
float x_axisz;
|
||||||
|
float y_axisx;
|
||||||
|
float y_axisy;
|
||||||
|
float y_axisz;
|
||||||
|
float z_axisx;
|
||||||
|
float z_axisy;
|
||||||
|
float z_axisz;
|
||||||
|
float focal;
|
||||||
|
float scalex;
|
||||||
|
float scaley;
|
||||||
|
float centerx;
|
||||||
|
float centery;
|
||||||
|
int viewportx;
|
||||||
|
int viewporty;
|
||||||
|
float k1;
|
||||||
|
float k2;
|
||||||
|
float k3;
|
||||||
|
float k4;
|
||||||
|
};
|
||||||
|
|
||||||
|
static const PropDescriptor &VertDesc(int i)
|
||||||
|
{
|
||||||
|
const static PropDescriptor pv[9]={
|
||||||
|
{"vertex", "x", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p[0]),0,0,0,0,0},
|
||||||
|
{"vertex", "y", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p[1]),0,0,0,0,0},
|
||||||
|
{"vertex", "z", ply::T_FLOAT, PlyType<ScalarType>(),offsetof(LoadPly_VertAux<ScalarType>,p[2]),0,0,0,0,0},
|
||||||
|
{"vertex", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_VertAux<ScalarType>,flags),0,0,0,0,0},
|
||||||
|
{"vertex", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,q),0,0,0,0,0},
|
||||||
|
{"vertex", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,r),0,0,0,0,0},
|
||||||
|
{"vertex", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,g),0,0,0,0,0},
|
||||||
|
{"vertex", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_VertAux<ScalarType>,b),0,0,0,0,0},
|
||||||
|
{"vertex", "confidence",ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_VertAux<ScalarType>,q),0,0,0,0,0},
|
||||||
|
};
|
||||||
|
return pv[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const PropDescriptor &FaceDesc(int i)
|
||||||
|
{
|
||||||
|
const static PropDescriptor qf[10]=
|
||||||
|
{
|
||||||
|
{"face", "vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,size) },
|
||||||
|
{"face", "flags", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,flags), 0,0,0,0,0},
|
||||||
|
{"face", "quality", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,q), 0,0,0,0,0},
|
||||||
|
{"face", "texcoord", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,tcoord), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ntcoord) },
|
||||||
|
{"face", "color", ply::T_FLOAT, ply::T_FLOAT, offsetof(LoadPly_FaceAux,colors), 1,0,ply::T_UCHAR,ply::T_UCHAR,offsetof(LoadPly_FaceAux,ncolors) },
|
||||||
|
{"face", "texnumber", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,tcoordind), 0,0,0,0,0},
|
||||||
|
{"face", "red" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,r), 0,0,0,0,0},
|
||||||
|
{"face", "green", ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,g), 0,0,0,0,0},
|
||||||
|
{"face", "blue" , ply::T_UCHAR, ply::T_UCHAR, offsetof(LoadPly_FaceAux,b), 0,0,0,0,0},
|
||||||
|
{"face", "vertex_index", ply::T_INT, ply::T_INT, offsetof(LoadPly_FaceAux,v), 1,0,ply::T_UCHAR,ply::T_CHAR,offsetof(LoadPly_FaceAux,size) },
|
||||||
|
};
|
||||||
|
return qf[i];
|
||||||
|
}
|
||||||
|
static const PropDescriptor &TristripDesc(int i)
|
||||||
|
{
|
||||||
|
const static PropDescriptor qf[1]=
|
||||||
|
{
|
||||||
|
{"tristrips","vertex_indices", ply::T_INT, ply::T_INT, offsetof(LoadPly_TristripAux,v), 1,1,ply::T_INT,ply::T_INT,offsetof(LoadPly_TristripAux,size) },
|
||||||
|
};
|
||||||
|
return qf[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static const PropDescriptor &CameraDesc(int i)
|
||||||
|
{
|
||||||
|
const static PropDescriptor cad[23] =
|
||||||
|
{
|
||||||
|
{"camera","view_px",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_px),0,0,0,0,0},
|
||||||
|
{"camera","view_py",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_py),0,0,0,0,0},
|
||||||
|
{"camera","view_pz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,view_pz),0,0,0,0,0},
|
||||||
|
{"camera","x_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisx),0,0,0,0,0},
|
||||||
|
{"camera","x_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisy),0,0,0,0,0},
|
||||||
|
{"camera","x_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,x_axisz),0,0,0,0,0},
|
||||||
|
{"camera","y_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisx),0,0,0,0,0},
|
||||||
|
{"camera","y_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisy),0,0,0,0,0},
|
||||||
|
{"camera","y_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,y_axisz),0,0,0,0,0},
|
||||||
|
{"camera","z_axisx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisx),0,0,0,0,0},
|
||||||
|
{"camera","z_axisy",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisy),0,0,0,0,0},
|
||||||
|
{"camera","z_axisz",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,z_axisz),0,0,0,0,0},
|
||||||
|
{"camera","focal" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,focal ),0,0,0,0,0},
|
||||||
|
{"camera","scalex" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scalex ),0,0,0,0,0},
|
||||||
|
{"camera","scaley" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,scaley ),0,0,0,0,0},
|
||||||
|
{"camera","centerx",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centerx),0,0,0,0,0},
|
||||||
|
{"camera","centery",ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,centery),0,0,0,0,0},
|
||||||
|
{"camera","viewportx",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewportx),0,0,0,0,0},
|
||||||
|
{"camera","viewporty",ply::T_INT,ply::T_INT ,offsetof(LoadPly_Camera,viewporty),0,0,0,0,0},
|
||||||
|
{"camera","k1" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k1 ),0,0,0,0,0},
|
||||||
|
{"camera","k2" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k2 ),0,0,0,0,0},
|
||||||
|
{"camera","k3" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k3 ),0,0,0,0,0},
|
||||||
|
{"camera","k4" ,ply::T_FLOAT,ply::T_FLOAT,offsetof(LoadPly_Camera,k4 ),0,0,0,0,0}
|
||||||
|
};
|
||||||
|
return cad[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
|
||||||
|
{
|
||||||
|
PlyInfo pi;
|
||||||
|
pi.cb=cb;
|
||||||
|
return Open(m, filename, pi);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int Open( OpenMeshType &m, const char * filename, int & loadmask, CallBackPos *cb =0)
|
||||||
|
{
|
||||||
|
PlyInfo pi;
|
||||||
|
pi.mask=loadmask;
|
||||||
|
return Open(m, filename,pi);
|
||||||
|
loadmask=pi.mask;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int Open( OpenMeshType &m, const char * filename, PlyInfo &pi )
|
||||||
|
{
|
||||||
|
assert(filename!=0);
|
||||||
|
vector<VertexPointer> index;
|
||||||
|
LoadPly_FaceAux fa;
|
||||||
|
LoadPly_TristripAux tsa;
|
||||||
|
LoadPly_VertAux<ScalarType> va;
|
||||||
|
|
||||||
|
pi.mask = 0;
|
||||||
|
bool multit = false; // true if texture has a per face int spec the texture index
|
||||||
|
|
||||||
|
va.flags = 42;
|
||||||
|
|
||||||
|
pi.status = ::vcg::ply::E_NOERROR;
|
||||||
|
|
||||||
|
// init defaults
|
||||||
|
VertexType tv;
|
||||||
|
tv.UberFlags() = 0;
|
||||||
|
if( VertexType::HasQuality() ) tv.Q()=1.0;
|
||||||
|
if( VertexType::HasColor() ) tv.C()=Color4b(Color4b::White);
|
||||||
|
|
||||||
|
FaceType tf;
|
||||||
|
tf.UberFlags() = 0;
|
||||||
|
if( FaceType::HasFaceQuality() ) tf.Q()=1.0;
|
||||||
|
if( FaceType::HasWedgeColor() ) tf.WC(0)=tf.WC(1)=tf.WC(2)=Color4b(Color4b::White);
|
||||||
|
if( FaceType::HasFaceColor() ) tf.C()=Color4b(Color4b::White);
|
||||||
|
// Descrittori delle strutture
|
||||||
|
|
||||||
|
//bool isvflags = false; // Il file contiene i flags
|
||||||
|
|
||||||
|
|
||||||
|
// The main descriptor of the ply file
|
||||||
|
vcg::ply::PlyFile pf;
|
||||||
|
|
||||||
|
// Open the file and parse the header
|
||||||
|
if( pf.Open(filename,vcg::ply::PlyFile::MODE_READ)==-1 )
|
||||||
|
{
|
||||||
|
pi.status = pf.GetError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
pi.header = pf.GetHeader();
|
||||||
|
|
||||||
|
// Descrittori della camera
|
||||||
|
{ // Check that all the camera properties are present.
|
||||||
|
bool found = true;
|
||||||
|
for(int i=0;i<23;++i)
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(CameraDesc(i))==-1 ) {
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(found) pi.mask |= PLYMask::PM_CAMERA;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descrittori dati standard (vertex coord e faces)
|
||||||
|
if( pf.AddToRead(VertDesc(0))==-1 ) { pi.status = E_NO_VERTEX; return -1; }
|
||||||
|
if( pf.AddToRead(VertDesc(1))==-1 ) { pi.status = E_NO_VERTEX; return -1; }
|
||||||
|
if( pf.AddToRead(VertDesc(2))==-1 ) { pi.status = E_NO_VERTEX; return -1; }
|
||||||
|
if( pf.AddToRead(FaceDesc(0))==-1 ) // Se fallisce si prova anche la sintassi di rapidform con index al posto di indices
|
||||||
|
if( pf.AddToRead(FaceDesc(9))==-1 )
|
||||||
|
if(pf.AddToRead(TristripDesc(0))==-1) // Se fallisce tutto si prova a vedere se ci sono tristrip alla levoy.
|
||||||
|
{ pi.status = E_NO_FACE; return -1; }
|
||||||
|
|
||||||
|
// Descrittori facoltativi dei flags
|
||||||
|
if( pf.AddToRead(VertDesc(3))!=-1 )
|
||||||
|
pi.mask |= PLYMask::PM_VERTFLAGS;
|
||||||
|
|
||||||
|
if( VertexType::HasQuality() )
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(VertDesc(4))!=-1 ||
|
||||||
|
pf.AddToRead(VertDesc(8))!=-1 )
|
||||||
|
pi.mask |= PLYMask::PM_VERTQUALITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( VertexType::HasColor() )
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(VertDesc(5))!=-1 )
|
||||||
|
{
|
||||||
|
pf.AddToRead(VertDesc(6));
|
||||||
|
pf.AddToRead(VertDesc(7));
|
||||||
|
pi.mask |= PLYMask::PM_VERTCOLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// se ci sono i flag per vertice ci devono essere anche i flag per faccia
|
||||||
|
if( pf.AddToRead(FaceDesc(1))!=-1 )
|
||||||
|
pi.mask |= PLYMask::PM_FACEFLAGS;
|
||||||
|
|
||||||
|
if( FaceType::HasFaceQuality())
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(FaceDesc(2))!=-1 )
|
||||||
|
pi.mask |= PLYMask::PM_FACEQUALITY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( FaceType::HasFaceColor() )
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(FaceDesc(6))!=-1 )
|
||||||
|
{
|
||||||
|
pf.AddToRead(FaceDesc(7));
|
||||||
|
pf.AddToRead(FaceDesc(8));
|
||||||
|
pi.mask |= PLYMask::PM_FACECOLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if( FaceType::HasWedgeTexture() )
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(FaceDesc(3))!=-1 )
|
||||||
|
{
|
||||||
|
if(pf.AddToRead(FaceDesc(5))==0) {
|
||||||
|
multit=true; // try to read also the multi texture indicies
|
||||||
|
pi.mask |= PLYMask::PM_WEDGTEXMULTI;
|
||||||
|
}
|
||||||
|
pi.mask |= PLYMask::PM_WEDGTEXCOORD;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( FaceType::HasWedgeColor() || FaceType::HasFaceColor() || VertexType::HasColor())
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(FaceDesc(4))!=-1 )
|
||||||
|
{
|
||||||
|
pi.mask |= PLYMask::PM_WEDGCOLOR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Descrittori definiti dall'utente,
|
||||||
|
vector<PropDescriptor> VPV(pi.vdn); // property descriptor relative al tipo LoadPly_VertexAux
|
||||||
|
vector<PropDescriptor> FPV(pi.fdn); // property descriptor relative al tipo LoadPly_FaceAux
|
||||||
|
if(pi.vdn>0){
|
||||||
|
// Compute the total size needed to load additional per vertex data.
|
||||||
|
size_t totsz=0;
|
||||||
|
for(int i=0;i<pi.vdn;i++){
|
||||||
|
VPV[i] = pi.VertexData[i];
|
||||||
|
VPV[i].offset1=offsetof(LoadPly_VertAux<ScalarType>,data)+totsz;
|
||||||
|
totsz+=pi.VertexData[i].memtypesize();
|
||||||
|
if( pf.AddToRead(VPV[i])==-1 ) { pi.status = pf.GetError(); return -1; }
|
||||||
|
}
|
||||||
|
if(totsz > MAX_USER_DATA)
|
||||||
|
{
|
||||||
|
pi.status = vcg::ply::E_BADTYPE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(pi.fdn>0){
|
||||||
|
size_t totsz=0;
|
||||||
|
for(int i=0;i<pi.fdn;i++){
|
||||||
|
FPV[i] = pi.FaceData[i];
|
||||||
|
FPV[i].offset1=offsetof(LoadPly_FaceAux,data)+totsz;
|
||||||
|
totsz+=pi.FaceData[i].memtypesize();
|
||||||
|
if( pf.AddToRead(FPV[i])==-1 ) { pi.status = pf.GetError(); return -1; }
|
||||||
|
}
|
||||||
|
if(totsz > MAX_USER_DATA)
|
||||||
|
{
|
||||||
|
pi.status = vcg::ply::E_BADTYPE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**************************************************************/
|
||||||
|
/* Main Reading Loop */
|
||||||
|
/**************************************************************/
|
||||||
|
m.Clear();
|
||||||
|
for(int i=0;i<int(pf.elements.size());i++)
|
||||||
|
{
|
||||||
|
int n = pf.ElemNumber(i);
|
||||||
|
|
||||||
|
if( !strcmp( pf.ElemName(i),"camera" ) )
|
||||||
|
{
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
LoadPly_Camera ca;
|
||||||
|
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
if( pf.Read( (void *)&(ca) )==-1 )
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
//camera.valid = true;
|
||||||
|
//camera.view_p[0] = ca.view_px;
|
||||||
|
//camera.view_p[1] = ca.view_py;
|
||||||
|
//camera.view_p[2] = ca.view_pz;
|
||||||
|
//camera.x_axis[0] = ca.x_axisx;
|
||||||
|
//camera.x_axis[1] = ca.x_axisy;
|
||||||
|
//camera.x_axis[2] = ca.x_axisz;
|
||||||
|
//camera.y_axis[0] = ca.y_axisx;
|
||||||
|
//camera.y_axis[1] = ca.y_axisy;
|
||||||
|
//camera.y_axis[2] = ca.y_axisz;
|
||||||
|
//camera.z_axis[0] = ca.z_axisx;
|
||||||
|
//camera.z_axis[1] = ca.z_axisy;
|
||||||
|
//camera.z_axis[2] = ca.z_axisz;
|
||||||
|
//camera.f = ca.focal;
|
||||||
|
//camera.s[0] = ca.scalex;
|
||||||
|
//camera.s[1] = ca.scaley;
|
||||||
|
//camera.c[0] = ca.centerx;
|
||||||
|
//camera.c[1] = ca.centery;
|
||||||
|
//camera.viewport[0] = ca.viewportx;
|
||||||
|
//camera.viewport[1] = ca.viewporty;
|
||||||
|
//camera.k[0] = ca.k1;
|
||||||
|
//camera.k[1] = ca.k2;
|
||||||
|
//camera.k[2] = ca.k3;
|
||||||
|
//camera.k[3] = ca.k4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if( !strcmp( pf.ElemName(i),"vertex" ) )
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,n);
|
||||||
|
|
||||||
|
for(j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
if(pi.cb && (j%1000)==0) pi.cb(j*50/n,"Vertex Loading");
|
||||||
|
(*vi).UberFlags()=0;
|
||||||
|
if( pf.Read( (void *)&(va) )==-1 )
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
(*vi).P()[0] = va.p[0];
|
||||||
|
(*vi).P()[1] = va.p[1];
|
||||||
|
(*vi).P()[2] = va.p[2];
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_VERTFLAGS )
|
||||||
|
(*vi).UberFlags() = va.flags;
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_VERTQUALITY )
|
||||||
|
(*vi).Q() = va.q;
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_VERTCOLOR )
|
||||||
|
{
|
||||||
|
(*vi).C()[0] = va.r;
|
||||||
|
(*vi).C()[1] = va.g;
|
||||||
|
(*vi).C()[2] = va.b;
|
||||||
|
(*vi).C()[3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for(int k=0;k<pi.vdn;k++)
|
||||||
|
memcpy((char *)(&*vi) + pi.VertexData[k].offset1,
|
||||||
|
(char *)(&va) + VPV[k].offset1,
|
||||||
|
VPV[k].memtypesize());
|
||||||
|
++vi;
|
||||||
|
}
|
||||||
|
|
||||||
|
index.resize(n);
|
||||||
|
for(j=0,vi=m.vert.begin();j<n;++j,++vi)
|
||||||
|
index[j] = &*vi;
|
||||||
|
}
|
||||||
|
else if( !strcmp( pf.ElemName(i),"face") )/************************************************************/
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
|
||||||
|
FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,n);
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
for(j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
|
||||||
|
if(pi.cb && (j%1000)==0) pi.cb(50+j*50/n,"Face Loading");
|
||||||
|
if( pf.Read(&fa)==-1 )
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(fa.size!=3)
|
||||||
|
{
|
||||||
|
pi.status = E_NO_3VERTINFACE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
for(k=0;k<3;++k)
|
||||||
|
{
|
||||||
|
if( fa.v[k]<0 || fa.v[k]>=m.vn )
|
||||||
|
{
|
||||||
|
pi.status = E_BAD_VERT_INDEX;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
(*fi).V(k) = index[ fa.v[k] ];
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_FACEFLAGS )
|
||||||
|
{
|
||||||
|
(*fi).UberFlags() = fa.flags;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_FACEQUALITY )
|
||||||
|
{
|
||||||
|
(*fi).Q() = fa.q;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_FACECOLOR )
|
||||||
|
{
|
||||||
|
(*fi).C()[0] = fa.r;
|
||||||
|
(*fi).C()[1] = fa.g;
|
||||||
|
(*fi).C()[2] = fa.b;
|
||||||
|
(*fi).C()[3] = 255;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_WEDGTEXCOORD )
|
||||||
|
{
|
||||||
|
for(int k=0;k<3;++k)
|
||||||
|
{
|
||||||
|
(*fi).WT(k).u() = fa.tcoord[k*2+0];
|
||||||
|
(*fi).WT(k).v() = fa.tcoord[k*2+1];
|
||||||
|
if(multit) (*fi).WT(k).n() = fa.tcoordind;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pi.mask & PLYMask::PM_WEDGCOLOR )
|
||||||
|
{
|
||||||
|
if(FaceType::HasWedgeColor()){
|
||||||
|
for(int k=0;k<3;++k)
|
||||||
|
{
|
||||||
|
(*fi).WC(k)[0] = (unsigned char)(fa.colors[k*3+0]*255);
|
||||||
|
(*fi).WC(k)[1] = (unsigned char)(fa.colors[k*3+1]*255);
|
||||||
|
(*fi).WC(k)[2] = (unsigned char)(fa.colors[k*3+2]*255);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if(FaceType::HasFaceColor()){
|
||||||
|
{
|
||||||
|
(*fi).C()[0] = (unsigned char)((fa.colors[0*3+0]*255+fa.colors[1*3+0]*255+fa.colors[2*3+0]*255)/3.0f);
|
||||||
|
(*fi).C()[1] = (unsigned char)((fa.colors[0*3+1]*255+fa.colors[1*3+1]*255+fa.colors[2*3+1]*255)/3.0f);
|
||||||
|
(*fi).C()[2] = (unsigned char)((fa.colors[0*3+2]*255+fa.colors[1*3+2]*255+fa.colors[2*3+2]*255)/3.0f);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for(k=0;k<pi.fdn;k++)
|
||||||
|
memcpy((char *)(&(*fi)) + pi.FaceData[k].offset1,
|
||||||
|
(char *)(&fa) + FPV[k].offset1,
|
||||||
|
FPV[k].memtypesize());
|
||||||
|
++fi;
|
||||||
|
}
|
||||||
|
}else if( !strcmp( pf.ElemName(i),"tristrips") )//////////////////// LETTURA TRISTRIP DI STANFORD
|
||||||
|
{
|
||||||
|
int j;
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
int numvert_tmp = m.vert.size();
|
||||||
|
for(j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
int k;
|
||||||
|
if(pi.cb && (j%1000)==0) pi.cb(50+j*50/n,"Tristrip Face Loading");
|
||||||
|
if( pf.Read(&tsa)==-1 )
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
int remainder=0;
|
||||||
|
int startface=m.face.size();
|
||||||
|
for(k=0;k<tsa.size-2;++k)
|
||||||
|
{
|
||||||
|
if(pi.cb && (k%1000)==0) pi.cb(50+k*50/tsa.size,"Tristrip Face Loading");
|
||||||
|
if(tsa.v[k]<0 || tsa.v[k]>=numvert_tmp ) {
|
||||||
|
pi.status = E_BAD_VERT_INDEX;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
if(tsa.v[k+2]==-1)
|
||||||
|
{
|
||||||
|
k+=2;
|
||||||
|
if(k%2) remainder=0;
|
||||||
|
else remainder=1;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
tf.V(0) = index[ tsa.v[k+0] ];
|
||||||
|
tf.V(1) = index[ tsa.v[k+1] ];
|
||||||
|
tf.V(2) = index[ tsa.v[k+2] ];
|
||||||
|
if((k+remainder)%2) swap (tf.V(0), tf.V(1) );
|
||||||
|
m.face.push_back( tf );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Skippaggio elementi non gestiti
|
||||||
|
int n = pf.ElemNumber(i);
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
for(int j=0;j<n;j++)
|
||||||
|
{
|
||||||
|
if( pf.Read(0)==-1)
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// // Parsing texture names
|
||||||
|
//textures.clear();
|
||||||
|
//normalmaps.clear();
|
||||||
|
|
||||||
|
//for(int co=0;co<int(pf.comments.size());++co)
|
||||||
|
//{
|
||||||
|
// const char * TFILE = "TextureFile";
|
||||||
|
// const char * NFILE = "TextureNormalFile";
|
||||||
|
// const char * c = pf.comments[co];
|
||||||
|
// char buf[256];
|
||||||
|
// int i,j,n;
|
||||||
|
|
||||||
|
// if( !strncmp(c,TFILE,strlen(TFILE)) )
|
||||||
|
// {
|
||||||
|
// strcpy(buf,c+strlen(TFILE)+1);
|
||||||
|
// n = strlen(buf);
|
||||||
|
// for(i=j=0;i<n;i++)
|
||||||
|
// if( buf[i]!=' ' && buf[i]!='\t' && buf[i]>32 && buf[i]<125 ) buf[j++] = buf[i];
|
||||||
|
//
|
||||||
|
// buf[j] = 0;
|
||||||
|
// char buf2[255];
|
||||||
|
// __interpret_texture_name( buf,filename,buf2 );
|
||||||
|
// textures.push_back( xstring(buf2) );
|
||||||
|
// }
|
||||||
|
// if( !strncmp(c,NFILE,strlen(NFILE)) )
|
||||||
|
// {
|
||||||
|
// strcpy(buf,c+strlen(NFILE)+1);
|
||||||
|
// n = strlen(buf);
|
||||||
|
// for(i=j=0;i<n;i++)
|
||||||
|
// if( buf[i]!=' ' && buf[i]!='\t' && buf[i]>32 && buf[i]<125 ) buf[j++] = buf[i];
|
||||||
|
//
|
||||||
|
// buf[j] = 0;
|
||||||
|
// char buf2[255];
|
||||||
|
// __interpret_texture_name( buf,filename,buf2 );
|
||||||
|
// normalmaps.push_back( xstring(buf2) );
|
||||||
|
// }
|
||||||
|
//}
|
||||||
|
|
||||||
|
// vn and fn should be correct but if someone wrongly saved some deleted elements they can be wrong.
|
||||||
|
m.vn = 0;
|
||||||
|
VertexIterator vi;
|
||||||
|
for(vi=m.vert.begin();vi!=m.vert.end();++vi)
|
||||||
|
if( ! (*vi).IsD() )
|
||||||
|
++m.vn;
|
||||||
|
|
||||||
|
m.fn = 0;
|
||||||
|
FaceIterator fi;
|
||||||
|
for(fi=m.face.begin();fi!=m.face.end();++fi)
|
||||||
|
if( ! (*fi).IsD() )
|
||||||
|
++m.fn;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// Caricamento camera da un ply
|
||||||
|
int LoadCamera(const char * filename)
|
||||||
|
{
|
||||||
|
PlyFile pf;
|
||||||
|
if( pf.Open(filename,PlyFile::MODE_READ)==-1 )
|
||||||
|
{
|
||||||
|
pi.status = pf.GetError();
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool found = true;
|
||||||
|
int i;
|
||||||
|
for(i=0;i<23;++i)
|
||||||
|
{
|
||||||
|
if( pf.AddToRead(CameraDesc(i))==-1 )
|
||||||
|
{
|
||||||
|
found = false;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!found)
|
||||||
|
return -1;
|
||||||
|
|
||||||
|
for(i=0;i<int(pf.elements.size());i++)
|
||||||
|
{
|
||||||
|
int n = pf.ElemNumber(i);
|
||||||
|
|
||||||
|
if( !strcmp( pf.ElemName(i),"camera" ) )
|
||||||
|
{
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
LoadPly_Camera ca;
|
||||||
|
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
if( pf.Read( (void *)&(ca) )==-1 )
|
||||||
|
{
|
||||||
|
pi.status = E_SHORTFILE;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
camera.valid = true;
|
||||||
|
camera.view_p[0] = ca.view_px;
|
||||||
|
camera.view_p[1] = ca.view_py;
|
||||||
|
camera.view_p[2] = ca.view_pz;
|
||||||
|
camera.x_axis[0] = ca.x_axisx;
|
||||||
|
camera.x_axis[1] = ca.x_axisy;
|
||||||
|
camera.x_axis[2] = ca.x_axisz;
|
||||||
|
camera.y_axis[0] = ca.y_axisx;
|
||||||
|
camera.y_axis[1] = ca.y_axisy;
|
||||||
|
camera.y_axis[2] = ca.y_axisz;
|
||||||
|
camera.z_axis[0] = ca.z_axisx;
|
||||||
|
camera.z_axis[1] = ca.z_axisy;
|
||||||
|
camera.z_axis[2] = ca.z_axisz;
|
||||||
|
camera.f = ca.focal;
|
||||||
|
camera.s[0] = ca.scalex;
|
||||||
|
camera.s[1] = ca.scaley;
|
||||||
|
camera.c[0] = ca.centerx;
|
||||||
|
camera.c[1] = ca.centery;
|
||||||
|
camera.viewport[0] = ca.viewportx;
|
||||||
|
camera.viewport[1] = ca.viewporty;
|
||||||
|
camera.k[0] = ca.k1;
|
||||||
|
camera.k[1] = ca.k2;
|
||||||
|
camera.k[2] = ca.k3;
|
||||||
|
camera.k[3] = ca.k4;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool LoadMask(const char * filename, int &mask)
|
||||||
|
{
|
||||||
|
mask=0;
|
||||||
|
PlyFile pf;
|
||||||
|
if( pf.Open(filename,PlyFile::MODE_READ)==-1 )
|
||||||
|
{
|
||||||
|
pi.status = pf.GetError();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pf.AddToRead(VertDesc(0))!=-1 &&
|
||||||
|
pf.AddToRead(VertDesc(1))!=-1 &&
|
||||||
|
pf.AddToRead(VertDesc(2))!=-1 ) mask |= PLYMask::PM_VERTCOORD;
|
||||||
|
|
||||||
|
if( pf.AddToRead(VertDesc(3))!=-1 ) mask |= PLYMask::PM_VERTFLAGS;
|
||||||
|
if( pf.AddToRead(VertDesc(4))!=-1 ) mask |= PLYMask::PM_VERTQUALITY;
|
||||||
|
if( pf.AddToRead(VertDesc(8))!=-1 ) mask |= PLYMask::PM_VERTQUALITY;
|
||||||
|
if( ( pf.AddToRead(VertDesc(5))!=-1 ) &&
|
||||||
|
( pf.AddToRead(VertDesc(6))!=-1 ) &&
|
||||||
|
( pf.AddToRead(VertDesc(7))!=-1 ) ) mask |= PLYMask::PM_VERTCOLOR;
|
||||||
|
|
||||||
|
if( pf.AddToRead(FaceDesc(0))!=-1 ) mask |= PLYMask::PM_FACEINDEX;
|
||||||
|
if( pf.AddToRead(FaceDesc(1))!=-1 ) mask |= PLYMask::PM_FACEFLAGS;
|
||||||
|
|
||||||
|
if( pf.AddToRead(FaceDesc(2))!=-1 ) mask |= PLYMask::PM_FACEQUALITY;
|
||||||
|
if( pf.AddToRead(FaceDesc(3))!=-1 ) mask |= PLYMask::PM_WEDGTEXCOORD;
|
||||||
|
if( pf.AddToRead(FaceDesc(5))!=-1 ) mask |= PLYMask::PM_WEDGTEXMULTI;
|
||||||
|
if( pf.AddToRead(FaceDesc(4))!=-1 ) mask |= PLYMask::PM_WEDGCOLOR;
|
||||||
|
if( ( pf.AddToRead(FaceDesc(6))!=-1 ) &&
|
||||||
|
( pf.AddToRead(FaceDesc(7))!=-1 ) &&
|
||||||
|
( pf.AddToRead(FaceDesc(8))!=-1 ) ) mask |= PLYMask::PM_FACECOLOR;
|
||||||
|
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}; // end class
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
} // end namespace tri
|
||||||
|
} // end namespace io
|
||||||
|
} // end namespace vcg
|
|
@ -0,0 +1,105 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004 \/)\/ *
|
||||||
|
* Visual Computing Lab /\/| *
|
||||||
|
* ISTI - Italian National Research Council | *
|
||||||
|
* \ *
|
||||||
|
* All rights reserved. *
|
||||||
|
* *
|
||||||
|
* 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||||
|
* for more details. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
History
|
||||||
|
|
||||||
|
$Log: not supported by cvs2svn $
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
/**
|
||||||
|
@name Load and Save in Ply format
|
||||||
|
*/
|
||||||
|
//@{
|
||||||
|
#include<wrap/callback.h>
|
||||||
|
#include<wrap/ply/plylib.h>
|
||||||
|
|
||||||
|
namespace vcg {
|
||||||
|
namespace tri {
|
||||||
|
namespace io {
|
||||||
|
|
||||||
|
|
||||||
|
class PLYMask
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
/*
|
||||||
|
Bitmask for specifying what data has to be loaded or saved or it is present in a given plyfile;
|
||||||
|
*/
|
||||||
|
|
||||||
|
enum {
|
||||||
|
PM_NONE = 0x0000,
|
||||||
|
|
||||||
|
PM_VERTCOORD = 0x0001,
|
||||||
|
PM_VERTFLAGS = 0x0002,
|
||||||
|
PM_VERTCOLOR = 0x0004,
|
||||||
|
PM_VERTQUALITY = 0x0008,
|
||||||
|
PM_VERTNORMAL = 0x0010,
|
||||||
|
PM_VERTTEXCOORD = 0x0020,
|
||||||
|
|
||||||
|
PM_FACEINDEX = 0x0040,
|
||||||
|
PM_FACEFLAGS = 0x0080,
|
||||||
|
PM_FACECOLOR = 0x0100,
|
||||||
|
PM_FACEQUALITY = 0x0200,
|
||||||
|
PM_FACENORMAL = 0x0400,
|
||||||
|
PM_WEDGCOLOR = 0x0800,
|
||||||
|
PM_WEDGTEXCOORD = 0x1000,
|
||||||
|
PM_WEDGTEXMULTI = 0x2000, // Se ha anche l'indice di texture esplicito
|
||||||
|
PM_WEDGNORMAL = 0x4000,
|
||||||
|
|
||||||
|
PM_CAMERA = 0x8000,
|
||||||
|
|
||||||
|
PM_FLAGS = PM_VERTFLAGS + PM_FACEFLAGS,
|
||||||
|
|
||||||
|
PM_ALL = 0xFFFF
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
static void SMFlags2String( int mask, char str[] )
|
||||||
|
{
|
||||||
|
str[0] = 0;
|
||||||
|
|
||||||
|
strcat(str,"V:");
|
||||||
|
if( mask & PM_VERTFLAGS ) strcat(str,"flag,");
|
||||||
|
if( mask & PM_VERTCOLOR ) strcat(str,"color,");
|
||||||
|
if( mask & PM_VERTQUALITY ) strcat(str,"quality,");
|
||||||
|
if( mask & PM_VERTTEXCOORD ) strcat(str,"tcoord,");
|
||||||
|
if( mask & PM_VERTNORMAL ) strcat(str,"normal,");
|
||||||
|
|
||||||
|
strcat(str," F:");
|
||||||
|
if( mask & PM_FACEFLAGS ) strcat(str,"mask,");
|
||||||
|
if( mask & PM_FACECOLOR ) strcat(str,"color,");
|
||||||
|
if( mask & PM_FACEQUALITY ) strcat(str,"quality,");
|
||||||
|
if( mask & PM_FACENORMAL ) strcat(str,"normal,");
|
||||||
|
|
||||||
|
strcat(str," W:");
|
||||||
|
if( mask & PM_WEDGCOLOR ) strcat(str,"color,");
|
||||||
|
if( mask & PM_WEDGTEXCOORD ) strcat(str,"tcoord,");
|
||||||
|
if( mask & PM_WEDGNORMAL ) strcat(str,"normal,");
|
||||||
|
|
||||||
|
if( mask & PM_CAMERA ) strcat(str," camera");
|
||||||
|
}
|
||||||
|
|
||||||
|
}; // end class
|
||||||
|
} // end namespace tri
|
||||||
|
} // end namespace io
|
||||||
|
} // end namespace vcg
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,312 @@
|
||||||
|
/****************************************************************************
|
||||||
|
* VCGLib o o *
|
||||||
|
* Visual and Computer Graphics Library o o *
|
||||||
|
* _ O _ *
|
||||||
|
* Copyright(C) 2004 \/)\/ *
|
||||||
|
* Visual Computing Lab /\/| *
|
||||||
|
* ISTI - Italian National Research Council | *
|
||||||
|
* \ *
|
||||||
|
* All rights reserved. *
|
||||||
|
* *
|
||||||
|
* 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 (http://www.gnu.org/licenses/gpl.txt) *
|
||||||
|
* for more details. *
|
||||||
|
* *
|
||||||
|
****************************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
Acknowlegments
|
||||||
|
Portions of this file were based on the original code of the Ply library
|
||||||
|
of Greg Turk and on the work of Claudio Rocchini
|
||||||
|
|
||||||
|
****************************************************************************/
|
||||||
|
/****************************************************************************
|
||||||
|
History
|
||||||
|
|
||||||
|
$Log: not supported by cvs2svn $
|
||||||
|
****************************************************************************/
|
||||||
|
|
||||||
|
#ifndef __VCG_PLYLIB
|
||||||
|
#define __VCG_PLYLIB
|
||||||
|
|
||||||
|
#include <memory.h>
|
||||||
|
#include <vector>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
namespace vcg {
|
||||||
|
namespace ply {
|
||||||
|
// Temporaneo
|
||||||
|
|
||||||
|
// Tipi di dato Supportati dal formato ply
|
||||||
|
enum PlyTypes {
|
||||||
|
T_NOTYPE,
|
||||||
|
T_CHAR,
|
||||||
|
T_SHORT,
|
||||||
|
T_INT,
|
||||||
|
T_UCHAR,
|
||||||
|
T_USHORT,
|
||||||
|
T_UINT,
|
||||||
|
T_FLOAT,
|
||||||
|
T_DOUBLE,
|
||||||
|
T_MAXTYPE
|
||||||
|
};
|
||||||
|
|
||||||
|
// Codici di errore riportati da GetError
|
||||||
|
enum PlyError {
|
||||||
|
E_NOERROR, // 0
|
||||||
|
// Errori di open
|
||||||
|
E_CANTOPEN, // 1
|
||||||
|
E_NOTHEADER, // 2
|
||||||
|
E_UNESPECTEDEOF, // 3
|
||||||
|
E_NOFORMAT, // 4
|
||||||
|
E_SYNTAX, // 5
|
||||||
|
E_PROPOUTOFELEMENT, // 6
|
||||||
|
E_BADTYPENAME, // 7
|
||||||
|
// Errori di addtoread
|
||||||
|
E_ELEMNOTFOUND, // 8
|
||||||
|
E_PROPNOTFOUND, // 9
|
||||||
|
E_BADTYPE, // 10
|
||||||
|
E_INCOMPATIBLETYPE, // 11
|
||||||
|
E_BADCAST, // 12
|
||||||
|
E_MAXPLYERRORS
|
||||||
|
};
|
||||||
|
|
||||||
|
// Tipi di formato di file
|
||||||
|
enum PlyFormat {
|
||||||
|
F_UNSPECIFIED,
|
||||||
|
F_ASCII,
|
||||||
|
F_BINLITTLE,
|
||||||
|
F_BINBIG
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef USE_ZLIB
|
||||||
|
typedef void * GZFILE;
|
||||||
|
#else
|
||||||
|
typedef FILE * GZFILE;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
// Messaggio di errore
|
||||||
|
extern const char * ply_error_msg[];
|
||||||
|
|
||||||
|
// TIPO FILE
|
||||||
|
|
||||||
|
|
||||||
|
// Descrittore esterno di propieta'
|
||||||
|
class PropDescriptor
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
char * elemname; // Nome dell'elemento
|
||||||
|
char * propname; // Nome della propieta'
|
||||||
|
int stotype1; // Tipo dell'elemento su file (se lista tipo degli elementi della lista)
|
||||||
|
int memtype1; // Tipo dell'elemento in memoria (se lista tipo degli elementi della lista)
|
||||||
|
int offset1; // Offset del valore in memoria
|
||||||
|
int islist; // 1 se lista, 0 altrimenti
|
||||||
|
int alloclist; // 1 se alloca lista, 0 se preallocata
|
||||||
|
int stotype2; // Tipo del numero di elementi della lista su file
|
||||||
|
int memtype2; // Tipo del numero di elementi della lista in memoria
|
||||||
|
int offset2; // Offset valore memoria
|
||||||
|
|
||||||
|
int format; // duplicazione del formato
|
||||||
|
|
||||||
|
size_t stotypesize() const; // per sapere quanto e'grande un dato descrittore sul file
|
||||||
|
size_t memtypesize() const; // per sapere quanto e'grande un dato descrittore in memoria
|
||||||
|
const char *memtypename() const;
|
||||||
|
const char *stotypename() const;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Callback di lettura
|
||||||
|
typedef bool (* readelemcb) ( GZFILE fp, void * mem, PropDescriptor * p );
|
||||||
|
|
||||||
|
class PlyProperty
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
inline PlyProperty()
|
||||||
|
{
|
||||||
|
tipo = 0;
|
||||||
|
islista = 0;
|
||||||
|
tipoindex = 0;
|
||||||
|
bestored = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PlyProperty( const char * na, int ti, int isl, int t2 )
|
||||||
|
{
|
||||||
|
assert(na);
|
||||||
|
assert(ti>0);
|
||||||
|
assert(ti<T_MAXTYPE);
|
||||||
|
assert( t2>0 || (t2==0 && isl==0) );
|
||||||
|
assert(t2<T_MAXTYPE);
|
||||||
|
|
||||||
|
name = std::string(na);
|
||||||
|
tipo = ti;
|
||||||
|
islista = isl;
|
||||||
|
tipoindex = t2;
|
||||||
|
bestored = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string name; // Nome della propieta'
|
||||||
|
int tipo; // Tipo di dato
|
||||||
|
int islista; // Vero se e' una lista
|
||||||
|
int tipoindex; // Tipo del contatore della lista
|
||||||
|
|
||||||
|
int bestored; // 1 se va storata
|
||||||
|
PropDescriptor desc; // Descrittore di memorizzazione
|
||||||
|
|
||||||
|
readelemcb cb; // Callback di lettura
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PlyElement
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
|
||||||
|
inline PlyElement()
|
||||||
|
{
|
||||||
|
number = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
inline PlyElement( const char * na, int nu )
|
||||||
|
{
|
||||||
|
assert(na);
|
||||||
|
assert(nu>=0);
|
||||||
|
|
||||||
|
name = std::string(na);
|
||||||
|
number = nu;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
inline void SetName( const char * na )
|
||||||
|
{
|
||||||
|
name = std::string(na);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline void SetNumbert( int nu )
|
||||||
|
{
|
||||||
|
assert(nu>0);
|
||||||
|
number = nu;
|
||||||
|
}
|
||||||
|
|
||||||
|
void AddProp( const char * na, int ti, int isl, int t2 );
|
||||||
|
|
||||||
|
int AddToRead(
|
||||||
|
const char * propname,
|
||||||
|
int stotype1,
|
||||||
|
int memtype1,
|
||||||
|
int offset1,
|
||||||
|
int islist,
|
||||||
|
int alloclist,
|
||||||
|
int stotype2,
|
||||||
|
int memtype2,
|
||||||
|
int offset2
|
||||||
|
); // Vedi struttura PropDescriptor
|
||||||
|
|
||||||
|
PlyProperty * FindProp( const char * name );
|
||||||
|
|
||||||
|
std::string name; // Nome dell'elemento
|
||||||
|
int number; // Numero di elementi di questo tipo
|
||||||
|
|
||||||
|
std::vector<PlyProperty> props; // Vettore dinamico delle property
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
class PlyFile
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
void compile( PlyElement * e );
|
||||||
|
void compile( PlyProperty * p );
|
||||||
|
|
||||||
|
public:
|
||||||
|
// Modi di apertura
|
||||||
|
enum {
|
||||||
|
MODE_READ,
|
||||||
|
MODE_WRITE
|
||||||
|
};
|
||||||
|
|
||||||
|
PlyFile();
|
||||||
|
~PlyFile();
|
||||||
|
|
||||||
|
// Apre un file ply
|
||||||
|
int Open( const char * filename, int mode );
|
||||||
|
// Chiude un file e disalloca la memoria
|
||||||
|
void Destroy();
|
||||||
|
// Ritorna il codice dell'ultimo errore
|
||||||
|
inline int GetError() const { return error; }
|
||||||
|
// Definizione di lettura (Vedi struttura PropDescriptor)
|
||||||
|
int AddToRead(
|
||||||
|
const char * elemname,
|
||||||
|
const char * propname,
|
||||||
|
int stotype1,
|
||||||
|
int memtype1,
|
||||||
|
int offset1,
|
||||||
|
int islist,
|
||||||
|
int alloclist,
|
||||||
|
int stotype2,
|
||||||
|
int memtype2,
|
||||||
|
int offset2
|
||||||
|
);
|
||||||
|
// Come sopra ma con descrittore
|
||||||
|
inline int AddToRead( const PropDescriptor & p )
|
||||||
|
{
|
||||||
|
return AddToRead(p.elemname,p.propname,p.stotype1,
|
||||||
|
p.memtype1,p.offset1,p.islist,p.alloclist,p.stotype2,
|
||||||
|
p.memtype2,p.offset2
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Ritorna il numero di oggetti di un tipo di elemento
|
||||||
|
const char * ElemName( int i );
|
||||||
|
|
||||||
|
int ElemNumber( int i ) const;
|
||||||
|
// Setta il tipo di elemento corrente per effetture
|
||||||
|
// la lettura
|
||||||
|
inline void SetCurElement( int i )
|
||||||
|
{
|
||||||
|
if(i<0 || i>=int(elements.size())) cure = 0;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
cure = &(elements[i]);
|
||||||
|
compile(cure);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Lettura du un elemento
|
||||||
|
int Read( void * mem );
|
||||||
|
|
||||||
|
std::vector<PlyElement> elements; // Vettore degli elementi
|
||||||
|
std::vector<std::string> comments; // Vettore dei commenti
|
||||||
|
static const char * typenames[9];
|
||||||
|
static const char * newtypenames[9];
|
||||||
|
|
||||||
|
inline const char * GetHeader() const { return header; }
|
||||||
|
protected:
|
||||||
|
|
||||||
|
GZFILE gzfp;
|
||||||
|
|
||||||
|
float version; // Versione del file
|
||||||
|
int error; // Errore corrente (vedi enum)
|
||||||
|
int format; // Formato del file (vedi enum )
|
||||||
|
|
||||||
|
char header[4096]; // Testo dell'header
|
||||||
|
|
||||||
|
PlyElement * cure; // Elemento da leggere
|
||||||
|
|
||||||
|
// Callback di lettura: vale ReadBin o ReadAcii
|
||||||
|
int (* ReadCB)( GZFILE fp, const PlyProperty * r, void * mem, int fmt );
|
||||||
|
|
||||||
|
int OpenRead( const char * filename );
|
||||||
|
int OpenWrite( const char * filename );
|
||||||
|
|
||||||
|
PlyElement * AddElement( const char * name, int number );
|
||||||
|
int FindType( const char * name ) const;
|
||||||
|
PlyElement * FindElement( const char * name );
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
|
@ -0,0 +1,340 @@
|
||||||
|
//****************** Gestione cache *****************
|
||||||
|
|
||||||
|
const int MAXBPATH = 256;
|
||||||
|
|
||||||
|
static bool GetDirFromPath( const char * path, char * dir, char * name )
|
||||||
|
{
|
||||||
|
strcpy(dir,path);
|
||||||
|
char * p;
|
||||||
|
|
||||||
|
p = strrchr(dir,'\\');
|
||||||
|
if(p==0) p=strrchr(dir,'/');
|
||||||
|
if(p==0)
|
||||||
|
{
|
||||||
|
dir[0] = 0;
|
||||||
|
strcpy(name,path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
strcpy(name,p+1);
|
||||||
|
*p = 0;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool CheckCacheDirectory( const char * dir )
|
||||||
|
{
|
||||||
|
if( pb_access(dir,0)!=0 )
|
||||||
|
{
|
||||||
|
if( pb_mkdir(dir)==-1 )
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool CheckCacheTime( const char * fname, const char * cname )
|
||||||
|
{
|
||||||
|
|
||||||
|
if( pb_access(fname,4)==-1 ) return false;
|
||||||
|
if( pb_access(cname,4)==-1 ) return false;
|
||||||
|
|
||||||
|
int h,r;
|
||||||
|
struct pb_stat st;
|
||||||
|
time_t ft,bt;
|
||||||
|
|
||||||
|
h = pb_open(fname,_O_BINARY|_O_RDONLY);
|
||||||
|
if(h==0) return false;
|
||||||
|
r = _fstat(h,&st);
|
||||||
|
pb_close(h);
|
||||||
|
if(r==-1) return false;
|
||||||
|
ft = st.st_mtime;
|
||||||
|
|
||||||
|
h = pb_open(cname,_O_BINARY|_O_RDONLY);
|
||||||
|
if(h==0) return false;
|
||||||
|
r = _fstat(h,&st);
|
||||||
|
//_read(h,&box,sizeof(box));
|
||||||
|
pb_close(h);
|
||||||
|
if(r==-1) return false;
|
||||||
|
bt = st.st_mtime;
|
||||||
|
|
||||||
|
if( difftime(bt,ft)>=0 ) return true;
|
||||||
|
else return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// restituisce true se il file con la cache del bbox della mesh e' piu' recente del file ply
|
||||||
|
// se fname2 != 0, allora deve essere piu recente anche di fname2.
|
||||||
|
static bool CheckBBoxCache( const char * fname, Box3d & box, char *fname2=0 )
|
||||||
|
{
|
||||||
|
char d[MAXBPATH];
|
||||||
|
char n[MAXBPATH];
|
||||||
|
char h[8];
|
||||||
|
|
||||||
|
// Estrazione dati
|
||||||
|
if( ! GetDirFromPath(fname,d,n) ) return false;
|
||||||
|
|
||||||
|
// Controllo esistenza directory delle cache
|
||||||
|
if(d[0]!=0)
|
||||||
|
strcat(d,"\\");
|
||||||
|
strcat(d,cachedir);
|
||||||
|
if( !CheckCacheDirectory(d) ) return false;
|
||||||
|
|
||||||
|
// Controllo esistenza e data file cache
|
||||||
|
strcat(d,"\\");
|
||||||
|
strcat(d,n);
|
||||||
|
strcat(d,bboxcacheext);
|
||||||
|
if( CheckCacheTime(fname,d) &&
|
||||||
|
(fname2==0 || CheckCacheTime(fname2,d)) )
|
||||||
|
{
|
||||||
|
// Lettura bbox e controllo
|
||||||
|
FILE * fp = fopen(d,"rb");
|
||||||
|
if(fp==0) return false;
|
||||||
|
if( fread(h,1,8,fp)!=8 )
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( fread(&box,sizeof(Box3d),1,fp)!=1 )
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
if( strncmp(h,bboxheader,8) )
|
||||||
|
return false;
|
||||||
|
else
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
bool GetCacheName( const char * fname, const char * ext_name, char * cname )
|
||||||
|
{
|
||||||
|
static char n[MAXBPATH];
|
||||||
|
|
||||||
|
// Estrazione dati
|
||||||
|
if( ! GetDirFromPath(fname,cname,n) ) return false;
|
||||||
|
|
||||||
|
// Controllo esistenza directory delle cache
|
||||||
|
if(cname[0]!=0)
|
||||||
|
strcat(cname,"\\");
|
||||||
|
strcat(cname,cachedir);
|
||||||
|
if( !CheckCacheDirectory(cname) ) return false;
|
||||||
|
|
||||||
|
strcat(cname,"\\");
|
||||||
|
strcat(cname,n);
|
||||||
|
strcat(cname,ext_name);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static bool SaveBBoxCache( const char * fname, const Box3d & box )
|
||||||
|
{
|
||||||
|
char d[MAXBPATH];
|
||||||
|
|
||||||
|
if( !GetCacheName(fname,bboxcacheext,d) )
|
||||||
|
return false;
|
||||||
|
|
||||||
|
// Lettura bbox e controllo
|
||||||
|
FILE * fp = fopen(d,"wb");
|
||||||
|
if(fp==0) return false;
|
||||||
|
if( fwrite(bboxheader,1,8,fp)!=8 )
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
if( fwrite(&box,sizeof(Box3d),1,fp)!=1 )
|
||||||
|
{
|
||||||
|
fclose(fp);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PlyPoint3d
|
||||||
|
{
|
||||||
|
double x;
|
||||||
|
double y;
|
||||||
|
double z;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// Calcola il bbox di un file ply
|
||||||
|
|
||||||
|
bool ScanBBox( const char * fname, Box3d & box, bool use_cache )
|
||||||
|
{
|
||||||
|
|
||||||
|
if(use_cache)
|
||||||
|
{
|
||||||
|
if( CheckBBoxCache(fname,box) )
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const PropDescriptor pv[3]=
|
||||||
|
{
|
||||||
|
{"vertex","x",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,x),0,0,0,0,0},
|
||||||
|
{"vertex","y",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,y),0,0,0,0,0},
|
||||||
|
{"vertex","z",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,z),0,0,0,0,0},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PlyFile pf;
|
||||||
|
|
||||||
|
if( pf.Open(fname,PlyFile::MODE_READ)==-1 )
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Warning: File %s not found\n",fname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pf.AddToRead(pv[0])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
if( pf.AddToRead(pv[1])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
if( pf.AddToRead(pv[2])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
|
||||||
|
box.SetNull();
|
||||||
|
char dummyspace[1024]; // sperando basti...
|
||||||
|
|
||||||
|
for(int i=0;i<int(pf.elements.size());++i)
|
||||||
|
{
|
||||||
|
int n = pf.ElemNumber(i);
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
if( !strcmp( pf.ElemName(i),"vertex" ) )
|
||||||
|
{
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
PlyPoint3d t;
|
||||||
|
|
||||||
|
pf.Read( (void *)(&t) );
|
||||||
|
box.Add( Point3d(t.x,t.y,t.z) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
//pf.Read( 0 ); // prima era cosi' e faceva un'assert e scrivema plausibilimente a caso in mem
|
||||||
|
pf.Read( dummyspace );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(use_cache)
|
||||||
|
{
|
||||||
|
SaveBBoxCache(fname,box);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Come la precedente ma applica la matrice m ai punti prima di calcolare il bbox.
|
||||||
|
// Visto che la matrice di solito e' tenuta in un qualche file, se si vuole usare la cache
|
||||||
|
// si puo' passare anche un'altro filename da controllare
|
||||||
|
bool ScanBBox( const char * fname, Box3d & box, const Matrix44d & m, bool use_cache, char *matrixfname)
|
||||||
|
{
|
||||||
|
|
||||||
|
if(use_cache)
|
||||||
|
{
|
||||||
|
if ( CheckBBoxCache(fname,box,matrixfname) ) return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static const PropDescriptor pv[3]=
|
||||||
|
{
|
||||||
|
{"vertex","x",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,x),0,0,0,0,0},
|
||||||
|
{"vertex","y",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,y),0,0,0,0,0},
|
||||||
|
{"vertex","z",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,z),0,0,0,0,0},
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
PlyFile pf;
|
||||||
|
|
||||||
|
if( pf.Open(fname,PlyFile::MODE_READ)==-1 )
|
||||||
|
{
|
||||||
|
fprintf(stderr,"Warning: File %s not found\n",fname);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if( pf.AddToRead(pv[0])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
if( pf.AddToRead(pv[1])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
if( pf.AddToRead(pv[2])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
|
||||||
|
|
||||||
|
box.SetNull();
|
||||||
|
char dummyspace[1024]; // sperando basti...
|
||||||
|
|
||||||
|
for(int i=0;i<int(pf.elements.size());++i)
|
||||||
|
{
|
||||||
|
int n = pf.ElemNumber(i);
|
||||||
|
pf.SetCurElement(i);
|
||||||
|
|
||||||
|
if( !strcmp( pf.ElemName(i),"vertex" ) )
|
||||||
|
{
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
{
|
||||||
|
PlyPoint3d t;
|
||||||
|
|
||||||
|
pf.Read( (void *)(&t) );
|
||||||
|
box.Add( m.Apply( Point3d(t.x,t.y,t.z) ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(int j=0;j<n;++j)
|
||||||
|
//pf.Read( 0 ); // prima era cosi' e faceva un'assert e scrivema plausibilimente a caso in mem
|
||||||
|
pf.Read( dummyspace );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(use_cache)
|
||||||
|
{
|
||||||
|
SaveBBoxCache(fname,box);
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void __interpret_texture_name(const char*a, const char*fn, char*output){
|
||||||
|
int ia=0,io=0;
|
||||||
|
output[0]=0;
|
||||||
|
while (a[ia]!=0){
|
||||||
|
if (a[ia]=='<') {
|
||||||
|
if (strlen(a)>ia+5) {
|
||||||
|
if ( ( (a[ia+1]=='t') || (a[ia+1]=='T') ) &&
|
||||||
|
( (a[ia+2]=='h') || (a[ia+2]=='H') ) &&
|
||||||
|
( (a[ia+3]=='i') || (a[ia+3]=='I') ) &&
|
||||||
|
( (a[ia+4]=='s') || (a[ia+4]=='S') ) &&
|
||||||
|
( a[ia+5]=='>' ) )
|
||||||
|
{
|
||||||
|
// substitute "<this>" with filename:
|
||||||
|
// 1) remove path from filename
|
||||||
|
int lastbar=0;
|
||||||
|
int ifn=0;
|
||||||
|
while (fn[ifn]!=0) { if ((fn[ifn]=='/') || (fn[ifn]=='\\')) lastbar=ifn+1; ifn++;}
|
||||||
|
ifn=lastbar;
|
||||||
|
char fn2[255];
|
||||||
|
while (fn[ifn]!=0) { fn2[ifn-lastbar]=fn[ifn]; ifn++;}
|
||||||
|
fn2[ifn-lastbar]=0;
|
||||||
|
|
||||||
|
// 2) remove ".ply" extention from filename
|
||||||
|
int l=ifn-lastbar;
|
||||||
|
if ((fn2[l-4]=='.')
|
||||||
|
&& ((fn2[l-3]=='P') || (fn2[l-3]=='p'))
|
||||||
|
&& ((fn2[l-2]=='L') || (fn2[l-2]=='l'))
|
||||||
|
&& ((fn2[l-1]=='Y') || (fn2[l-1]=='y')) )
|
||||||
|
fn2[l-4]=0;
|
||||||
|
|
||||||
|
// 3) append
|
||||||
|
output[io]=0;
|
||||||
|
sprintf(output,"%s%s",output,fn2);
|
||||||
|
io=strlen(output);
|
||||||
|
ia+=6; //skip the "<this>"
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
output[io++]=a[ia++];
|
||||||
|
};
|
||||||
|
output[io]=0;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue