Main Page | Namespace List | Class Hierarchy | Alphabetical List | Class List | Directories | File List | Namespace Members | Class Members | File Members | Related Pages

Parser.cpp

Go to the documentation of this file.
00001 //
00002 // File:   Parser.cpp
00003 // Author: Steve Kilthau
00004 // Date:   August, 1999
00005 // 
00006 // This file implements a parser class.  The parser is
00007 // used to read scene-files describing objects in a 
00008 // given scene.
00009 //
00010 
00011 #include <stdio.h>
00012 #include <string.h>
00013 #include "Parser.h"
00014 #include "spectral.h"
00015 #include "vuColourRGBa.h"
00016 #include "vuColour31a.h"
00017 #include "vuColour7a.h"
00018 #include "vuColour9a.h"
00019 #include "vuColourXYZa.h"
00020 #include "Util.h"
00021 
00022 namespace ns_vu1112112 {
00023 using namespace ns_vu1112112;
00024 
00025 // Default constructor - set initial values
00026 Parser::Parser()
00027 {
00028     m_Buffer = 0;
00029     m_Pos    = 0;
00030     m_ReadAmbient = false;
00031 }
00032 
00033 // Destructor
00034 Parser::~Parser()
00035 {
00036     if (m_Buffer)
00037         delete [] m_Buffer;
00038 }
00039 
00040 // Parse the file represented by "filename" and 
00041 // return the resulting scene in "scene".
00042 bool Parser::Parse(const char* filename, vu1112112& scene)
00043 {
00044     FILE* ifp;
00045 
00046     ifp = fopen(filename, "rb");
00047     if (ifp)
00048     {
00049         int stats[5] = {0,0,0,0,0};
00050         int length;
00051 
00052         // Get the buffer
00053                 // SB: Here we could add a feature for comment lines
00054         fseek(ifp, 0, SEEK_END);
00055         length = ftell(ifp);
00056         fseek(ifp, 0, SEEK_SET);
00057         m_Buffer = new char[length+1];
00058         fread(m_Buffer, 1, length, ifp);
00059         m_Buffer[length] = 0;
00060         fclose(ifp);
00061 
00062         // Read the scene
00063         do
00064         {
00065             stats[4] = 0;
00066             if (!stats[0] && ReadGeneral(scene)){
00067                 stats[0] = 1; stats[4]++;
00068             }
00069             if (!stats[1] && ReadTarga(scene)){
00070                 stats[1] = 1; stats[4]++;
00071             }
00072             if (!stats[2] && ReadMaterial(scene)){
00073                 //stats[2] = 1; 
00074                                 stats[4]++;
00075             }
00076             if (!stats[3] && ReadLight(scene)){
00077                 //stats[3] = 1; 
00078                                 stats[4]++;
00079             }
00080         }while(stats[4]);
00081 
00082         CheckError();
00083     }
00084 
00085     return true;
00086 }
00087 
00088 // Try to read the "general" block from the buffer
00089 bool Parser::ReadGeneral(vu1112112& s)
00090 {
00091     int stats[7] = {0,0,0,0,0,0,0};
00092     ColourType c;
00093     vuVector v;
00094     float n;
00095 
00096     if (ReadString(" general {"))
00097     {
00098                 Material mat;
00099         do
00100         {
00101             stats[6] = 0;
00102             if (!stats[0] && ReadColourType(" background", c, cColour)){
00103                 stats[0] = 1; stats[6]++; s.Background = c;
00104             }
00105             if (!stats[1] && ReadNumber(" brightness", n)){
00106                 stats[1] = 1; stats[6]++; s.brightness = n;
00107             }
00108             if (!stats[2] && ReadVector3(" light_dir", v)){
00109                 stats[2] = 1; stats[6]++; s.m_LightDir = v.normalize();
00110             }
00111             if (!stats[3] && ReadNumber(" diffuse", n)){
00112                 stats[3] = 1; stats[6]++; s.diffuse = n;
00113             }
00114             if (!stats[4] && ReadNumber(" light_scale", n)){
00115                 stats[4] = 1; stats[6]++; s.light_scale = n;
00116             }
00117             if (ReadString(" }")){
00118                 stats[6]++; break;
00119             }
00120         }while(stats[6]);
00121 
00122         if (stats[6])
00123             return true;
00124     }
00125     return false;
00126 }
00127 
00128 // Check if an error was encountered during parsing.
00129 // Report the position in the file that was successfully
00130 // parsed up to.
00131 void Parser::CheckError(void)
00132 {
00133     int pos = m_Pos;
00134 
00135     // Skip trailing whitespace
00136     ReadString(" ");
00137 
00138     // If not at the end of the buffer then there
00139     // has been a parse error.
00140     if (m_Buffer[m_Pos])
00141     {
00142         char error[1024];
00143         char last=0;
00144         int  line=1;
00145         int  i=0;
00146 
00147         // Count the number of lines parsed
00148         while(i < pos)
00149         {
00150             if (m_Buffer[i]==10)
00151             {
00152                 if (last==13)
00153                 {
00154                     last = 0;
00155                     ++i;
00156                 }
00157                 else
00158                 {
00159                     ++line;
00160                     last = m_Buffer[i++];
00161                 }
00162             }
00163             else if (m_Buffer[i]==13)
00164             {
00165                 if (last==10)
00166                 {
00167                     last = 0;
00168                     ++i;
00169                 }
00170                 else
00171                 {
00172                     ++line;
00173                     last = m_Buffer[i++];
00174                 }
00175             }
00176             else
00177                 last = m_Buffer[i++];
00178         }
00179 
00180         // Find the position in the current line
00181         while((i>0) && (m_Buffer[i]!=10) && (m_Buffer[i]!=13))
00182             --i;
00183         pos -= i;
00184         if ((pos==0) && (line>1))
00185             ++line;
00186 
00187         sprintf(error, "PARSER - Parsed successfully to line %i, character %i.", line, pos);
00188         throw error;
00189     }
00190 }
00191 
00192 // Try to read the static text given by "s" from the buffer
00193 bool Parser::ReadString(char* s)
00194 {
00195     char str[1024];
00196     int ret, len=0;
00197     strcpy(str, s);
00198     strcat(str, "%n");
00199     ret = sscanf(&m_Buffer[m_Pos], str, &len);
00200     if ((ret!=EOF) && (len!=0))
00201     {
00202         m_Pos += len;
00203         return true;
00204     }
00205     return false;
00206 }
00207 
00208 // Try to read a string prefixed by "prefix" from the buffer
00209 bool Parser::ReadString(char* prefix, char* s)
00210 {
00211     char str[1024];
00212     int i=0;
00213     strcpy(str, prefix);
00214     strcat(str, " \"");
00215     if (ReadString(str))
00216     {
00217         while((m_Buffer[m_Pos]!='"') && m_Buffer[m_Pos])
00218             s[i++] = m_Buffer[m_Pos++];
00219         s[i] = 0;
00220         if (m_Buffer[m_Pos]=='"')
00221         {
00222             ++m_Pos;
00223             return true;
00224         }
00225     }
00226     return false;
00227 }
00228 
00229 // Try to read a number prefixed by "prefix" from the buffer
00230 bool Parser::ReadNumber(char* prefix, float& t)
00231 {
00232     char str[1024];
00233     int ret, len=0;
00234     strcpy(str, prefix);
00235     strcat(str, " %f%n");
00236     ret = sscanf(&m_Buffer[m_Pos], str, (float*)&t, &len);
00237     if ((ret == 1) && (len!=0))
00238     {
00239         m_Pos += len;
00240         return true;
00241     }
00242     return false;
00243 }
00244 
00245 // Try to read a vector prefixed by "prefix" from the buffer.
00246 // The vector read must have 3 members.
00247 bool Parser::ReadVector3(char* prefix, vuVector& v)
00248 {
00249     char str[1024];
00250     int pos;
00251 
00252     pos = m_Pos;
00253     strcpy(str, prefix);
00254     strcat(str, " <");
00255     if (ReadNumber(str, v[0]))
00256         if (ReadNumber(" ,", v[1]))
00257             if (ReadNumber(" ,", v[2]))
00258                 if (ReadString(" >"))
00259                     return true;
00260     m_Pos = pos;
00261     return false;
00262 }
00263 
00264 // Try to read a vector prefixed by "prefix" from the buffer.
00265 // The vector read must have 4 members.
00266 bool Parser::ReadvuVector(char* prefix, vuVector& v)
00267 {
00268     char str[1024];
00269     int pos;
00270 
00271     pos = m_Pos;
00272     strcpy(str, prefix);
00273     strcat(str, " <");
00274     if (ReadNumber(str, v[0]))
00275         if (ReadNumber(" ,", v[1]))
00276             if (ReadNumber(" ,", v[2]))
00277                 if (ReadNumber(" ,", v[3]))
00278                     if (ReadString(" >"))
00279                         return true;
00280     m_Pos = pos;
00281     return false;
00282 }
00283 
00284 // Try to read an vuColourRGBa prefixed by "prefix" from the buffer.
00285 // Only read the RGB values.
00286 bool Parser::ReadRGB(char* prefix, vuColourRGBa& r)
00287 {
00288     char str[1024];
00289     int pos;
00290 
00291     pos = m_Pos;
00292     strcpy(str, prefix);
00293     strcat(str, " <");
00294     if (ReadNumber(str, r[0]))
00295         if (ReadNumber(" ,", r[1]))
00296             if (ReadNumber(" ,", r[2]))
00297                 if (ReadString(" >"))
00298                     return true;
00299     m_Pos = pos;
00300     return false;
00301 }
00302 
00303 // Try to read an vuColourRGBa prefixed by "prefix" from the buffer.
00304 // Read all of the vuColourRGBa values.
00305 bool Parser::ReadvuColourRGBa(char* prefix, vuColourRGBa& r)
00306 {
00307     char str[1024];
00308     int pos;
00309 
00310     pos = m_Pos;
00311     strcpy(str, prefix);
00312     strcat(str, " <");
00313     if (ReadNumber(str, r[0]))
00314         if (ReadNumber(" ,", r[1]))
00315             if (ReadNumber(" ,", r[2]))
00316                 if (ReadNumber(" ,", r[3]))
00317                     if (ReadString(" >"))
00318                         return true;
00319     m_Pos = pos;
00320     return false;
00321 }
00322 
00323 // Try to read a vuColour31a prefixed by "prefix" from the buffer.
00324 // Do not read the alpha channel.
00325 bool Parser::ReadSpectrum31(char* prefix, vuColour31a& s)
00326 {
00327     char str[1024];
00328     bool good;
00329     int pos;
00330     int i;
00331 
00332     pos = m_Pos;
00333     strcpy(str, prefix);
00334     strcat(str, " <");
00335     if (ReadNumber(str, s[0]))
00336     {
00337         good = true;
00338         for(i=1;(i<31)&&good;++i)
00339             good = ReadNumber(" ,", s[i]);
00340         if (good && ReadString(" >"))
00341             return true;
00342     }
00343     m_Pos = pos;
00344     return false;
00345 }
00346 
00347 // Try to read a vuColour31a prefixed by "prefix" from the buffer.
00348 // Read all channels.
00349 bool Parser::ReadvuColour31a(char* prefix, vuColour31a& s)
00350 {
00351     char str[1024];
00352     bool good;
00353     int pos;
00354     int i;
00355 
00356     pos = m_Pos;
00357     strcpy(str, prefix);
00358     strcat(str, " <");
00359     if (ReadNumber(str, s[0]))
00360     {
00361         good = true;
00362         for(i=1;(i<32)&&good;++i)
00363             good = ReadNumber(" ,", s[i]);
00364         if (good && ReadString(" >"))
00365             return true;
00366     }
00367     m_Pos = pos;
00368     return false;
00369 }
00370 
00371 // Try to read a vuColour7a prefixed by "prefix" from the buffer.
00372 // Do not read the alpha channel.
00373 bool Parser::ReadSpectrum7(char* prefix, vuColour7a& s)
00374 {
00375     char str[1024];
00376     bool good;
00377     int pos;
00378     int i;
00379 
00380     pos = m_Pos;
00381     strcpy(str, prefix);
00382     strcat(str, " <");
00383     if (ReadNumber(str, s[0]))
00384     {
00385         good = true;
00386         for(i=1;(i<7)&&good;++i)
00387             good = ReadNumber(" ,", s[i]);
00388         if (good && ReadString(" >"))
00389             return true;
00390     }
00391     m_Pos = pos;
00392     return false;
00393 }
00394 
00395 // Try to read a vuColour7a prefixed by "prefix" from the buffer.
00396 // Read all channels.
00397 bool Parser::ReadvuColour7a(char* prefix, vuColour7a& s)
00398 {
00399     char str[1024];
00400     bool good;
00401     int pos;
00402     int i;
00403 
00404     pos = m_Pos;
00405     strcpy(str, prefix);
00406     strcat(str, " <");
00407     if (ReadNumber(str, s[0]))
00408     {
00409         good = true;
00410         for(i=1;(i<8)&&good;++i)
00411             good = ReadNumber(" ,", s[i]);
00412         if (good && ReadString(" >"))
00413             return true;
00414     }
00415     m_Pos = pos;
00416     return false;
00417 }
00418 
00419 // Try to read a vuColour9a prefixed by "prefix" from the buffer.
00420 // Do not read the alpha channel.
00421 bool Parser::ReadSpectrum9(char* prefix, vuColour9a& s)
00422 {
00423     char str[1024];
00424     bool good;
00425     int pos;
00426     int i;
00427 
00428     pos = m_Pos;
00429     strcpy(str, prefix);
00430     strcat(str, " <");
00431     if (ReadNumber(str, s[0]))
00432     {
00433         good = true;
00434         for(i=1;(i<9)&&good;++i)
00435             good = ReadNumber(" ,", s[i]);
00436         if (good && ReadString(" >"))
00437             return true;
00438     }
00439     m_Pos = pos;
00440     return false;
00441 }
00442 
00443 // Try to read a vuColour9a prefixed by "prefix" from the buffer.
00444 // Read all channels.
00445 bool Parser::ReadvuColour9a(char* prefix, vuColour9a& s)
00446 {
00447     char str[1024];
00448     bool good;
00449     int pos;
00450     int i;
00451 
00452     pos = m_Pos;
00453     strcpy(str, prefix);
00454     strcat(str, " <");
00455     if (ReadNumber(str, s[0]))
00456     {
00457         good = true;
00458         for(i=1;(i<10)&&good;++i)
00459             good = ReadNumber(" ,", s[i]);
00460         if (good && ReadString(" >"))
00461             return true;
00462     }
00463     m_Pos = pos;
00464     return false;
00465 }
00466 
00467 // Try to read a colour prefixed by "prefix" from the buffer.
00468 // Do not read the alpha channel.
00469 bool Parser::ReadColourType(char* prefix,
00470                             ColourType& c,
00471                             ColourUsage u)
00472 {
00473 #if defined USE_vuColourRGBa
00474     if (u == cColour)
00475     {
00476         if (ReadvuColourRGBa(prefix, c))
00477         {
00478             return true;
00479         }
00480         else
00481         {
00482             vuColour31a s;
00483             vuColourXYZa x;
00484             if (ReadvuColour31a(prefix, s))
00485             {
00486                 if (m_ReadAmbient)
00487                     s *= m_Ambient;
00488                 x.From(s);
00489                 if (m_ReadAmbient)
00490                     x.SetNormalSpectrum(m_Ambient);
00491                 x.Normalize();
00492                 c.From(x);
00493                 c.ClampTo1();
00494                 return true;
00495             }
00496         }
00497     }
00498     else if (u == cLight || u == cAmbient || u == cBackground)
00499     {
00500         if (ReadRGB(prefix, c))
00501         {
00502             return true;
00503         }
00504         else
00505         {
00506             vuColour31a s;
00507             vuColourXYZa x;
00508             if (ReadSpectrum31(prefix, s))
00509             {
00510                 if (u == cAmbient)
00511                 {
00512                     m_Ambient = s;
00513                     m_ReadAmbient = true;
00514                 }
00515                 if (m_ReadAmbient && u == cBackground)
00516                     s *= m_Ambient;
00517                 x.From(s);
00518                 if (m_ReadAmbient)
00519                     x.SetNormalSpectrum(m_Ambient);
00520                 x.Normalize();
00521                 c.From(x);
00522                 c.ClampTo1();
00523                 return true;
00524             }
00525         }
00526     }
00527     return false;
00528 #elif defined USE_SPECTRUM31A
00529     if (u == cColour)
00530         return ReadvuColour31a(prefix, c);
00531     return ReadSpectrum31(prefix, c);
00532 #elif defined USE_SPECTRUM7A
00533     if (u == cColour)
00534     {
00535         if (ReadvuColour7a(prefix, c))
00536         {
00537             return true;
00538         }
00539         else
00540         {
00541             vuColour31a s;
00542             if (ReadvuColour31a(prefix, s))
00543             {
00544                 c.from(s);
00545                 return true;
00546             }
00547         }
00548     }
00549     else if (u == cLight)
00550     {
00551         if (ReadSpectrum7(prefix, c))
00552         {
00553             return true;
00554         }
00555         else
00556         {
00557             vuColour31a s;
00558             if (ReadSpectrum31(prefix, s))
00559             {
00560                 c.from(s);
00561                 return true;
00562             }
00563         }
00564     }
00565     return false;
00566 #elif defined USE_SPECTRUM9A
00567     if (u == cColour)
00568     {
00569         if (ReadvuColour9a(prefix, c))
00570         {
00571             return true;
00572         }
00573         else
00574         {
00575             vuColour31a s;
00576             if (ReadvuColour31a(prefix, s))
00577             {
00578                 c.from(s);
00579                 return true;
00580             }
00581         }
00582     }
00583     else if (u == cLight)
00584     {
00585         if (ReadSpectrum9(prefix, c))
00586         {
00587             return true;
00588         }
00589         else
00590         {
00591             vuColour31a s;
00592             if (ReadSpectrum31(prefix, s))
00593             {
00594                 c.from(s);
00595                 return true;
00596             }
00597         }
00598     }
00599     return false;
00600 #endif
00601 }
00602 
00603 // Try to read an Material from the buffer.
00604 bool Parser::ReadMaterial(vu1112112 &r)
00605 {
00606     int stats[8] = {0,0,0,0,0,0,0,0};
00607     ColourType c;
00608     float n;
00609     if (ReadString(" material {"))
00610     {     
00611         Material m;
00612         m.scattering=1;
00613         m.absorption=1;
00614         do
00615         {
00616             stats[7] = 0;
00617             if (!stats[0] && ReadColourType(" colour", c, cColour)){
00618                 stats[0] = 1; stats[7]++; m.scattering = c;
00619             }
00620             if (!stats[1] && ReadColourType(" absorption", c, cColour)){
00621                 stats[1] = 1; stats[7]++; m.absorption = c;
00622             }
00623             if (!stats[2] && ReadNumber(" low_th", n)){
00624                 stats[2] = 1; stats[7]++; m.low_th = (int)n;
00625             }
00626             if (!stats[3] && ReadNumber(" high_th", n)){
00627                 stats[3] = 1; stats[7]++; m.high_th = (int)n;
00628             }
00629             if (!stats[4] && ReadNumber(" xray", n)){
00630                 stats[4] = 1; stats[7]++; m.xray = (n == 1);
00631             }
00632             if (ReadString(" }")){
00633                 stats[7]++; break;
00634             }
00635         }while(stats[7]);
00636 
00637         if (stats[7])
00638                 {
00639                   m.check_absorption();
00640                   r.add_material(m);
00641                   return true;
00642                 }
00643     }
00644     return false;
00645 }
00646 
00647 // Try to read the "image" block from the buffer
00648 bool Parser::ReadTarga(vu1112112& s)
00649 {
00650     int stats[4] = {0,0,0,0};
00651     char c[64];
00652     float n;
00653 
00654     if (ReadString(" image {"))
00655     {
00656         do
00657         {
00658             stats[3] = 0;
00659             if (!stats[0] && ReadString(" name", c)){
00660                 FixName(c);
00661                 stats[0] = 1; stats[3]++; //s.Image.Name(c);
00662             }
00663             if (!stats[1] && ReadNumber(" width", n)){
00664                 stats[1] = 1; stats[3]++;
00665                 s.m_Camera->setWidth((int)n);
00666             }
00667             if (!stats[2] && ReadNumber(" height", n)){
00668                 stats[2] = 1; stats[3]++;
00669                 s.m_Camera->setHeight((int)n);
00670             }
00671             if (ReadString(" }")){
00672                 stats[3]++; break;
00673             }
00674         }while(stats[3]);
00675 
00676         if (stats[3])
00677             return true;
00678     }
00679     return false;
00680 }
00681 
00682 // Try to read a "light" block from the buffer
00683 bool Parser::ReadLight(vu1112112& scene)
00684 {
00685     int stats[4] = {0,0,0,0};
00686     vuVector v;
00687     ColourType c;
00688 
00689     if (ReadString(" light {"))
00690     {
00691         do
00692         {
00693             stats[3] = 0;
00694             if (!stats[1] && ReadColourType(" colour", c, cLight)){
00695                 stats[1] = 1; stats[3]++; scene.add_light(c);
00696             }
00697             if (ReadString(" }")){
00698                 stats[3]++; break;
00699             }
00700         }while(stats[3]);
00701 
00702         if (stats[3])
00703         {
00704             return true;
00705         }
00706     }
00707     return false;
00708 }
00709 
00710 void Parser::FixName(char* str)
00711 {
00712     char ext[32];
00713     int i=0;
00714 
00715     while(str[i] != '.' && str[i])
00716         ++i;
00717     strcpy(ext, &str[i]);
00718     str[i] = 0;
00719 #if defined USE_vuColourRGBa
00720     strcat(str, "_rgb");
00721 #elif defined USE_SPECTRUM31A
00722     strcat(str, "_31");
00723 #elif defined USE_SPECTRUM7A
00724     strcat(str, "_7");
00725 #elif defined USE_SPECTRUM9A
00726     strcat(str, "_9");
00727 #endif
00728     strcat(str, ext);
00729 }
00730 
00731 } // end of namespace

Generated on Wed Dec 15 21:20:30 2004 for vuVolume by  doxygen 1.3.9.1