00001 /* 00002 File: ParseSL.cc 00003 00004 Function: Parser for GCL's scene language 00005 00006 Author: Andrew Willmott 00007 00008 Notes: 00009 */ 00010 00011 #include "gcl/ParseSL.h" 00012 #include "gcl/Readers.h" 00013 #include "gcl/SceneObjects.h" 00014 #include "gcl/Avars.h" 00015 #include "gcl/SceneLang.h" 00016 #include "gcl/PolyLib.h" 00017 00018 #define INFO_COUT cerr 00019 00020 00021 // --- SL Parser -------------------------------------------------------------- 00022 00023 // this is GCL's native scene language. 00024 00025 static FileName gSLReadPath; 00026 00027 struct SLParseState 00028 { 00029 FileName readPath; 00030 Int version; 00031 }; 00032 00033 const Int SL_CURRENT_VERSION = 3; 00034 00035 scObject *ParseSLObject(istream &s) 00036 // XXX Need to tokenize using a Hash sometime. This is tres inefficient... 00037 { 00038 String str; 00039 scObject *object; 00040 Vector v; 00041 GCLReal r; 00042 00043 // get next 'token' 00044 str.ReadWord(s); 00045 00046 // handle comments 00047 while (str[0] == '#') 00048 { 00049 str.ReadLine(s); 00050 if (!s) 00051 return(0); 00052 str.ReadWord(s); 00053 } 00054 00055 // attributes 00056 if (str == "camera") 00057 object = new scCamera; 00058 else if (str == "texture") 00059 object = new scTexture; 00060 else if (str == "avar") 00061 { 00062 str.ReadWord(s); 00063 00064 if (str == "colour" || str == "reflectance") 00065 object = new scAvarColour(Avar("dummy"), vl_z); 00066 else if (str == "emittance") 00067 object = new scAvarEmittance(Avar("dummy"), vl_z); 00068 else if (str == "shift") 00069 object = new scAvarShift(Avar("dummy"), vl_z); 00070 else if (str == "rotate") 00071 object = new scAvarRotation(Avar("dummy"), vl_z); 00072 else if (str == "scale") 00073 object = new scAvarScale(Avar("dummy"), vl_z); 00074 else if (str == "scalef") 00075 object = new scAvarScalef(Avar("dummy")); 00076 else if (str == "switch") 00077 object = new scAvarSwitch(Avar("dummy")); 00078 else 00079 { 00080 INFO_COUT << "Unknown avar type: " << str << endl; 00081 return(0); 00082 } 00083 } 00084 else if (str == "points") 00085 object = new scPoints; 00086 else if (str == "coords") 00087 object = new scCoords; 00088 else if (str == "colours") 00089 object = new scColours; 00090 else if (str == "normals") 00091 object = new scNormals; 00092 00093 else if (str == "indexes" || str == "vertices") 00094 object = new scIndexes(aPointIndexes); 00095 else if (str == "surfaces" || str == "s_indexes" || str == "c_indexes") 00096 object = new scIndexes(aColourIndexes); 00097 else if (str == "n_indexes") 00098 object = new scIndexes(aNormalIndexes); 00099 else if (str == "t_indexes") 00100 object = new scIndexes(aCoordIndexes); 00101 else if (str == "faces") 00102 object = new scIndexes(aFaceIndexes); 00103 else if (str == "face") 00104 { 00105 // XXX face [i1 i2 i3] (-normals [])... 00106 } 00107 00108 else if (str == "colour" || str == "reflectance") 00109 object = new scColour; 00110 else if (str == "emittance") 00111 object = new scEmittance; 00112 00113 // transforms 00114 else if (str == "transform") 00115 object = new scTransform; 00116 else if (str == "shift") 00117 { 00118 object = new scTransform; 00119 s >> v; 00120 *(scTransform*) object = Shift(v); 00121 return(object); 00122 } 00123 else if (str == "rotate") 00124 { 00125 object = new scTransform; 00126 s >> v >> r; 00127 *(scTransform*) object = Rotation(v, DegsToRads(r)); 00128 return(object); 00129 } 00130 else if (str == "scale") 00131 { 00132 object = new scTransform; 00133 s >> v; 00134 *(scTransform*) object = Scale(v); 00135 return(object); 00136 } 00137 else if (str == "scalef") 00138 { 00139 object = new scTransform; 00140 s >> r; 00141 *(scTransform*) object = Scale(Vector(r, r, r)); 00142 return(object); 00143 } 00144 else if (str == "set") 00145 { 00146 // XXX should set rendering state info at some stage. at the 00147 // moment we just have this hardcoded monstrosity 00148 str.ReadWord(s); 00149 if (str == "tesselation") 00150 s >> PolyLib::numTesselations; 00151 else 00152 INFO_COUT << "unrecognized variable " << str << endl; 00153 00154 str.ReadLine(s); 00155 return(ParseSLObject(s)); 00156 } 00157 00158 // primitives 00159 else if (str == "poly" || str == "polys" || str == "mesh") 00160 object = Clone(slGetLibrary()->Member("poly")); 00161 else if (str == "object") 00162 object = Clone(slGetLibrary()->Member("group")); 00163 else if (str == "end") 00164 return(0); 00165 // external scene files 00166 else if (str == "coloursfile") 00167 { 00168 scColours *clrs = new scColours; 00169 str.ReadString(s); 00170 clrs->ReadFile(str); 00171 return(clrs); 00172 } 00173 else if (str == "objectfile") 00174 { 00175 scScenePtr scene; 00176 FileName filename(gSLReadPath); 00177 00178 str.ReadString(s); 00179 filename.SetRelPath(SubstituteEnvVars(str)); 00180 INFO_COUT << "including " << filename.GetPath() << endl; 00181 scene = SceneReader::Load(filename); 00182 if (scene) 00183 { 00184 while (!IsEndOfLine(s)) 00185 { 00186 str.ReadWord(s); 00187 if (str == "-zy" || str == "-zup") 00188 scene->Apply(Rotation(vl_x, -vl_halfPi)); 00189 else if (str == "-unit") 00190 scene->Normalise(); 00191 else 00192 INFO_COUT << "objectfile: unrecognized option: " 00193 << str << endl; 00194 } 00195 return(scene); 00196 } 00197 else 00198 { 00199 str.ReadLine(s); 00200 return(ParseSLObject(s)); 00201 } 00202 } 00203 // add object definition to library 00204 else if (str == "define") 00205 { 00206 scGroup *group; 00207 00208 group = (scGroup *) Clone(slGetLibrary()->Member("group")); 00209 group->Parse(s); 00210 slGetLibrary()->AddMember(group); 00211 00212 return(ParseSLObject(s)); 00213 } 00214 // retrieve object from library 00215 else if (object = slGetLibrary()->Member(str)) 00216 { 00217 object = Clone(object); 00218 if (!object->IsGroup()) 00219 object->Parse(s); 00220 return(object); 00221 } 00222 // give up. 00223 else 00224 { 00225 INFO_COUT << "Unknown token: " << str << endl; 00226 return(0); 00227 } 00228 00229 object->Parse(s); 00230 00231 return(object); 00232 } 00233 00234 scScenePtr ParseSLFile(const Char *filename) 00235 { 00236 ifstream inFile; 00237 scScenePtr result; 00238 FileName savePath; 00239 SLParseState state; 00240 00241 inFile.open(filename); 00242 if (!inFile) 00243 { 00244 INFO_COUT << "Couldn't read file " << filename << endl; 00245 return(0); 00246 } 00247 00248 savePath = gSLReadPath; 00249 gSLReadPath.SetPath(filename); 00250 // state.readPath.SetPath(filename); 00251 // state.version = SL_CURRENT_VERSION; 00252 result = (scScenePtr) ParseSLObject(inFile); 00253 gSLReadPath = savePath; 00254 00255 inFile.close(); 00256 return(result); 00257 } 00258