src/SceneBuilder.cpp

Go to the documentation of this file.
00001 
00002 #include <stdexcept>
00003 #include <fstream>
00004 #include <vector>
00005 
00006 #include "SceneBuilder.h"
00007 #include "Scene.h"
00008 #include "Camera.h"
00009 #include "defines.h"
00010 #include "SceneBuilderFactories.h"
00011 #include "QuotedString.h"
00012 #include "Animator.h"
00013 
00014 
00015 // FIXME detect commas between numbers (like resolution in cameras)
00016 
00017 // macro for throwing parse exception
00018 #define THROW_SPE(x) {  LOG("Throwing SceneParseException\n\n"); \
00019                         throw SceneParseException(mFileName, mLineNr, (x)); \
00020                      }
00021 
00022 
00025 SceneBuilder::SceneBuilder()
00026     : mFileName(),
00027         mLine(),
00028         mLineNr(-1),
00029         mLights(),
00030         mTextures(),
00031         mShaders(),
00032         mObjects(),
00033         mCameraParsers(),
00034         mLightParsers(),
00035         mShaderParsers(),
00036         mObjectParsers(),
00037         mTransformators(),
00038         mPhysicsParsers()
00039 {
00040     // init all parsers
00041     mCameraParsers.push_back(new PerspectiveCameraFactory());
00042     mCameraParsers.push_back(new DepthOfFieldCameraFactory());
00043 
00044     mLightParsers.push_back(new PointLightFactory());
00045     mLightParsers.push_back(new QuadAreaLightFactory());
00046 
00047     mShaderParsers.push_back(new CombineShaderFactory(mShaders, mTextures));
00048     mShaderParsers.push_back(new CloudShaderFactory(mTextures));
00049     mShaderParsers.push_back(new MirrorShaderFactory(mTextures));
00050     mShaderParsers.push_back(new PhongShaderFactory(mTextures));
00051     mShaderParsers.push_back(new TransparentShaderFactory());
00052     mShaderParsers.push_back(new RefractiveShaderFactory(mTextures));
00053     mShaderParsers.push_back(new CookTorranceShaderFactory(mTextures));
00054     mShaderParsers.push_back(new WoodShaderFactory(mTextures));
00055 
00056     mObjectParsers.push_back(new OBJObjectFactory(mShaders));
00057     mObjectParsers.push_back(new SphereObjectFactory(mShaders));
00058     mObjectParsers.push_back(new CopyObjectFactory(mObjects));
00059 
00060     mTransformators.push_back(new Translator(mObjects));
00061     mTransformators.push_back(new Rotator(mObjects));
00062     mTransformators.push_back(new Scaler(mObjects));
00063 
00064     mPhysicsParsers.push_back(new PhysicsStepParser(mObjects));
00065 }
00066 
00067 
00070 SceneBuilder::~SceneBuilder()
00071 {
00072     for (unsigned int i = 0; i < mCameraParsers.size(); i++)
00073         delete mCameraParsers[i];
00074 
00075     for (unsigned int i = 0; i < mLightParsers.size(); i++)
00076         delete mLightParsers[i];
00077 
00078     for (unsigned int i = 0; i < mShaderParsers.size(); i++)
00079         delete mShaderParsers[i];
00080 
00081     for (unsigned int i = 0; i < mObjectParsers.size(); i++)
00082         delete mObjectParsers[i];
00083 
00084     for (unsigned int i = 0; i < mTransformators.size(); i++)
00085         delete mTransformators[i];
00086 
00087     for (unsigned int i = 0; i < mPhysicsParsers.size(); i++)
00088         delete mPhysicsParsers[i];
00089 }
00090 
00091 
00102 void SceneBuilder::load(Scene &             scene,
00103                         Camera *&           camera,
00104                         const std::string & fileName,
00105                         bool                parseScene)
00106 {
00107     if (parseScene)
00108     {
00109         clear();
00110     }
00111     mFileName   = fileName;
00112     mLineNr     = 0;
00113     camera      = NULL;
00114     LOG("Trying to load scene from \"" << fileName << "\"");
00115 
00116     // test file name extension
00117     if (fileName.size() < 7 || fileName.substr(fileName.size() - 6) != ".scene")
00118         throw std::invalid_argument("Unknown file name extension in \"" + fileName + "\"");
00119 
00120     // open file
00121     std::ifstream file(fileName.c_str());
00122     if (!file)
00123         THROW_SPE("Could not open scene file");
00124 
00125     // parse the file
00126     std::string type;
00127 
00128     // scene section
00129     type = nextOperator(file);
00130     if (type != "scene:")
00131         THROW_SPE("Found unexpected token \"" + type + "\" instead of scene: section");
00132     LOG("Found scene: section");
00133     if (parseScene)
00134     {
00135         bool foundscene = false;
00136         while (!file.eof())
00137         {
00138             type = nextOperator(file);
00139             if (type == "scene")
00140             {
00141                 foundscene = true;
00142                 makeScene(scene);
00143             }
00144             else if (type == "perspectivecamera" || type == "depthoffieldcamera")
00145             {
00146                 if (camera)
00147                     THROW_SPE("Multiple camera definitions in scene: section");
00148                 camera = makeCamera(type);
00149                 LOG("Added new camera of type \"" << type << "\"");
00150             }
00151             else if (type == "include")
00152             {
00153                 QuotedString includefile;
00154                 mLine >> includefile;
00155                 Camera *    tmpc;
00156                 std::string tmpf = mFileName;
00157                 int         tmpfn = mLineNr;
00158                 LOG("Found include statement, including \"" << includefile.str() << "\"");
00159                 load(scene, tmpc, includefile.str(), false);
00160                 mFileName   = tmpf;
00161                 mLineNr     = tmpfn;
00162             }
00163             else if (type == "lights:" || type == "")
00164                 break;
00165             else
00166                 THROW_SPE("Unknown statement \"" + type + "\"");
00167         }
00168         if (!foundscene)
00169             THROW_SPE("No \"scene\" statement in scene: section");
00170         if (!camera)
00171             THROW_SPE("No \"perspectivecamera\" or \"depthoffieldcamera\" statement in scene: section");
00172     }
00173     else
00174     {
00175         LOG("Skipping scene: section as requested");
00176         while (!file.eof())
00177         {
00178             type = nextOperator(file);
00179             if (type == "lights:" || type == "")
00180                 break;
00181         }
00182     }
00183 
00184     // lights section
00185     if (type != "lights:")
00186         THROW_SPE("Found unexpected token \"" + type + "\" instead of lights: section");
00187     LOG("Found lights: section");
00188     while (!file.eof())
00189     {
00190         type = nextOperator(file);
00191         if (type == "textures:" || type == "")
00192             break;
00193         addLight(scene, type);
00194     }
00195 
00196     // textures section
00197     if (type != "textures:")
00198         THROW_SPE("Found unexpected token \"" + type + "\" instead of textures: section");
00199     LOG("Found textures: section");
00200     while (!file.eof())
00201     {
00202         type = nextOperator(file);
00203         if (type == "shaders:" || type == "")
00204             break;
00205         addTexture(scene, type);
00206     }
00207 
00208     // shaders section
00209     if (type != "shaders:")
00210         THROW_SPE("Found unexpected token \"" + type + "\" instead of shaders: section");
00211     LOG("Found shaders: section");
00212     while (!file.eof())
00213     {
00214         type = nextOperator(file);
00215         if (type == "objects:" || type == "")
00216             break;
00217         addShader(scene, type);
00218     }
00219 
00220     // objects section
00221     if (type != "objects:")
00222         THROW_SPE("Found unexpected token \"" + type + "\" instead of objects: section");
00223     LOG("Found objects: section");
00224     while (!file.eof())
00225     {
00226         type = nextOperator(file);
00227         if (type == "initialization:" || type == "")
00228             break;
00229         addObject(scene, type);
00230     }
00231 
00232     // initialization section
00233     if (type != "initialization:")
00234         THROW_SPE("Found unexpected token \"" + type + "\" instead of initialization: section");
00235     LOG("Found initialization: section");
00236     while (!file.eof())
00237     {
00238         type = nextOperator(file);
00239         if (type == "physics:" || type == "")
00240             break;
00241         doInit(type);
00242     }
00243 
00244     // physics section
00245     if (type != "physics:")
00246         THROW_SPE("Found unexpected token \"" + type + "\" instead of physics: section");
00247     LOG("Found physics: section");
00248     while (!file.eof())
00249     {
00250         type = nextOperator(file);
00251         if (type == "")
00252             break;
00253         addPhysicsStep(scene, type);
00254     }
00255 
00256     // cleanup
00257     if (parseScene)
00258         clear();
00259     LOG("Completed scene file parsing\n");
00260 }
00261 
00262 
00263 /* Clear internal structures
00264  */
00265 void SceneBuilder::clear()
00266 {
00267     mFileName   = "";
00268     mLine.str("");
00269     mLineNr     = -1;
00270     mLights.clear();
00271     mTextures.clear();
00272     mShaders.clear();
00273     mObjects.clear();
00274 }
00275 
00276 
00283 std::string SceneBuilder::nextOperator(std::istream & ifile)
00284 {
00285     std::string s;
00286     while (!ifile.eof() && (s == "" || s == "#"))
00287     {
00288         ifile.clear();
00289         std::getline(ifile, s);
00290         mLine.clear();
00291         mLine.str(s);
00292         mLine >> std::ws >> s;
00293         mLine.clear();
00294         mLineNr++;
00295     }
00296     return s;
00297 }
00298 
00299 
00305 void SceneBuilder::makeScene(Scene & scene)
00306 {
00307     try
00308     {
00309         RGBAColor col;
00310         bool b = false;
00311 
00312         mLine.clear();
00313         mLine >> col >> std::ws >> std::boolalpha >> b;
00314         mLine.clear();
00315         
00316         LOG("scene cast shadows: " << b);
00317 
00318         scene.setBgColor(col);
00319         scene.setCastShadows(b);
00320     }
00321     catch (std::exception & e)
00322     {
00323         mLine.clear();
00324         THROW_SPE(e.what());
00325     }
00326 }
00327 
00328 
00334 Camera * SceneBuilder::makeCamera(const std::string & type) // FIXME use res-x and res-y from parameters
00335 {
00336     try
00337     {
00338         Camera * cam = NULL;
00339         for (unsigned int i = 0; i < mCameraParsers.size(); i++)
00340         {
00341             cam = mCameraParsers[i]->create(type, mLine);
00342             if (cam)
00343                 return cam;
00344         }
00345     }
00346     catch (std::exception & e)
00347     {
00348         mLine.clear();
00349         THROW_SPE(e.what());
00350     }
00351     return NULL;
00352 }
00353 
00354 
00361 void SceneBuilder::addLight(Scene & scene, const std::string & type)
00362 {
00363     try
00364     {
00365         std::string name;
00366         mLine.clear();
00367         mLine >> std::ws >> name >> std::ws;
00368         mLine.clear();
00369 
00370         Light * lt = NULL;
00371         for (unsigned int i = 0; i < mLightParsers.size(); i++)
00372         {
00373             lt = mLightParsers[i]->create(type, mLine);
00374             if (lt)
00375             {
00376                 Light * oldLt = mLights[name];
00377                 if (oldLt)
00378                 {
00379                     delete lt;
00380                     THROW_SPE("Light name \"" + name + "\" is already in use");
00381                 }
00382                 mLights[name] = lt;
00383                 scene.addLight(lt);
00384                 break;
00385             }
00386         }
00387         if (!lt)
00388             THROW_SPE("Unknown statement \"" + type + "\"");
00389     }
00390     catch (std::exception & e)  // FIXME this doesnt work for a strange reason
00391     {
00392         mLine.clear();
00393         THROW_SPE(e.what());
00394     }
00395 }
00396 
00397 
00404 void SceneBuilder::addTexture(Scene & scene, const std::string & type)
00405 {
00406     Texture2DFactory texParser;
00407     try
00408     {
00409         std::string name;
00410         mLine.clear();
00411         mLine >> std::ws >> name >> std::ws;
00412         mLine.clear();
00413 
00414         Texture * tx = NULL;
00415         tx = texParser.create(type, mLine);
00416         if (tx)
00417         {
00418             Texture * oldTx = mTextures[name];
00419             if (oldTx)
00420             {
00421                 delete tx;
00422                 THROW_SPE("Texture name \"" + name + "\" is already in use");
00423             }
00424             mTextures[name] = tx;
00425             scene.addTexture(tx);
00426         }
00427         else
00428             THROW_SPE("Unknown statement \"" + type + "\"");
00429     }
00430     catch (std::exception & e)
00431     {
00432         mLine.clear();
00433         THROW_SPE(e.what());
00434     }
00435 }
00436 
00437 
00444 void SceneBuilder::addShader(Scene & scene, const std::string & type)
00445 {
00446     try
00447     {
00448         std::string name;
00449         mLine.clear();
00450         mLine >> std::ws >> name >> std::ws;
00451         mLine.clear();
00452 
00453         Shader * sh = NULL;
00454         for (unsigned int i = 0; i < mShaderParsers.size(); i++)
00455         {
00456             sh = mShaderParsers[i]->create(type, mLine, &scene);
00457             if (sh)
00458             {
00459                 Shader * oldSh = mShaders[name];
00460                 if (oldSh)
00461                 {
00462                     delete sh;
00463                     THROW_SPE("Shader name \"" + name + "\" is already in use");
00464                 }
00465                 mShaders[name] = sh;
00466                 scene.addShader(sh);
00467                 break;
00468             }
00469         }
00470         if (!sh)
00471             THROW_SPE("Unknown statement \"" + type + "\"");
00472     }
00473     catch (std::exception & e)
00474     {
00475         mLine.clear();
00476         THROW_SPE(e.what());
00477     }
00478 }
00479 
00480 
00487 void SceneBuilder::addObject(Scene & scene, const std::string & type)
00488 {
00489     try
00490     {
00491         std::string name;
00492         mLine.clear();
00493         mLine >> std::ws >> name >> std::ws;
00494         mLine.clear();
00495 
00496         Object * obj = NULL;
00497         for (unsigned int i = 0; i < mObjectParsers.size(); i++)
00498         {
00499             obj = mObjectParsers[i]->create(type, mLine);
00500             if (obj)
00501             {
00502                 Object * oldObj = mObjects[name];
00503                 if (oldObj)
00504                 {
00505                     delete obj;
00506                     THROW_SPE("Object name \"" + name + "\" is already in use");
00507                 }
00508                 mObjects[name] = obj;
00509                 obj->setName(name);
00510                 scene.addObject(obj);
00511                 LOG("Added object \"" << name << "\"\n");
00512                 break;
00513             }
00514         }
00515         if (!obj)
00516             THROW_SPE("Unknown statement \"" + type + "\"");
00517     }
00518     catch (std::exception & e)
00519     {
00520         mLine.clear();
00521         THROW_SPE(e.what());
00522     }
00523 }
00524 
00525 
00531 void SceneBuilder::doInit(const std::string & type)
00532 {
00533     try
00534     {
00535         bool done = false;
00536         for (unsigned int i = 0; i < mTransformators.size(); i++)
00537         {
00538             done = mTransformators[i]->transform(type, mLine);
00539             if (done)
00540                 break;
00541         }
00542         if (!done)
00543             THROW_SPE("Unknown statement \"" + type + "\"");
00544     }
00545     catch (std::exception & e)
00546     {
00547         mLine.clear();
00548         THROW_SPE(e.what());
00549     }
00550 }
00551 
00552 
00559 void SceneBuilder::addPhysicsStep(Scene & scene, const std::string & type)
00560 {
00561     try
00562     {
00563         mLine.clear();
00564         Animator * ps = NULL;
00565         for (unsigned int i = 0; i < mPhysicsParsers.size(); i++)
00566         {
00567             ps = mPhysicsParsers[i]->create(type, mLine);
00568             if (ps)
00569             {
00570                 scene.addAnimator(ps);
00571                 break;
00572             }
00573         }
00574         if (!ps)
00575             THROW_SPE("Unknown statement \"" + type + "\"");
00576     }
00577     catch (std::exception & e)
00578     {
00579         mLine.clear();
00580         THROW_SPE(e.what());
00581     }
00582 }
00583 
00584 

Generated on Fri Feb 1 00:01:42 2008 for Grayfall by  doxygen 1.5.1