Main Page Class Hierarchy Compound List File List Compound Members File Members

ParseObj.cc

Go to the documentation of this file.
00001 /*
00002 File: ParseObj.cc
00003 
00004 Function: Read wavefront "obj" files
00005 
00006 Author: Andrew Willmott
00007 
00008 Notes: 
00009 */
00010 
00011 #include <string.h>
00012 #include <unistd.h>
00013 #include "gcl/Scene.h"
00014 #include "gcl/SceneObjects.h"
00015 #include "gcl/Avars.h"
00016 #include "gcl/SceneLang.h"
00017 
00018 scScenePtr ParseObjFile(const Char *filename);
00019 
00020  static Void ReadIndexes(istream &s, Int &idx, Int &tidx, Int &nidx)
00021 {
00022 Char c;
00023 
00024 idx = tidx = nidx = 0;
00025 if (isdigit(s.peek()))
00026 s >> idx;
00027 if (s.peek() == '/')
00028 {
00029 s.get();
00030 if (isdigit(s.peek()))
00031 s >> tidx;
00032 if (s.peek() == '/')
00033 {
00034 s.get();
00035 if (isdigit(s.peek()))
00036 s >> nidx;
00037 }
00038 }
00039 
00040 idx--;
00041 nidx--;
00042 tidx--;
00043 }
00044 
00045 /*
00046 Example material file:
00047 
00048 newmtl Cube_0
00049 Ns 100
00050 d 1
00051 illum 2
00052 Ka .2 .2 .2
00053 Kd 0.8 0.8 0.8
00054 Ks 0 0 0
00055 map_Kd finishedx0001.jpg
00056 map_Ka finishedx0001.jpg
00057 */
00058 
00059  struct Mtl
00060 {
00061  Mtl() : flags(0) {};
00062 
00063  UInt32 flags;
00064  Colour kd;
00065  String texFile; 
00066 
00067 Void ApplyMtl();
00068 };
00069 
00070  enum MtlFlags 
00071 {
00072 hasTexture = 1,
00073 hasKd = 2,
00074 };
00075 
00076  Void Mtl::ApplyMtl()
00077 {
00078 if (flags & hasKd)
00079 slColour(kd);
00080 if (flags & hasTexture)
00081 {
00082 cerr << "setting texture " << texFile << endl;
00083 slEndFaces();
00084 slTexture(texFile);
00085 slBeginFaces();
00086 }
00087 }
00088 
00089  typedef Array<Mtl> MtlList;
00090 
00091  MtlList gMtlList;
00092  IntHash gMtlNames;
00093 
00094  Int ParseMaterialFile(StrConst filename)
00095 {
00096 String token;
00097 ifstream s;
00098 Colour c;
00099 
00100 cerr << "parsing material file " << filename << endl;
00101 s.open(filename);
00102 if (!s)
00103 {
00104 cerr << "(ParseMaterialFile) Cannot access " << filename << endl;
00105 return(-1);
00106 }
00107 
00108 while (s)
00109 {
00110 if (token.ReadWord(s))
00111 {
00112 if (token[0] == '#')
00113 ;
00114 else if (token == "newmtl")
00115 {
00116 String mtlName;
00117 
00118 mtlName.ReadWord(s);
00119 cerr << "new material " << mtlName << endl;
00120 gMtlNames.SetItem(mtlName, gMtlList.NumItems());
00121 gMtlList.Add(1);
00122 }
00123 else if (token == "Kd")
00124 {
00125 s >> c[0] >> c[1] >> c[2];
00126 gMtlList.Last().kd = c;
00127 gMtlList.Last().flags |= hasKd;
00128 }
00129 else if (token == "map_Kd")
00130 {
00131 String texFile;
00132 
00133 texFile.ReadWord(s);
00134 SubstituteEnvVars(texFile);
00135 
00136 cerr << "texture file " << texFile << endl;
00137 gMtlList.Last().flags |= hasTexture;
00138 gMtlList.Last().texFile = texFile;
00139 }
00140 else
00141 cerr << "(ParseMaterialFile) *** Ignoring unknown token: " << token << endl;
00142 
00143 token.ReadLine(s); // ignore rest of the line
00144 }
00145 }
00146 return(0);
00147 }
00148 
00149  #define SMF_OLD
00150 
00151  scScenePtr ParseObjFile(const Char *filename)
00152 // Parses wavefront-style .obj file.
00153 /*
00154 Format is: 'function args' on each line.
00155 
00156 v x y z add vertex
00157 vt u v [w] add texture vert.
00158 vn i j k add normal
00159 f 1 5 3 2 define polygon
00160 indices are of the form v[/vt[/vn]] 
00161 indices are 1-based.
00162 g group1 group2... set group names for following f's.
00163 o object name for following f's
00164 s n set smoothing group.
00165 usemtl material set material name for ...
00166 
00167 Extensions:
00168 
00169 c r g b add colour
00170 
00171 */
00172 {
00173 String token;
00174 Point vtx;
00175 Vector nrm;
00176 Coord tc;
00177 Colour clr;
00178 Int idx, tidx, nidx, cidx, vtxOffset;
00179 Int vertices, faces, colours, normals, texCoords;
00180 ifstream s;
00181 scScenePtr result;
00182 
00183 // create default material
00184 gMtlList.Clear();
00185 gMtlList.Add(1);
00186 
00187 vtxOffset = -1; // for michael garland's SMF format
00188 
00189 s.open(filename);
00190 if (!s)
00191 {
00192 cerr << "(ParseObjFile) Cannot access " << filename << endl;
00193 return(0);
00194 }
00195 
00196 result = slBeginObject(filename);
00197 slPointList();
00198 slBeginFaces();
00199 vertices = colours = faces = normals = texCoords = 0;
00200 
00201 while (s)
00202 {
00203 if (token.ReadWord(s))
00204 {
00205 if (token[0] == '#')
00206 ;
00207 else if (token == "begin" || token == "end")
00208 {
00209 // michael's stack demarcation? ignore for now
00210 }
00211 else if (token == "%SMF")
00212 {
00213 GCLReal version;
00214 s >> version;
00215 if (version < 1.0)
00216 vtxOffset = 0;
00217 }
00218 #ifdef SMF_OLD
00219 else if (token == "t")
00220 {
00221 // SMF triangle : obsolete?
00222 s >> idx; slPointIndex(idx + vtxOffset);
00223 s >> idx; slPointIndex(idx + vtxOffset);
00224 s >> idx; slPointIndex(idx + vtxOffset);
00225 slFace();
00226 faces++;
00227 }
00228 #endif 
00229 else if (token == "set")
00230 {
00231 token.ReadWord(s);
00232 if (token == "vertex_correction")
00233 {
00234 s >> vtxOffset;
00235 vtxOffset = 1 - vtxOffset;
00236 }
00237 else 
00238 cerr << "(ParseObjFile) *** Ignoring unknown set variable: "
00239 << token << endl;
00240 }
00241 
00242 // standard wavefront stuff
00243 else if (token == "v")
00244 {
00245 s >> vtx[0] >> vtx[1] >> vtx[2];
00246 slPoint(vtx);
00247 vertices++;
00248 }
00249 else if (token == "vt")
00250 {
00251 s >> tc[0] >> tc[1];
00252 
00253 if (texCoords == 0)
00254 slCoordList();
00255 slCoord(tc);
00256 
00257 texCoords++;
00258 }
00259 else if (token == "vn" || token == "n")
00260 {
00261 s >> nrm[0] >> nrm[1] >> nrm[2];
00262 
00263 if (normals == 0)
00264 slNormalList();
00265 slNormal(nrm);
00266 
00267 normals++;
00268 }
00269 else if (token == "vc" || token == "c") 
00270 // extension to handle vertex colours
00271 {
00272 s >> clr[0] >> clr[1] >> clr[2];
00273 if (colours == 0)
00274 slColourList();
00275 slColour(clr);
00276 colours++;
00277 }
00278 else if (token == "g" || token == "s" || token == "o")
00279 {
00280 // ignore for now...
00281 }
00282 else if (token == "f" || token == "fo")
00283 {
00284 while(!IsEndOfLine(s))
00285 {
00286 ReadIndexes(s, idx, tidx, nidx);
00287 
00288 if (idx < 0) idx += vertices;
00289 if (tidx < 0) tidx += texCoords;
00290 if (nidx < 0) nidx += normals;
00291 
00292 slPointIndex(idx);
00293 
00294 if (tidx >= 0)
00295 slCoordIndex(tidx);
00296 if (nidx >= 0)
00297 slNormalIndex(nidx);
00298 }
00299 slFace(); 
00300 faces++;
00301 }
00302 else if (token == "mtllib")
00303 {
00304 FileName mtlFile;
00305 
00306 token.ReadWord(s);
00307 mtlFile.SetPath(filename);
00308 mtlFile.SetRelPath(token);
00309 ParseMaterialFile(mtlFile.GetPath());
00310 }
00311 else if (token == "usemtl")
00312 {
00313 String material;
00314 
00315 material.ReadWord(s);
00316 
00317 slEndFaces();
00318 
00319 if (gMtlNames.ItemExists(material))
00320 {
00321 // XXX
00322 Int mtlIdx = gMtlNames.GetItem(material);
00323 
00324 gMtlList[mtlIdx].ApplyMtl();
00325 }
00326 else if (material == "light")
00327 {
00328 slAttribute(new scAvarEmittance(Avar("light", 20, 5, 50), 
00329 cWhite));
00330 scColour(cBlack);
00331 }
00332 else if (material == "colour")
00333 {
00334 Colour mc;
00335 
00336 s >> mc[0] >> mc[1] >> mc[2];
00337 slColour(mc); 
00338 }
00339 else if (material == "white")
00340 slColour(cWhite); 
00341 else if (material == "black")
00342 slColour(cBlack); 
00343 else if (material == "red")
00344 slColour(cRed); 
00345 else if (material == "blue")
00346 slColour(cBlue); 
00347 else if (material == "green")
00348 slColour(cGreen); 
00349 else if (material == "grey")
00350 slAttribute(new scAvarColour(Avar("grey", 0.5, 0, 1),
00351 cWhite));
00352 else
00353 {
00354 cerr << "(ParseObjFile) *** Warning: unrecognized material: " 
00355 << material << endl;
00356 // set to default material
00357 gMtlNames.SetItem(material, 0); 
00358 }
00359 
00360 slBeginFaces();
00361 }
00362 else
00363 cerr << "(ParseObjFile) *** Ignoring unknown token: " << token << endl;
00364 
00365 token.ReadLine(s); // ignore rest of the line
00366 }
00367 }
00368 
00369 slEndFaces();
00370 slEndObject();
00371 s.close();
00372 
00373 cerr << "Read " << vertices << " vertices, ";
00374 if (colours) cerr << colours << " colours, ";
00375 if (normals) cerr << normals << " normals, ";
00376 if (texCoords) cerr << texCoords << " texture coordinates, ";
00377 cerr << "and " << faces << " faces." << endl;
00378 
00379 return(result);
00380 }
00381 
00382 #ifdef CL_SGI_INST
00383 #pragma instantiate Array<Mtl>
00384 #endif
00385 

Generated at Sat Aug 5 00:17:01 2000 for Graphics Class Library by doxygen 1.1.0 written by Dimitri van Heesch, © 1997-2000

AltStyle によって変換されたページ (->オリジナル) /