00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054 #ifndef __VCG_PLYLIB_STUFF
00055 #define __VCG_PLYLIB_STUFF
00056
00057 #include <sys/types.h>
00058 #include <sys/stat.h>
00059 #include <fcntl.h>
00060 #ifdef WIN32
00061 #include <io.h>
00062 #endif
00063
00064 #include <vcg/space/box3.h>
00065 #include <wrap/ply/plylib.h>
00066 using namespace vcg;
00067
00068 #ifdef WIN32
00069 #include <direct.h>
00070 #define pb_mkdir(n) _mkdir(n)
00071 #define pb_access _access
00072 #define pb_stat _stat
00073 #define pb_fstat _fstat
00074 #define pb_open _open
00075 #define pb_close _close
00076 #define DIR_SEP "\\"
00077 #else
00078 #define pb_mkdir(n) mkdir(n,0755)
00079 #define pb_access access
00080 #define pb_stat stat
00081 #define pb_fstat fstat
00082 #define pb_open open
00083 #define pb_close close
00084 #define _O_BINARY 0 // Does not exist on Unix
00085 #define _O_RDONLY O_RDONLY
00086 #define DIR_SEP "/"
00087 #endif
00088
00089
00090 namespace vcg {
00091 namespace ply {
00092
00093 const int MAXBPATH = 256;
00094
00095
00096 const char * cachedir = "vcg_cache";
00097 const char * bboxcacheext = ".bbox_cache";
00098 const char * bboxheader = "BBOXCACH";
00099
00100 bool GetDirFromPath( const char * path, char * dir, char * name )
00101 {
00102 strcpy(dir,path);
00103 char * p;
00104
00105 p = strrchr(dir,'\\');
00106 if(p==0) p=strrchr(dir,'/');
00107 if(p==0)
00108 {
00109 dir[0] = 0;
00110 strcpy(name,path);
00111 }
00112 else
00113 {
00114 strcpy(name,p+1);
00115 *p = 0;
00116 }
00117 return true;
00118 }
00119
00120
00121 static bool CheckCacheDirectory( const char * dir )
00122 {
00123 if( pb_access(dir,0)!=0 )
00124 {
00125 if( pb_mkdir(dir)==-1 )
00126 return false;
00127 }
00128 return true;
00129 }
00130
00131
00132 bool CheckCacheTime( const char * fname, const char * cname )
00133 {
00134
00135 if( pb_access(fname,4)==-1 ) return false;
00136 if( pb_access(cname,4)==-1 ) return false;
00137
00138 int h,r;
00139 struct pb_stat st;
00140 time_t ft,bt;
00141
00142 h = pb_open(fname,_O_BINARY|_O_RDONLY);
00143 if(h==0) return false;
00144 r = pb_fstat(h,&st);
00145 pb_close(h);
00146 if(r==-1) return false;
00147 ft = st.st_mtime;
00148
00149 h = pb_open(cname,_O_BINARY|_O_RDONLY);
00150 if(h==0) return false;
00151 r = pb_fstat(h,&st);
00152
00153 pb_close(h);
00154 if(r==-1) return false;
00155 bt = st.st_mtime;
00156
00157 if( difftime(bt,ft)>=0 ) return true;
00158 else return false;
00159 }
00160
00161
00162
00163 template<class ScalarType>
00164 static bool CheckBBoxCache( const char * fname, Box3<ScalarType> & box, const char *fname2=0 )
00165 {
00166 char d[MAXBPATH];
00167 char n[MAXBPATH];
00168 char h[8];
00169
00170
00171 if( ! GetDirFromPath(fname,d,n) ) return false;
00172
00173
00174 if(d[0]!=0)
00175 strcat(d,DIR_SEP);
00176 strcat(d,cachedir);
00177 if( !CheckCacheDirectory(d) ) return false;
00178
00179
00180 strcat(d,DIR_SEP);
00181 strcat(d,n);
00182 strcat(d,bboxcacheext);
00183 if( CheckCacheTime(fname,d) &&
00184 (fname2==0 || CheckCacheTime(fname2,d)) )
00185 {
00186
00187 Box3d readBB;
00188 FILE * fp = fopen(d,"rb");
00189 if(fp==0) return false;
00190 if( fread(h,1,8,fp)!=8 )
00191 {
00192 fclose(fp);
00193 return false;
00194 }
00195 if( fread(&readBB,sizeof(Box3d),1,fp)!=1 )
00196 {
00197 fclose(fp);
00198 return false;
00199 }
00200 fclose(fp);
00201 box.Import(readBB);
00202 if( strncmp(h,bboxheader,8) )
00203 return false;
00204 else
00205 return true;
00206 }
00207 else
00208 return false;
00209 }
00210
00211
00212 bool GetCacheName( const char * fname, const char * ext_name, char * cname )
00213 {
00214 static char n[MAXBPATH];
00215
00216
00217 if( ! GetDirFromPath(fname,cname,n) ) return false;
00218
00219
00220 if(cname[0]!=0)
00221 strcat(cname,DIR_SEP);
00222 strcat(cname,cachedir);
00223 if( !CheckCacheDirectory(cname) ) return false;
00224
00225 strcat(cname,DIR_SEP);
00226 strcat(cname,n);
00227 strcat(cname,ext_name);
00228 return true;
00229 }
00230
00231
00232 template <class ScalarType>
00233 static bool SaveBBoxCache( const char * fname, const Box3<ScalarType> & boxOut )
00234 {
00235 char d[MAXBPATH];
00236
00237 Box3d box;
00238 box.Import(boxOut);
00239 if( !GetCacheName(fname,bboxcacheext,d) )
00240 return false;
00241
00242
00243 FILE * fp = fopen(d,"wb");
00244 if(fp==0) return false;
00245 if( fwrite(bboxheader,1,8,fp)!=8 )
00246 {
00247 fclose(fp);
00248 return false;
00249 }
00250 if( fwrite(&box,sizeof(Box3d),1,fp)!=1 )
00251 {
00252 fclose(fp);
00253 return false;
00254 }
00255 fclose(fp);
00256 return true;
00257 }
00258
00259 struct PlyPoint3d
00260 {
00261 double x;
00262 double y;
00263 double z;
00264 };
00265
00266
00267
00268 template <class ScalarType>
00269 bool ScanBBox( const char * fname, Box3<ScalarType> & box, bool use_cache=true )
00270 {
00271
00272 if(use_cache)
00273 {
00274 if( CheckBBoxCache(fname,box) )
00275 return true;
00276 }
00277
00278 static const PropDescriptor pv[3]=
00279 {
00280 {"vertex","x",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,x),0,0,0,0,0 ,0},
00281 {"vertex","y",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,y),0,0,0,0,0 ,0},
00282 {"vertex","z",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,z),0,0,0,0,0, 0},
00283 };
00284
00285
00286 PlyFile pf;
00287
00288 if( pf.Open(fname,PlyFile::MODE_READ)==-1 )
00289 {
00290 fprintf(stderr,"Warning: File %s not found\n",fname);
00291 return false;
00292 }
00293
00294 if( pf.AddToRead(pv[0])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00295 if( pf.AddToRead(pv[1])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00296 if( pf.AddToRead(pv[2])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00297
00298 box.SetNull();
00299 char dummyspace[1024];
00300
00301 for(int i=0;i<int(pf.elements.size());++i)
00302 {
00303 int n = pf.ElemNumber(i);
00304 pf.SetCurElement(i);
00305
00306 if( !strcmp( pf.ElemName(i),"vertex" ) )
00307 {
00308 for(int j=0;j<n;++j)
00309 {
00310 PlyPoint3d t;
00311
00312 pf.Read( (void *)(&t) );
00313 box.Add( Point3<ScalarType>(t.x,t.y,t.z) );
00314 }
00315 }
00316 else
00317 {
00318 for(int j=0;j<n;++j)
00319
00320 pf.Read( dummyspace );
00321 }
00322 }
00323
00324 if(use_cache)
00325 {
00326 SaveBBoxCache(fname,box);
00327 }
00328
00329 return true;
00330 }
00331
00332
00333
00334
00335 template <class ScalarType>
00336 bool ScanBBox( const char * fname, Box3<ScalarType> & box, const Matrix44<ScalarType> & m, bool use_cache, const char *matrixfname)
00337 {
00338
00339 if(use_cache)
00340 {
00341 if ( CheckBBoxCache(fname,box,matrixfname) ) return true;
00342 }
00343
00344 static const PropDescriptor pv[3]=
00345 {
00346 {"vertex","x",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,x),0,0,0,0,0, 0},
00347 {"vertex","y",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,y),0,0,0,0,0, 0},
00348 {"vertex","z",T_FLOAT,T_DOUBLE,offsetof(PlyPoint3d,z),0,0,0,0,0, 0},
00349 };
00350
00351
00352 PlyFile pf;
00353
00354 if( pf.Open(fname,PlyFile::MODE_READ)==-1 )
00355 {
00356 fprintf(stderr,"Warning: File %s not found\n",fname);
00357 return false;
00358 }
00359
00360 if( pf.AddToRead(pv[0])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00361 if( pf.AddToRead(pv[1])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00362 if( pf.AddToRead(pv[2])==-1 ) { fprintf(stderr,"Warning: Read error\n"); return false; }
00363
00364 box.SetNull();
00365 char dummyspace[1024];
00366
00367 for(int i=0;i<int(pf.elements.size());++i)
00368 {
00369 int n = pf.ElemNumber(i);
00370 pf.SetCurElement(i);
00371
00372 if( !strcmp( pf.ElemName(i),"vertex" ) )
00373 {
00374 for(int j=0;j<n;++j)
00375 {
00376 PlyPoint3d t;
00377
00378 pf.Read( (void *)(&t) );
00379 box.Add( m*Point3<ScalarType>(t.x,t.y,t.z) );
00380 }
00381 }
00382 else
00383 {
00384 for(int j=0;j<n;++j)
00385
00386 pf.Read( dummyspace );
00387 }
00388 }
00389
00390 if(use_cache)
00391 {
00392 SaveBBoxCache(fname,box);
00393 }
00394
00395 return true;
00396 }
00397
00398 }
00399 }
00400 #endif
00401