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