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
00016
00017
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
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
00117 if (fileName.size() < 7 || fileName.substr(fileName.size() - 6) != ".scene")
00118 throw std::invalid_argument("Unknown file name extension in \"" + fileName + "\"");
00119
00120
00121 std::ifstream file(fileName.c_str());
00122 if (!file)
00123 THROW_SPE("Could not open scene file");
00124
00125
00126 std::string type;
00127
00128
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
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
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
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
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
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
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
00257 if (parseScene)
00258 clear();
00259 LOG("Completed scene file parsing\n");
00260 }
00261
00262
00263
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)
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)
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