00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #ifndef __VCGLIB_IMPORT_PTX
00025 #define __VCGLIB_IMPORT_PTX
00026
00027 #include <stdio.h>
00028 #include <wrap/callback.h>
00029 #include <vcg/complex/algorithms/clean.h>
00030 #include <vcg/complex/algorithms/update/normal.h>
00031 #include <vcg/complex/algorithms/update/position.h>
00032 #include <vcg/complex/algorithms/update/bounding.h>
00033
00034 namespace vcg {
00035 namespace tri {
00036 namespace io {
00041 template <class OpenMeshType>
00042 class ImporterPTX
00043 {
00044 public:
00045 typedef typename OpenMeshType::VertexPointer VertexPointer;
00046 typedef typename OpenMeshType::ScalarType ScalarType;
00047 typedef typename OpenMeshType::VertexType VertexType;
00048 typedef typename OpenMeshType::FaceType FaceType;
00049 typedef typename OpenMeshType::VertexIterator VertexIterator;
00050 typedef typename OpenMeshType::FaceIterator FaceIterator;
00051 typedef typename OpenMeshType::CoordType CoordType;
00052 typedef typename vcg::Matrix44<ScalarType> Matrix44x;
00053
00054 class Info
00055 {
00056 public:
00057
00058 Info()
00059 {
00060 mask = 0;
00061 meshnum = 0;
00062 anglecull = true;
00063 angle = 89;
00064 savecolor = true;
00065 pointcull = true;
00066 pointsonly = false;
00067 switchside = false;
00068 flipfaces = false;
00069 }
00070
00072 int mask;
00073
00075 int meshnum;
00076
00078 bool anglecull;
00080 float angle;
00081
00083 bool pointcull;
00084
00086 bool pointsonly;
00087
00089 bool savecolor;
00090
00092 bool switchside;
00094 bool flipfaces;
00095
00096 };
00097
00098
00100 static const char *ErrorMsg(int error)
00101 {
00102 static const char * ptx_error_msg[] =
00103 {
00104 "No errors",
00105 "Can't open file",
00106 "Header not found",
00107 "Eof in header",
00108 "Format not found",
00109 "Syntax error on header",
00110 };
00111 if(error>6 || error<0) return "Unknown error";
00112 else return ptx_error_msg[error];
00113 };
00114
00117 static bool skipmesh(FILE* fp, CallBackPos *cb=NULL)
00118 {
00119 int colnum;
00120 int rownum;
00121 int skiplines;
00122 char linebuf;
00123
00124 if(feof(fp)) return false;
00125
00126
00127 fscanf(fp,"%i\n",&colnum);
00128 fscanf(fp,"%i\n",&rownum);
00129
00130 if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00131 if(feof(fp)) return false;
00132
00133
00134 skiplines = (colnum * rownum) + 8;
00135 for(int ii=0; ii<skiplines; ii++)
00136 {
00137 fread(&linebuf,1,1,fp);
00138 while(linebuf != '\n') fread(&linebuf,1,1,fp);
00139 }
00140
00141 if(cb) cb( 100, "Skipped preamble");
00142 return true;
00143 }
00144
00146 static int Open( OpenMeshType &m, const char * filename, Info importparams, CallBackPos *cb=NULL)
00147 {
00148 FILE *fp;
00149 fp = fopen(filename, "rb");
00150 if(fp == NULL) return false;
00151 m.Clear();
00152 m.vn=0;
00153 m.fn=0;
00154
00155
00156 if (importparams.meshnum>0)
00157 for (int i=0; i!=importparams.meshnum; ++i)
00158 if(!skipmesh(fp, cb))
00159 return 1;
00160
00161 if (!readPTX( m, fp, importparams, cb))
00162 {
00163 m.Clear();
00164 return 1;
00165 }
00166
00167 return 0;
00168 }
00169
00171 static bool readPTX( OpenMeshType &m, FILE *fp, Info importparams, CallBackPos *cb=NULL)
00172 {
00173 int numtokens;
00174 int colnum;
00175 int rownum;
00176 double xx,yy,zz;
00177 float rr,gg,bb;
00178 float rf;
00179 Matrix44d currtrasf;
00180
00181 bool hascolor;
00182 bool savecolor = importparams.savecolor && VertexType::HasColor();
00183 bool switchside = importparams.switchside;
00184
00185 int total = 50;
00186 if (importparams.pointsonly) total = 100;
00187 char linebuf[256];
00188
00189 fscanf(fp,"%i\n",&colnum);
00190 fscanf(fp,"%i\n",&rownum);
00191
00192 if ( ( colnum <=0 ) || ( rownum <=0 ) ) return false;
00193
00194 if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00195 if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00196 if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00197 if ( !fscanf(fp,"%lf %lf %lf\n", &xx, &yy, &zz) ) return false;
00198
00199 if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(0,0)), &(currtrasf.ElementAt(0,1)), &(currtrasf.ElementAt(0,2)), &(currtrasf.ElementAt(0,3))) )return false;
00200 if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(1,0)), &(currtrasf.ElementAt(1,1)), &(currtrasf.ElementAt(1,2)), &(currtrasf.ElementAt(1,3))) )return false;
00201 if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(2,0)), &(currtrasf.ElementAt(2,1)), &(currtrasf.ElementAt(2,2)), &(currtrasf.ElementAt(2,3))) )return false;
00202 if ( !fscanf(fp,"%lf %lf %lf %lf\n", &(currtrasf.ElementAt(3,0)), &(currtrasf.ElementAt(3,1)), &(currtrasf.ElementAt(3,2)), &(currtrasf.ElementAt(3,3))) )return false;
00203
00204
00205
00206
00207
00208
00209
00210 int ii=0;
00211 fread(&(linebuf[ii++]),1,1,fp);
00212 while(linebuf[ii-1] != '\n') if ( fread(&(linebuf[ii++]),1,1,fp)==0 ) return false;
00213 linebuf[ii-1] = '\0';
00214 numtokens=1;
00215 for(ii=0; ii<(int)strlen(linebuf); ii++) if(linebuf[ii] == ' ') numtokens++;
00216 if(numtokens == 4) hascolor = false;
00217 else if(numtokens == 7) hascolor = true;
00218 else return false;
00219
00220
00221 currtrasf.transposeInPlace();
00222
00223
00224 int vn = rownum*colnum;
00225 VertexIterator vi = Allocator<OpenMeshType>::AddVertices(m,vn);
00226 m.vn = vn;
00227 m.bbox.SetNull();
00228
00229
00230 if(hascolor)
00231 {
00232 printf("\n hascolor ");
00233 sscanf(linebuf,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00234 }
00235 else
00236 {
00237 printf("\n no color ");
00238 sscanf(linebuf,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
00239 }
00240
00241
00242 (*vi).P()[0]=xx;
00243 (*vi).P()[1]=yy;
00244 (*vi).P()[2]=zz;
00245
00246 if(VertexType::HasQuality())
00247 {
00248 (*vi).Q()=rf;
00249 }
00250
00251 if(savecolor)
00252 {
00253 if(hascolor)
00254 {
00255 (*vi).C()[0]=rr;
00256 (*vi).C()[1]=gg;
00257 (*vi).C()[2]=bb;
00258 } else {
00259 (*vi).C()[0]=rf*255;
00260 (*vi).C()[1]=rf*255;
00261 (*vi).C()[2]=rf*255;
00262 }
00263 }
00264 vi++;
00265
00266 if(switchside) std::swap(rownum,colnum);
00267
00268
00269 for(ii=0; ii<((rownum*colnum)-1); ii++)
00270 {
00271 if(cb && (ii%100)==0) cb((ii*total)/vn, "Vertex Loading");
00272
00273
00274 if(hascolor)
00275 fscanf(fp,"%lf %lf %lf %f %f %f %f", &xx, &yy, &zz, &rf, &rr, &gg, &bb);
00276 else
00277 fscanf(fp,"%lf %lf %lf %f", &xx, &yy, &zz, &rf);
00278
00279
00280 (*vi).P()[0]=xx;
00281 (*vi).P()[1]=yy;
00282 (*vi).P()[2]=zz;
00283
00284
00285 if(tri::HasPerVertexQuality(m)) (*vi).Q()=rf;
00286
00287 if(hascolor && savecolor)
00288 {
00289 (*vi).C()[0]=rr;
00290 (*vi).C()[1]=gg;
00291 (*vi).C()[2]=bb;
00292 }
00293 else if(!hascolor && savecolor)
00294 {
00295 (*vi).C()[0]=rf*255;
00296 (*vi).C()[1]=rf*255;
00297 (*vi).C()[2]=rf*255;
00298 }
00299
00300 vi++;
00301 }
00302
00303 if(! importparams.pointsonly)
00304 {
00305
00306 int trinum = (rownum-1) * (colnum-1) * 2;
00307 typename OpenMeshType::FaceIterator fi= Allocator<OpenMeshType>::AddFaces(m,trinum);
00308 int v0i,v1i,v2i, t;
00309 t=0;
00310 for(int rit=0; rit<rownum-1; rit++)
00311 for(int cit=0; cit<colnum-1; cit++)
00312 {
00313 t++;
00314 if(cb) cb(50 + (t*50)/(rownum*colnum),"PTX Mesh Loading");
00315
00316 v0i = (rit ) + ((cit ) * rownum);
00317 v1i = (rit+1) + ((cit ) * rownum);
00318 v2i = (rit ) + ((cit+1) * rownum);
00319
00320
00321 (*fi).V(2) = &(m.vert[v0i]);
00322 (*fi).V(1) = &(m.vert[v1i]);
00323 (*fi).V(0) = &(m.vert[v2i]);
00324
00325 fi++;
00326
00327 v0i = (rit+1) + ((cit ) * rownum);
00328 v1i = (rit+1) + ((cit+1) * rownum);
00329 v2i = (rit ) + ((cit+1) * rownum);
00330
00331
00332 (*fi).V(2) = &(m.vert[v0i]);
00333 (*fi).V(1) = &(m.vert[v1i]);
00334 (*fi).V(0) = &(m.vert[v2i]);
00335
00336 fi++;
00337 }
00338 }
00339 printf("Loaded %i vert\n",m.vn);
00340
00341 if(importparams.pointcull)
00342 {
00343 if(cb) cb(40,"PTX Mesh Loading - remove invalid vertices");
00344 for(VertexIterator vi = m.vert.begin(); vi != m.vert.end(); vi++)
00345 {
00346 if((*vi).P() == CoordType(0.0, 0.0, 0.0))
00347 Allocator<OpenMeshType>::DeleteVertex(m,*vi);
00348 }
00349
00350 if(! importparams.pointsonly)
00351 {
00352 if(cb) cb(60,"PTX Mesh Loading - remove invalid faces");
00353 for(typename OpenMeshType::FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00354 {
00355 if( ((*fi).V(0)->IsD()) || ((*fi).V(1)->IsD()) || ((*fi).V(2)->IsD()) )
00356 Allocator<OpenMeshType>::DeleteFace(m,*fi);
00357 }
00358 }
00359 }
00360
00361 float limitCos = cos( math::ToRad(importparams.angle) );
00362 printf("Loaded %i vert\n",m.vn);
00363 if(importparams.pointsonly)
00364 {
00365
00366
00367 if(cb) cb(85,"PTX Mesh Loading - computing vert normals");
00368 for(int rit=0; rit<rownum; rit++)
00369 {
00370 int ritL = std::max(rit-1,0);
00371 int ritR = std::min(rit+1,rownum-1);
00372 for(int cit=0; cit<colnum; cit++)
00373 {
00374 int citT = std::max(cit-1,0);
00375 int citB = std::min(cit+1,colnum-1);
00376 int v0 = (rit ) + ((cit ) * rownum);
00377
00378 if(m.vert[v0].IsD()) continue;
00379
00380 int vL = (ritL) + ((cit ) * rownum);
00381 int vR = (ritR) + ((cit) * rownum);
00382 int vT = (rit ) + ((citT ) * rownum);
00383 int vB = (rit ) + ((citB) * rownum);
00384
00385 CoordType v0p=m.vert[v0].P();
00386 CoordType vLp(0,0,0),vRp(0,0,0),vTp(0,0,0),vBp(0,0,0);
00387 if(!m.vert[vL].IsD()) vLp=(m.vert[vL].P()-v0p).Normalize();
00388 if(!m.vert[vR].IsD()) vRp=(m.vert[vR].P()-v0p).Normalize();
00389 if(!m.vert[vT].IsD()) vTp=(m.vert[vT].P()-v0p).Normalize();
00390 if(!m.vert[vB].IsD()) vBp=(m.vert[vB].P()-v0p).Normalize();
00391 float r=0;
00392 int rc=0; CoordType v0pn = Normalize(v0p);
00393
00394
00395 CoordType vLTn = (vLp ^ vTp).Normalize();
00396 CoordType vTRn = (vTp ^ vRp).Normalize();
00397 CoordType vRBn = (vRp ^ vBp).Normalize();
00398 CoordType vBLn = (vBp ^ vLp).Normalize();
00399
00400
00401
00402 CoordType N(0,0,0);
00403 if((vLTn*v0pn)>limitCos) { N+=vLTn; r += Distance(m.vert[vL].P(),v0p)+Distance(m.vert[vT].P(),v0p); rc++; }
00404 if((vTRn*v0pn)>limitCos) { N+=vTRn; r += Distance(m.vert[vT].P(),v0p)+Distance(m.vert[vR].P(),v0p); rc++; }
00405 if((vRBn*v0pn)>limitCos) { N+=vRBn; r += Distance(m.vert[vR].P(),v0p)+Distance(m.vert[vB].P(),v0p); rc++; }
00406 if((vBLn*v0pn)>limitCos) { N+=vBLn; r += Distance(m.vert[vB].P(),v0p)+Distance(m.vert[vL].P(),v0p); rc++; }
00407
00408 m.vert[v0].N()=-N;
00409
00410 if(tri::HasPerVertexRadius(m)) m.vert[v0].R() = r/(rc*2.0f);
00411
00412 if(m.vert[v0].N() == CoordType(0,0,0)) Allocator<OpenMeshType>::DeleteVertex(m,m.vert[v0]);
00413 }
00414 }
00415 }
00416 else
00417
00418 {
00419 if(importparams.flipfaces)
00420 tri::Clean<OpenMeshType>::FlipMesh(m);
00421 if(importparams.anglecull)
00422 {
00423 if(cb) cb(85,"PTX Mesh Loading - remove steep faces");
00424 tri::UpdateNormal<OpenMeshType>::PerFaceNormalized(m);
00425 for(FaceIterator fi = m.face.begin(); fi != m.face.end(); fi++)
00426 if(!(*fi).IsD())
00427 {
00428 CoordType raggio = -((*fi).P(0) + (*fi).P(1) + (*fi).P(2)) / 3.0;
00429 raggio.Normalize();
00430 if((raggio.dot((*fi).N())) < limitCos)
00431 Allocator<OpenMeshType>::DeleteFace(m,*fi);
00432 }
00433
00434 tri::Clean<OpenMeshType>::RemoveUnreferencedVertex(m);
00435 }
00436 }
00437 Matrix44x tr;
00438 tr.Import(currtrasf);
00439 tri::UpdatePosition<OpenMeshType>::Matrix(m,tr,true);
00440 tri::Allocator<OpenMeshType>::CompactVertexVector(m);
00441 tri::UpdateBounding<OpenMeshType>::Box(m);
00442 if(cb) cb(100,"PTX Mesh Loading finished!");
00443 return true;
00444 }
00445
00446 };
00447
00448 }
00449 }
00450 }
00451 #endif