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 #ifndef __VCGLIB_IMPORT_PTX
00038 #define __VCGLIB_IMPORT_PTX
00039
00040 #include <stdio.h>
00041 #include <wrap/callback.h>
00042 #include <vcg/complex/trimesh/allocate.h>
00043 #include <vcg/complex/trimesh/clean.h>
00044 #include <vcg/complex/trimesh/update/normal.h>
00045 #include <vcg/complex/trimesh/update/bounding.h>
00046
00047 namespace vcg {
00048 namespace tri {
00049 namespace io {
00053 template <class OpenMeshType>
00054 class ImporterPTX
00055 {
00056 public:
00057 typedef typename OpenMeshType::VertexPointer VertexPointer;
00058 typedef typename OpenMeshType::ScalarType ScalarType;
00059 typedef typename OpenMeshType::VertexType VertexType;
00060 typedef typename OpenMeshType::FaceType FaceType;
00061 typedef typename OpenMeshType::VertexIterator VertexIterator;
00062 typedef typename OpenMeshType::FaceIterator FaceIterator;
00063
00064 class Info
00065 {
00066 public:
00067
00068 Info()
00069 {
00070 mask = 0;
00071 meshnum = 0;
00072 anglecull = true;
00073 angle = 89;
00074 savecolor = true;
00075 pointcull = true;
00076 pointsonly = false;
00077 switchside = false;
00078 flipfaces = false;
00079 }
00080
00082 int mask;
00083
00085 int meshnum;
00086
00088 bool anglecull;
00090 float angle;
00091
00093 bool pointcull;
00094
00096 bool pointsonly;
00097
00099 bool savecolor;
00100
00102 bool switchside;
00104 bool flipfaces;
00105
00106 };
00107
00108
00110 static const char *ErrorMsg(int error)
00111 {
00112 static const char * ptx_error_msg[] =
00113 {
00114 "No errors",
00115 "Can't open file",
00116 "Header not found",
00117 "Eof in header",
00118 "Format not found",
00119 "Syntax error on header",
00120 };
00121 if(error>6 || error<0) return "Unknown error";
00122 else return ptx_error_msg[error];
00123 };
00124
00127 static bool skipmesh(FILE* fp, CallBackPos *cb=NULL)
00128 {
00129 int colnum;
00130 int rownum;
00131 int skiplines;
00132 char linebuf;
00133
00134 if(feof(fp)) return false;
00135
00136
00137 fscanf(fp,"%i\n",&colnum);
00138 fscanf(fp,"%i\n",&rownum);
00139
00140 if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00141 if(feof(fp)) return false;
00142
00143
00144 skiplines = (colnum * rownum) + 8;
00145 for(int ii=0; ii<skiplines; ii++)
00146 {
00147 fread(&linebuf,1,1,fp);
00148 while(linebuf != '\n') fread(&linebuf,1,1,fp);
00149 }
00150
00151 if(cb) cb( 100, "Skipped preamble");
00152 return true;
00153 }
00154
00156 static int Open( OpenMeshType &m, const char * filename, Info importparams, CallBackPos *cb=NULL)
00157 {
00158 FILE *fp;
00159 fp = fopen(filename, "rb");
00160 if(fp == NULL) return false;
00161 m.Clear();
00162 m.vn=0;
00163 m.fn=0;
00164
00165
00166 if (importparams.meshnum>0)
00167 for (int i=0; i!=importparams.meshnum; ++i)
00168 if(!skipmesh(fp, cb))
00169 return 1;
00170
00171 if (!readPTX( m, fp, importparams, cb))
00172 {
00173 m.Clear();
00174 return 1;
00175 }
00176
00177 return 0;
00178 }
00179
00181 static bool readPTX( OpenMeshType &m, FILE *fp, Info importparams, CallBackPos *cb=NULL)
00182 {
00183 int numtokens;
00184 int colnum;
00185 int rownum;
00186 float xx,yy,zz;
00187 float rr,gg,bb;
00188 float rf;
00189 Matrix44f currtrasf;
00190
00191 bool hascolor;
00192 bool savecolor = importparams.savecolor && VertexType::HasColor();
00193 bool onlypoints = importparams.pointsonly;
00194 bool switchside = importparams.switchside;
00195 bool flipfaces = importparams.flipfaces;
00196
00197 int total = 50;
00198 if (onlypoints) total = 100;
00199 char linebuf[256];
00200
00201 fscanf(fp,"%i\n",&colnum);
00202 fscanf(fp,"%i\n",&rownum);
00203
00204 if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00205
00206 if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
00207 if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
00208 if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
00209 if ( !fscanf(fp,"%f %f %f\n", &xx, &yy, &zz) ) return false;
00210
00211 if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false;
00212 if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false;
00213 if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false;
00214 if ( !fscanf(fp,"%f %f %f %f\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false;
00215
00216
00217
00218
00219
00220
00221
00222 int ii=0;
00223 fread(&(linebuf[ii++]),1,1,fp);
00224 while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
00225 linebuf[ii-1] = '\0';
00226 numtokens=1;
00227 for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
00228 if(numtokens == 4) hascolor = false;
00229 else if(numtokens == 7) hascolor = true;
00230 else return false;
00231
00232
00233 currtrasf.transposeInPlace();
00234
00235
00236 int vn = rownum*colnum;
00237 VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
00238 m.vn = vn;
00239 m.bbox.SetNull();
00240
00241
00242 if(hascolor)
00243 {
00244 printf("\n hascolor ");
00245 sscanf(linebuf,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00246 }
00247 else
00248 {
00249 printf("\n no color ");
00250 sscanf(linebuf,"%f %f %f %f", &xx, &yy, &zz, &rf);
00251 }
00252
00253
00254 (*vi).P()[0]=xx;
00255 (*vi).P()[1]=yy;
00256 (*vi).P()[2]=zz;
00257
00258 m.bbox.Add( (*vi).P() );
00259
00260 if(VertexType::HasQuality())
00261 {
00262 (*vi).Q()=rf;
00263 }
00264
00265 if(hascolor && savecolor)
00266 {
00267 (*vi).C()[0]=rr;
00268 (*vi).C()[1]=gg;
00269 (*vi).C()[2]=bb;
00270 }
00271 else if(!hascolor && savecolor)
00272 {
00273 (*vi).C()[0]=rf*255;
00274 (*vi).C()[1]=rf*255;
00275 (*vi).C()[2]=rf*255;
00276 }
00277 vi++;
00278
00279
00280 for(ii=0; ii<((rownum*colnum)-1); ii++)
00281 {
00282 char tmp[255];
00283 sprintf(tmp, "PTX Mesh Loading...");
00284 if(cb) cb((ii*total)/vn, tmp);
00285
00286
00287 if(hascolor)
00288 fscanf(fp,"%f %f %f %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00289 else
00290 fscanf(fp,"%f %f %f %f", &xx, &yy, &zz, &rf);
00291
00292
00293 (*vi).P()[0]=xx;
00294 (*vi).P()[1]=yy;
00295 (*vi).P()[2]=zz;
00296
00297 m.bbox.Add( (*vi).P() );
00298
00299 if(VertexType::HasQuality())
00300 {
00301 (*vi).Q()=rf;
00302 }
00303
00304 if(hascolor && savecolor)
00305 {
00306 (*vi).C()[0]=rr;
00307 (*vi).C()[1]=gg;
00308 (*vi).C()[2]=bb;
00309 }
00310 else if(!hascolor && savecolor)
00311 {
00312 (*vi).C()[0]=rf*255;
00313 (*vi).C()[1]=rf*255;
00314 (*vi).C()[2]=rf*255;
00315 }
00316
00317 vi++;
00318 }
00319
00320 if(! onlypoints)
00321 {
00322
00323 int trinum = (rownum-1) * (colnum-1) * 2;
00324 typename OpenMeshType::FaceIterator fi= Allocator<OpenMeshType>::AddFaces(m,trinum);
00325 m.fn = trinum;
00326 int v0i,v1i,v2i, t;
00327 t=0;
00328 for(int rit=0; rit<rownum-1; rit++)
00329 for(int cit=0; cit<colnum-1; cit++)
00330 {
00331 t++;
00332 if(cb) cb(50 + (t*50)/(rownum*colnum),"PTX Mesh Loading");
00333
00334 if(!switchside)
00335 {
00336 v0i = (rit ) + ((cit ) * rownum);
00337 v1i = (rit+1) + ((cit ) * rownum);
00338 v2i = (rit ) + ((cit+1) * rownum);
00339 }
00340 else
00341 {
00342 v0i = (cit ) + ((rit ) * colnum);
00343 v1i = (cit+1) + ((rit ) * colnum);
00344 v2i = (cit ) + ((rit+1) * colnum);
00345 }
00346
00347
00348 (*fi).V(2) = &(m.vert[v0i]);
00349 (*fi).V(1) = &(m.vert[v1i]);
00350 (*fi).V(0) = &(m.vert[v2i]);
00351 if(flipfaces)
00352 {
00353 (*fi).V(2) = &(m.vert[v1i]);
00354 (*fi).V(1) = &(m.vert[v0i]);
00355 }
00356
00357 fi++;
00358 if(!switchside)
00359 {
00360 v0i = (rit+1) + ((cit ) * rownum);
00361 v1i = (rit+1) + ((cit+1) * rownum);
00362 v2i = (rit ) + ((cit+1) * rownum);
00363 }
00364 else
00365 {
00366 v0i = (cit+1) + ((rit ) * colnum);
00367 v1i = (cit+1) + ((rit+1) * colnum);
00368 v2i = (cit ) + ((rit+1) * colnum);
00369 }
00370
00371 (*fi).V(2) = &(m.vert[v0i]);
00372 (*fi).V(1) = &(m.vert[v1i]);
00373 (*fi).V(0) = &(m.vert[v2i]);
00374 if(flipfaces)
00375 {
00376 (*fi).V(2) = &(m.vert[v1i]);
00377 (*fi).V(1) = &(m.vert[v0i]);
00378 }
00379
00380 fi++;
00381 }
00382 }
00383
00384
00385 if(importparams.pointcull)
00386 {
00387 if(cb) cb(40,"PTX Mesh Loading - remove invalid vertices");
00388 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
00389 {
00390 if((*vi).P() == Point3f(0.0, 0.0, 0.0))
00391 Allocator<OpenMeshType>::DeleteVertex(m,*vi);
00392 }
00393
00394 if(! importparams.pointsonly)
00395 {
00396 if(cb) cb(60,"PTX Mesh Loading - remove invalid faces");
00397 for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00398 {
00399 if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) )
00400 Allocator<OpenMeshType>::DeleteFace(m,*fi);
00401 }
00402 }
00403 }
00404
00405
00406 if(! importparams.pointsonly)
00407 {
00408 if(importparams.anglecull)
00409 {
00410 float limit = cos( double(importparams.angle)*3.14159265358979323846/180.0 );
00411 Point3f raggio;
00412
00413 if(cb) cb(85,"PTX Mesh Loading - remove steep faces");
00414 vcg::tri::UpdateNormals<OpenMeshType>::PerFaceNormalized(m);
00415 for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00416 if(!(*fi).IsD())
00417 {
00418 raggio = -((*fi).V(0)->P() + (*fi).V(1)->P() + (*fi).V(2)->P()) / 3.0;
00419 raggio.Normalize();
00420 if((raggio.dot((*fi).N())) < limit)
00421 Allocator<OpenMeshType>::DeleteFace(m,*fi);
00422
00423 }
00424 }
00425 }
00426
00427 for(typename OpenMeshType::VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
00428 {
00429 if(!(*vi).IsD())
00430 (*vi).P() = currtrasf * (*vi).P();
00431 }
00432
00433
00434 vcg::tri::Clean<OpenMeshType>::RemoveUnreferencedVertex(m);
00435 vcg::tri::UpdateNormals<OpenMeshType>::PerFaceNormalized(m);
00436 vcg::tri::UpdateBounding<CMeshO>::Box(m);
00437 if(cb) cb(100,"PTX Mesh Loading finish!");
00438 return true;
00439 }
00440
00441 };
00442
00443 }
00444 }
00445 }
00446 #endif