vcglib/wrap/ply/plystuff.h

380 lines
9.0 KiB
C++

/****************************************************************************
* 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 $
Revision 1.3 2005/03/18 00:14:40 cignoni
removed small gcc compiling issues
Revision 1.2 2005/03/15 11:46:52 cignoni
Cleaning of the automatic bbox caching support for ply files. First working version.
*/
//****************** Gestione cache *****************
#ifndef __VCG_PLYLIB_STUFF
#define __VCG_PLYLIB_STUFF
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <io.h>
#include <vcg/space/box3.h>
#include <wrap/ply/plylib.h>
using namespace vcg;
#ifdef WIN32
#include <direct.h>
#define pb_mkdir(n) _mkdir(n)
#define pb_access _access
#define pb_stat _stat
#define pb_fstat _fstat
#define pb_open _open
#define pb_close _close
#else
#define pb_mkdir(n) mkdir(n,0)
#define pb_access access
#define pb_stat stat
#define pb_fstat fstat
#define pb_open open
#define pb_close close
#endif
namespace vcg {
namespace ply {
const int MAXBPATH = 256;
// Stringhe per la cache
const char * cachedir = "vcg_cache";
const char * bboxcacheext = ".bbox_cache";
const char * bboxheader = "BBOXCACH";
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 = pb_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 = pb_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, const 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=true )
{
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, const 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*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;
}
} // end namespace ply
} // end namespace vcg
#endif