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

ParseSC.cc

Go to the documentation of this file.
00001 /*
00002     File:       ParseSC.cc
00003     
00004     Purpose:    Parses Paul's .sc format
00005     
00006     Author:     Mainly uses code from Paul Heckbert & John Murphy.
00007 */
00008 
00009 #include "gcl/GCLConfig.h"
00010 
00011 #ifdef GCL_PARSE_SC
00012 
00013 #include <stdlib.h>
00014 #include <string.h>
00015 #include <ctype.h>
00016 #include <stdio.h>
00017 
00018 #include "gcl/SceneLang.h"
00019 
00020 
00022 static int lc;          // current line number in scene file
00023 
00024 // read whatever is left on a line (for comments)
00025 Void fread_to_eol(FILE *fp) {
00026     char c;
00027     do c = getc(fp); while (c!='\n');
00028     do {c = getc(fp); lc++;} while (c=='\n');
00029     if (!feof(fp)) ungetc(c, fp);
00030 }
00031 
00032 // Chomp away white space, but keep track of the newlines
00033 Void eatspace(FILE *fp) {
00034     char c;
00035     do {
00036     c = getc(fp);
00037     if (c=='#') {c = ' '; fread_to_eol(fp);}
00038     if (c=='\n') lc++;
00039     if (feof(fp)) return;
00040     } while (isspace(c));
00041     ungetc(c, fp);
00042 }
00043 
00044 // read the next string from the file, returns ptr to static
00045 char *fread_word(FILE *fp) {
00046     static char word[80];   // sets maximum word length
00047     eatspace(fp);
00048     int test = fscanf(fp, "%s", word);
00049     if (test==EOF) strcpy(word, "end");
00050     else if (test!=1) {
00051     cerr << "Scene Error, line " << lc
00052         << ": scanf returned " << test << endl;
00053     exit(1);
00054     }
00055     return word;
00056 }
00057 
00058 // read the next number from the file
00059 double fread_number(FILE *fp) {
00060     eatspace(fp);
00061     double number;
00062     int test = fscanf(fp, "%lf", &number);
00063     if (test!=1) {
00064     cerr << "Scene Error, line " << lc
00065         << ": scanf returned " << test << endl;
00066     exit(1);
00067     }
00068     return number;
00069 }
00070 
00071 Vector fread_Vector(FILE *fp)
00072 {
00073     double x = fread_number(fp);
00074     double y = fread_number(fp);
00075     double z = fread_number(fp);
00076     return(Vector(x, y, z));
00077 }
00078 
00079 Colour fread_Colour(FILE *fp)
00080 {
00081     double x = fread_number(fp);
00082     double y = fread_number(fp);
00083     double z = fread_number(fp);
00084     return(Colour(x, y, z));
00085 }
00086 
00087 // parse a scene file
00088 // add to existing scene
00089 
00090 scScenePtr ParseSCFile(const Char *filename)
00091 {
00092     FILE        *fp;
00093     scScenePtr  result;
00094     
00095     if ((fp = fopen(filename, "r")) == NULL)
00096     {
00097         cerr << "Cannot access " << filename << endl;
00098         return(0);
00099     }
00100 
00101     result = slBeginObject(filename);
00102     slCamera();
00103 
00104     Bool bad;
00105     lc = 1;
00106     char *word = NULL;
00107 
00108     for (;;) {
00109     if (feof(fp)) strcpy(word, "end");
00110     else word = fread_word(fp);
00111     bad = false;
00112 
00113     switch (word[0]) {
00114     case '#':           // comment
00115         fread_to_eol(fp);
00116         break;
00117 
00118     case '/':           // comment
00119         fread_to_eol(fp);
00120         break;
00121 
00122     case 'a':
00123         if (!strcmp(word, "ambient")) {
00124 //      ambient = fread_Vector(fp);
00125 //      ambient *= fread_number(fp);
00126         fread_Vector(fp);
00127         fread_number(fp);
00128         }
00129         else bad = true;
00130         break;
00131     case 'b':
00132         if (!strcmp(word, "background")) {
00133 //      background = fread_Vector(fp);
00134 //      background *= fread_number(fp);
00135         fread_Vector(fp);
00136         fread_number(fp);
00137         }
00138         else bad = true;
00139         break;
00140     case 'd':
00141         if (!strcmp(word, "diffuse")) {
00142 /*
00143         cur_material().color = fread_Vector(fp);
00144         cur_material().kdiffrefl = fread_number(fp);
00145         cur_material().kspecrefl = 0.;
00146         cur_material().kspectran = 0.;
00147         cur_material().exponent = 0.;
00148         cur_material().indexrefr = 1.;
00149         cur_material().kemission = 0.;
00150         new_material = true;
00151 */
00152         Colour c = fread_Colour(fp);
00153         slColour(c * fread_number(fp));
00154         
00155         }
00156         else if (!strcmp(word, "diffspec")) {
00157 /*
00158         cur_material().color = fread_Vector(fp);
00159         cur_material().kdiffrefl = fread_number(fp);
00160         cur_material().kspecrefl = fread_number(fp);
00161         cur_material().kspectran = fread_number(fp);
00162         cur_material().exponent = fread_number(fp);
00163         cur_material().indexrefr = fread_number(fp);
00164         cur_material().kemission = 0.;
00165         new_material = true;
00166 */
00167         Colour c = fread_Colour(fp);
00168         slColour(c * fread_number(fp));
00169         
00170         fread_number(fp);
00171         fread_number(fp);
00172         fread_number(fp);
00173         fread_number(fp);
00174         }
00175         else bad = true;
00176         break;
00177     case 'e':
00178         if (!strcmp(word, "emissive")) {
00179 /*
00180         cur_material().color = fread_Vector(fp);
00181         cur_material().kdiffrefl = 0.;
00182         cur_material().kspecrefl = 0.;
00183         cur_material().kspectran = 0.;
00184         cur_material().exponent = 0.;
00185         cur_material().indexrefr = 1.;
00186         cur_material().kemission = fread_number(fp);
00187         new_material = true;
00188 */
00189         Colour c = fread_Colour(fp);
00190         slEmittance(c * fread_number(fp));
00191 
00192         }
00193         else if (!strcmp(word, "end")) {
00194         cout << "Completed reading the scene\n";
00195         fclose(fp);
00196         slEndObject();
00197         return(result);
00198         }
00199         else bad = true;
00200         break;
00201     case 'g':
00202         if (!strcmp(word, "gpop")) {
00203 
00204 /*      if (!gstack.first()->next()) {
00205             cerr << "Scene Error, line " << lc
00206             << ": Can't pop top level gstate" << endl;
00207             exit(1);
00208         }
00209         gstack.pop();
00210         cout << "popped stack" << endl;
00211         cout << gstack.first();
00212 */
00213         slEndObject();
00214 
00215         }
00216         else if (!strcmp(word, "gpush")) {
00217 
00218 /*      gstack.dup();
00219         // dup() copies the material structure, light list
00220         // header, and matrix stack headers.
00221         // At this point, cur_matrix() points to the same
00222         // matrix as before the dup().
00223 
00224         // Set up matrix stack in new Gstate so that it contains a
00225         // copy of current matrix, and nothing else.
00226         // That way, if someone does too many pops, they'll get
00227         // an error message.
00228         // (push and pop must be nested within gpush, gpop)
00229         Matrix_item *m = new Matrix_item(*cur_matrix());
00230         gstack.first()->matrix_stack.init();
00231         gstack.first()->matrix_stack.push(*m);
00232 */
00233 
00234         slBeginObject("bob");
00235     
00236         }
00237         else bad = true;
00238         break;
00239     case 'l':
00240         if (!strcmp(word, "lookat")) {
00241         Vec3d from = fread_Vector(fp);
00242         Vec3d to = fread_Vector(fp);
00243         Vec3d up = fread_Vector(fp);
00244         Vec3d vec = to-from;
00245 
00246         if (up[2] > 0)
00247             slTransform(Rotation(vl_x, -vl_pi / 2.0));
00248         else if (up[1] > 0)
00249             slTransform(Rotation(vl_z, vl_pi / 2.0));
00250         
00251 /*      double alpha;
00252         if (vec[1]!=0 || vec[2]!=0) alpha = atan2(-vec[1], -vec[2]);
00253         else alpha = 0.;
00254         double beta
00255             = atan2(vec[0], sqrt(vec[1]*vec[1] + vec[2]*vec[2]));
00256         Matrix rm;
00257         rm.MakeUnit();  // identity
00258         rm.rotate('x', -alpha);
00259         rm.rotate('y', -beta);
00260 
00261         double gamma
00262             = atan2(up[0]*rm[0][0]+up[1]*rm[1][0]+up[2]*rm[2][0],
00263                 up[0]*rm[0][1]+up[1]*rm[1][1]+up[2]*rm[2][1]);
00264         cur_matrix()->rotate('z', gamma);
00265         cur_matrix()->rotate('y', beta);
00266         cur_matrix()->rotate('x', alpha);
00267         cur_matrix()->translate(-from[0], -from[1], -from[2]);
00268 */
00269 
00270 
00271         }
00272         else bad = true;
00273         break;
00274     case 'p':
00275         if (!strcmp(word, "persp")) {
00276             fread_number(fp);
00277             fread_number(fp);
00278         }
00279         else if (!strcmp(word, "pointlight")) {
00280 //      Light_item *light = new Light_item;
00281         Vec3d pos = fread_Vector(fp);
00282 /*      light->position = transform33(*cur_matrix(), pos);
00283         light->color = fread_Vector(fp);
00284         light->color *= fread_number(fp);
00285         cur_lights().append(*light);
00286 */
00287         fread_Vector(fp);
00288         fread_number(fp);
00289         }
00290         else if (!strcmp(word, "poly3") || !strcmp(word, "poly2")) {
00291         int poly3 = !strcmp(word, "poly3");
00292         int nvert = (int)fread_number(fp);
00293 
00294         if (nvert<3) {
00295             cerr << "Scene Error, line " << lc
00296             << ": poly needs >=3 vertices." << endl;
00297             exit(1);
00298         }
00299 //      Polygon *p = new Polygon;
00300         Vec3d point;
00301         int i;
00302 
00303         slPointList();
00304         
00305         for (i=0; i<nvert; i++) {
00306             point[0] = fread_number(fp);
00307             point[1] = fread_number(fp);
00308             if (poly3) point[2] = fread_number(fp);
00309             else point[2] = 0.;
00310 //          point = transform33(*cur_matrix(), point);
00311 //          p->append_vertex(point);
00312 
00313             slPoint(point);
00314         }
00315         slPoly();
00316         
00317 //      p->precompute();    // set plane & edge equations
00318 //      append_prim(*p);
00319         }
00320         else if (!strcmp(word, "pop")) {
00321 /*      if (!cur_matrix()->next()) {
00322             cerr << "Scene Error, line " << lc
00323             << ": Attempt to pop last matrix on stack" << endl;
00324             exit(1);
00325         }
00326         gstack.first()->matrix_stack.pop();
00327 */
00328 
00329             slEndObject();
00330         }
00331         else if (!strcmp(word, "push")) {
00332 //      gstack.first()->matrix_stack.dup();
00333             slBeginObject("bob");
00334         }
00335         else bad = true;
00336         break;
00337     case 'r':
00338         if (!strcmp(word, "rotate")) {
00339         char *axis = fread_word(fp);
00340         double angle = fread_number(fp);
00341         if (!axis[1] && (axis[0]=='x' || axis[0]=='y' || axis[0]=='z'))
00342 //          cur_matrix()->rotate(axis[0], angle*M_PI/180.);
00343             slTransform(Rotation(vl_axis(axis[0] - 'x'), DegsToRads(angle)));
00344         else {
00345             cerr << "Scene Error, line " << lc
00346             << ": Illegal rotate axis (" << axis << ")" << endl;
00347             exit(1);
00348         }
00349         }
00350         else if (!strcmp(word, "rotgen")) {
00351             Vec3d v = fread_Vector(fp);
00352             double angle = fread_number(fp);
00353             slTransform(Rotation(v, DegsToRads(angle)));
00354         }
00355         else bad = true;
00356         break;
00357     case 's':
00358         if (!strcmp(word, "scale")) {
00359             double sx, sy, sz;
00360             sx = fread_number(fp);
00361             sy = fread_number(fp);
00362             sz = fread_number(fp);
00363             slTransform(Scale(Vector(sx, sy, sz)));
00364         }
00365         else if (!strcmp(word, "screensize")) {
00366 /*
00367         double dscale = (double)scale / 100.0;
00368         double sx = dscale * fread_number(fp);
00369         double sy = dscale * fread_number(fp);
00370         double sz = dscale * fread_number(fp);
00371         width = (int)sx;
00372         height = (int)sy;
00373         cur_matrix()->scale(sx/2.0, -sy/2.0, sz/2);
00374         cur_matrix()->translate(1, -1, 0);
00375 */
00376 
00377         fread_number(fp);
00378         fread_number(fp);
00379         fread_number(fp);
00380         
00381         }
00382         else if (!strcmp(word, "sphere")) {
00383         Vec3d center = fread_Vector(fp);
00384         double radius = fread_number(fp);
00385         }
00386         else bad = true;
00387         break;
00388     case 't':
00389         if (!strcmp(word, "translate")) {
00390         double tx, ty, tz;
00391         tx = fread_number(fp);
00392         ty = fread_number(fp);
00393         tz = fread_number(fp);
00394 
00395         slTransform(Shift(Vector(tx, ty, tz)));
00396         }
00397         else bad = true;
00398         break;
00399     case 'w':
00400         if (!strcmp(word, "world_space")) {
00401         // currently, all matrices in matrix stacks transform to screen
00402         // space
00403 
00404         // save world-to-screen transform
00405 //      world_to_screen = *cur_matrix();
00406 
00407         // Step through matrix stacks of all previous graphics states
00408         // and premultiply their matrices by screen_to_world space,
00409         // so that all matrices henceforth transform to world space.
00410 
00411         // We could just flush all previous graphics states and all
00412         // matrix stacks, but that is less elegant.
00413         // Doing it this way allows you to place geometry relative to
00414         // camera, and even in screen space.
00415 //      Gstate_item *gs;
00416 //      Matrix_item *m;
00417 //      Matrix sw = inv(world_to_screen);
00418 //      for (gs=gstack.first(); gs; gs=gs->next())
00419 //          for (m=gs->matrix_stack.first(); m; m=m->next())
00420 //          *m = sw * *m;       // 4x4 matrix multiply
00421 
00422         // cur_matrix() is identity+roundoff at this point
00423 //      cur_matrix()->MakeUnit();   // to eliminate the roundoff
00424                         // (just being fussy)
00425         }
00426         else bad = true;
00427         break;
00428     case 'x':
00429         if (!strcmp(word, "xyzrange")) {
00430 //      double xn, xf, yn, yf, zn, zf;
00431         /*xn =*/ fread_number(fp);
00432         /*xf =*/ fread_number(fp);
00433         /*yn =*/ fread_number(fp);
00434         /*yf =*/ fread_number(fp);
00435         /*zn =*/ fread_number(fp);
00436         /*zf =*/ fread_number(fp);
00437 //      cur_matrix()->scale(2./(xf-xn), 2./(yf-yn), 2./(zf-zn));
00438 //      cur_matrix()->translate((xf+xn)/-2., (yf+yn)/-2., (zf+zn)/-2.);
00439         }
00440         else bad = true;
00441         break;
00442     case 'z':
00443         if (!strcmp(word, "zrange")) {
00444         //double zn, zf;
00445         /*zn =*/ fread_number(fp);
00446         /*zf =*/ fread_number(fp);
00447 //      cur_matrix()->translate(0., 0., (zf+zn)/(zf-zn));
00448 //      cur_matrix()->scale(1., 1., -2./(1./zn-1./zf));
00449         }
00450         else bad = true;
00451         break;
00452     default:
00453         bad = true;
00454         break;
00455     }
00456 
00457     if (bad) {
00458         cerr << "Scene Error, line " << lc
00459         << ": bad keyword (" << word << ")." << endl;
00460         exit(1);
00461     }
00462     }
00463 }
00464 
00465 #endif

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