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
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070 #ifndef __VCGLIB_IMPORT_STL
00071 #define __VCGLIB_IMPORT_STL
00072 #include <stdio.h>
00073 #include <wrap/callback.h>
00074 #include <vcg/complex/trimesh/allocate.h>
00075
00076 namespace vcg {
00077 namespace tri {
00078 namespace io {
00079
00085 template <class OpenMeshType>
00086 class ImporterSTL
00087 {
00088 public:
00089
00090 typedef typename OpenMeshType::VertexPointer VertexPointer;
00091 typedef typename OpenMeshType::ScalarType ScalarType;
00092 typedef typename OpenMeshType::VertexType VertexType;
00093 typedef typename OpenMeshType::FaceType FaceType;
00094 typedef typename OpenMeshType::VertexIterator VertexIterator;
00095 typedef typename OpenMeshType::FaceIterator FaceIterator;
00096
00097
00098
00099 enum {STL_LABEL_SIZE=80};
00100
00101 class STLFacet
00102 {
00103 public:
00104 Point3f n;
00105 Point3f v[3];
00106
00107 };
00108
00109 enum STLError {
00110 E_NOERROR,
00111
00112 E_CANTOPEN,
00113 E_UNESPECTEDEOF
00114 };
00115
00116 static const char *ErrorMsg(int error)
00117 {
00118 static const char * stl_error_msg[] =
00119 {
00120 "No errors",
00121 "Can't open file",
00122 "Premature End of file",
00123 };
00124
00125 if(error>2 || error<0) return "Unknown error";
00126 else return stl_error_msg[error];
00127 };
00128
00129 static int Open(OpenMeshType &mesh, const char *filename, int &loadmask, CallBackPos *cb=0)
00130 {
00131 loadmask = Mask::IOM_VERTCOORD | Mask::IOM_FACEINDEX;
00132 return Open(mesh,filename,cb);
00133 }
00134
00135 static int Open( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
00136 {
00137 FILE *fp;
00138 bool binary=false;
00139 fp = fopen(filename, "r");
00140 if(fp == NULL)
00141 {
00142 return E_CANTOPEN;
00143 }
00144
00145
00146 fseek(fp, 0, SEEK_END);
00147 int file_size = ftell(fp);
00148 int facenum;
00149
00150 fseek(fp, STL_LABEL_SIZE, SEEK_SET);
00151 fread(&facenum, sizeof(int), 1, fp);
00152 int expected_file_size=STL_LABEL_SIZE + 4 + (sizeof(short)+sizeof(STLFacet) )*facenum ;
00153 if(file_size == expected_file_size) binary = true;
00154 unsigned char tmpbuf[128];
00155 fread(tmpbuf,sizeof(tmpbuf),1,fp);
00156 for(unsigned int i = 0; i < sizeof(tmpbuf); i++)
00157 {
00158 if(tmpbuf[i] > 127)
00159 {
00160 binary=true;
00161 break;
00162 }
00163 }
00164
00165 fclose(fp);
00166 if(binary) return OpenBinary(m,filename,cb);
00167 else return OpenAscii(m,filename,cb);
00168 }
00169
00170 static int OpenBinary( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
00171 {
00172 FILE *fp;
00173 fp = fopen(filename, "rb");
00174 if(fp == NULL)
00175 {
00176 return E_CANTOPEN;
00177 }
00178
00179 int facenum;
00180 fseek(fp, STL_LABEL_SIZE, SEEK_SET);
00181 fread(&facenum, sizeof(int), 1, fp);
00182
00183 m.Clear();
00184 FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,facenum);
00185 VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,facenum*3);
00186
00187 for(int i=0;i<facenum;++i)
00188 {
00189 short attr;
00190 Point3f norm;
00191 Point3f tri[3];
00192 fread(&norm,sizeof(Point3f),1,fp);
00193 fread(&tri,sizeof(Point3f),3,fp);
00194 fread(&attr,sizeof(short),1,fp);
00195 for(int k=0;k<3;++k)
00196 {
00197 (*vi).P().Import(tri[k]);
00198 (*fi).V(k)=&*vi;
00199 ++vi;
00200 }
00201 ++fi;
00202 if(cb && (i%1000)==0) cb((i*100)/facenum,"STL Mesh Loading");
00203 }
00204 fclose(fp);
00205 return E_NOERROR;
00206 }
00207
00208
00209 static int OpenAscii( OpenMeshType &m, const char * filename, CallBackPos *cb=0)
00210 {
00211 FILE *fp;
00212 fp = fopen(filename, "r");
00213 if(fp == NULL)
00214 {
00215 return E_CANTOPEN;
00216 }
00217 long currentPos = ftell(fp);
00218 fseek(fp,0L,SEEK_END);
00219 long fileLen = ftell(fp);
00220 fseek(fp,currentPos,SEEK_SET);
00221
00222 m.Clear();
00223
00224
00225 while(getc(fp) != '\n') { }
00226
00227 STLFacet f;
00228 int cnt=0;
00229 int lineCnt=0;
00230 int ret;
00231
00232 while(!feof(fp))
00233 {
00234 if(cb && (++cnt)%1000) cb( int(double(ftell(fp))*100.0/fileLen), "STL Mesh Loading");
00235 ret=fscanf(fp, "%*s %*s %f %f %f\n", &f.n.X(), &f.n.Y(), &f.n.Z());
00236 if(ret!=3)
00237 {
00238
00239
00240
00241
00242
00243
00244 lineCnt++;
00245 continue;
00246 }
00247 ret=fscanf(fp, "%*s %*s");
00248 ret=fscanf(fp, "%*s %f %f %f\n", &f.v[0].X(), &f.v[0].Y(), &f.v[0].Z());
00249 if(ret!=3)
00250 return E_UNESPECTEDEOF;
00251 ret=fscanf(fp, "%*s %f %f %f\n", &f.v[1].X(), &f.v[1].Y(), &f.v[1].Z());
00252 if(ret!=3)
00253 return E_UNESPECTEDEOF;
00254 ret=fscanf(fp, "%*s %f %f %f\n", &f.v[2].X(), &f.v[2].Y(), &f.v[2].Z());
00255 if(ret!=3)
00256 return E_UNESPECTEDEOF;
00257 ret=fscanf(fp, "%*s");
00258 ret=fscanf(fp, "%*s");
00259 lineCnt+=7;
00260 if(feof(fp)) break;
00261 FaceIterator fi=Allocator<OpenMeshType>::AddFaces(m,1);
00262 VertexIterator vi=Allocator<OpenMeshType>::AddVertices(m,3);
00263 for(int k=0;k<3;++k)
00264 {
00265 (*vi).P().Import(f.v[k]);
00266 (*fi).V(k)=&*vi;
00267 ++vi;
00268 }
00269 }
00270 fclose(fp);
00271 return E_NOERROR;
00272 }
00273 };
00274 }
00275 }
00276 }
00277
00278 #endif