SceneXML.cc

00001 /**********************************************************************
00002  * blaRAY -- photon mapper/raytracer
00003  * (C) 2008 by Tomasz bla Fortuna <bla@thera.be>, <bla@af.gliwice.pl>
00004  *
00005  * This program is free software: you can redistribute it and/or modify
00006  * it under the terms of the GNU General Public License as published by
00007  * the Free Software Foundation, either version 3 of the License, or
00008  * any later version.
00009  *
00010  * See Docs/LICENSE
00011  *********************/
00012 
00013 #include <stdexcept>
00014 #include <iostream>
00015 
00016 #include "World/Scene.hh"
00017 
00018 namespace World {
00020         template<typename T>
00021         static std::string ToStr(const T &var) {
00022                 std::ostringstream tmp;
00023                 tmp << var;
00024                 return tmp.str();
00025         }
00026 
00028         static Double ToDouble(const std::string &str)
00029         {
00030                 std::stringstream os(str);
00031                 Double a; 
00033                 os >> a;
00034                 return a;
00035         }
00036 
00038         class XMLError : public std::runtime_error {
00039         public:
00041                 XMLError(xmlNodePtr Node, const std::string &Desc)
00042                         : std::runtime_error(
00043                                 "On line " + ToStr(xmlGetLineNo(Node)) +
00044                                 ": " + Desc)
00045                 {
00046                 }
00047 
00049                 XMLError(const std::string &Desc)
00050                         : std::runtime_error(Desc)
00051                 {
00052                 }
00053         };
00054 
00057         static Bool IsDouble(const std::string &str)
00058         {
00059                 Bool WasDot = false;
00060                 if (str.length() == 0)
00061                         return false;
00062                 for (UInt i = 0U;
00063                      i != str.length();
00064                      i++) {
00065                         if (str[i] == '-' && i == 0)
00066                                 continue;
00067 
00068                         if (str[i] == '.' && WasDot == false) {
00069                                 WasDot = true;
00070                                 continue;
00071                         }
00072                         if (str[i] < '0' || str[i] > '9')
00073                                 return false;
00074                 }
00075                 return true;
00076         }
00077 
00079         static std::string GetProp(xmlNodePtr Node, const char *id)
00080         {
00081                 xmlChar *text = (xmlChar *)xmlGetProp(Node,(const xmlChar *)id);
00082                 if (text == NULL)
00083                         return std::string("");
00084                 std::string t((const char *)text);
00085                 xmlFree(text);
00086                 return t;
00087         }
00088 
00090         static Double GetDoubleProp(xmlNodePtr Node, const char *str)
00091         {
00092                 std::string Prop = GetProp(Node, str);
00093                 if (Prop == "")
00094                         throw XMLError(Node,
00095                         "Unable to find numerical tag " + std::string(str));
00096                 if (!IsDouble(Prop))
00097                     throw XMLError(Node, "Invalid numerical value");
00098                 Double Val = ToDouble(Prop);
00099                 /* \bug Do some checking! And return exception */
00100                 return Val;
00101         }
00102 
00105         static Double GetDoubleProp(xmlNodePtr Node,
00106                                     const char *str,
00107                                     Double DefaultValue)
00108         {
00109                 std::string Prop = GetProp(Node, str);
00110                 if (Prop == "")
00111                         return DefaultValue;
00112 
00113                 Double Val = ToDouble(Prop);
00114                 /* \bug Do some checking! And return exception */
00115                 return Val;
00116         }
00117 
00119         static void EnsureColorTag(xmlNodePtr Node, xmlNodePtr ErrorCtx = NULL)
00120         {
00121                 if (!Node) {
00122                         throw XMLError(ErrorCtx,
00123                                 "Expected \"Color\" tag within"
00124                                 " this context got nothing ");
00125                 }
00126 
00127                 if (xmlStrcmp(Node->name, (const xmlChar *) "Color"))
00128                         throw XMLError(Node,
00129                                 "Expected \"Color\" tag got " +
00130                                 std::string((char *)Node->name));
00131         }
00132 
00136         static std::string GetID(xmlNodePtr Node)
00137         {
00138                 std::string id = GetProp(Node, "id");
00139                 if (id == "")
00140                         throw XMLError(Node,
00141                                 "No identifier (id tag) specified");
00142                 return id;
00143         }
00144 
00146         static Bool IsToken(xmlNodePtr Node, const char *Token)
00147         {
00148                 if ((xmlStrcmp(Node->name, (const xmlChar *)Token)) == 0)
00149                         return true;
00150                 return false;
00151         }
00152 
00154         static void OmitComments(xmlNodePtr &Node)
00155         {
00156                 for (; Node != NULL; Node = Node->next) {
00157                         if (IsToken(Node, "comment"))
00158                                 continue;
00159                         break;
00160                 }
00161         }
00162 
00163         void Scene::DumpLibrary()
00164         {
00165                 using namespace std;
00166                 cout << "--- Dumping colors: " << endl;
00167                 for (ColIter i = ColMap.begin();
00168                      i != ColMap.end(); i++) {
00169                         cout << i->first << " == " << i->second << endl;
00170                 }
00171 
00172                 cout << "--- Dumping textures: " << endl;
00173                 for (TexIter i = TexMap.begin();
00174                      i != TexMap.end(); i++) {
00175                         cout << i->first << " == " << *i->second << endl;
00176                 }
00177 
00178                 cout << "--- Dumping materials: " << endl;
00179                 for (MatIter i = MatMap.begin();
00180                      i != MatMap.end(); i++) {
00181                         cout << i->first << " == " << *i->second << endl;
00182                 }
00183         }
00184 
00185         void Scene::CreateLibrary()
00186         {
00187                 using namespace std;
00188 
00189                 ColMap.insert(make_pair(string("Black"), ColLib::Black()));
00190                 ColMap.insert(make_pair(string("White"), ColLib::White()));
00191                 ColMap.insert(make_pair(string("Red"), ColLib::Red()));
00192                 ColMap.insert(make_pair(string("Green"), ColLib::Green()));
00193                 ColMap.insert(make_pair(string("Blue"), ColLib::Blue()));
00194                 ColMap.insert(make_pair(string("Gray"), ColLib::Gray()));
00195 
00196                 TexMap.insert(make_pair(string("Black"), &TexLib::Black()));
00197                 TexMap.insert(make_pair(string("White"), &TexLib::White()));
00198                 TexMap.insert(make_pair(string("Red"), &TexLib::Red()));
00199                 TexMap.insert(make_pair(string("Green"), &TexLib::Green()));
00200                 TexMap.insert(make_pair(string("Blue"), &TexLib::Blue()));
00201                 TexMap.insert(make_pair(string("Gray"), &TexLib::Gray()));
00202 
00203                 IdxMap.insert(make_pair(string("Vacuum"), 1.0));
00204                 IdxMap.insert(make_pair(string("Air"), 1.0002926));
00205                 IdxMap.insert(make_pair(string("Water"), 1.333));
00206                 IdxMap.insert(make_pair(string("Diamond"), 2.419));
00207                 IdxMap.insert(make_pair(string("Amber"), 1.55));
00208                 IdxMap.insert(make_pair(string("Salt"), 1.544));
00209                 IdxMap.insert(make_pair(string("Ice"), 1.31));
00210                 IdxMap.insert(make_pair(string("Glass"), 1.60));
00211         }
00212 
00213         Color Scene::ParseColor(xmlNodePtr Node)
00214         {
00215                 /* <Color [id="ColorID"] [r="float" g="float" b="float"] />
00216                  *   If ID is specified:
00217                  *      if color is is map return it.
00218                  *      else
00219                  *              if r,g,b present define color
00220                  *              else error
00221                  *      else
00222                  *      if r,g,b present create and return color
00223                  *      else error
00224                 */
00225                 std::string id = GetProp(Node, "id");
00226                 std::string r = GetProp(Node, "r");
00227                 std::string g = GetProp(Node, "g");
00228                 std::string b = GetProp(Node, "b");
00229 
00230                 if (id == "" && (r == "" || g == "" || b == ""))
00231                         throw XMLError(Node,
00232                                "Inappropriate color declaration");
00233 
00234                 if (id != "") {
00235                         /* Do we have this id in map? */
00236                         ColIter iter = ColMap.find(id);
00237                         if (iter != ColMap.end())
00238                                 return iter->second;
00239 
00240                         if (r == "" || g == "" || b == "")
00241                                 throw XMLError(Node,
00242                                                "Color \"" + id +
00243                                                "\" doesn't exist in database");
00244                 }
00245 
00246                 /* We don't have it - insert it */
00247                 double R, G, B;
00248                 R = ToDouble(r);
00249                 G = ToDouble(g);
00250                 B = ToDouble(b);
00251                 if (R > 1.0 || R < 0.0 || G > 1.0
00252                     || G < 0.0 || B > 1.0 || B < 0.0)
00253                         throw XMLError(Node,
00254                                 "Illegal color attribute value. "
00255                                 "R, G, B belongs between 0.0 and 1.0");
00256                 if (id != "")
00257                         ColMap.insert( make_pair(id, Color(R, G, B)) );
00258                 return Color(R, G, B);
00259         }
00260 
00261         Math::Vector Scene::ParseVector(xmlNodePtr Node)
00262         {
00263                 std::string x = GetProp(Node, "x");
00264                 std::string y = GetProp(Node, "y");
00265                 std::string z = GetProp(Node, "z");
00266                 if (x == "" || y == "" || z == "")
00267                         throw XMLError(Node,
00268                                 "Inappropriate vector declaration");
00269 
00270                 double X, Y, Z;
00271                 X = ToDouble(x);
00272                 Y = ToDouble(y);
00273                 Z = ToDouble(z);
00274                 return Math::Vector(X, Y, Z);
00275         }
00276 
00277         const Texture *Scene::GetTexture(const std::string &id)
00278         {
00279                 TexIter iter = TexMap.find(id);
00280                 if (iter != TexMap.end())
00281                         return iter->second;
00282                 return NULL;
00283         }
00284 
00285         const Material *Scene::GetMaterial(const std::string &id)
00286         {
00287                 MatIter iter = MatMap.find(id);
00288                 if (iter != MatMap.end())
00289                         return iter->second;
00290                 return NULL;
00291         }
00292 
00293 
00294         void Scene::ParseTexture(xmlNodePtr Node)
00295         {
00296                 std::string id = GetID(Node);
00297                 std::string Type = GetProp(Node, "type");
00298                 if (Type == "")
00299                         throw XMLError(Node,
00300                                        "No texture type specified"
00301                                        " (plane or checked)");
00302                 if (id == "")
00303                         throw XMLError(Node,
00304                                        "No identified given for texture");
00305 
00306                 if (GetTexture(id) != NULL)
00307                         throw XMLError(Node,
00308                                        "Texture with this ID already exists");
00309 
00310                 if (Type == "Plain") {
00311                         xmlNodePtr Child = Node->xmlChildrenNode;
00312                         OmitComments(Child);
00313                         EnsureColorTag(Child, Node);
00314                         Color C = ParseColor(Child);
00315 
00316                         Child = Child->next;
00317                         OmitComments(Child);
00318                         if (Child)
00319                                 throw XMLError(Node,
00320                                         "Plane texture requires"
00321                                         " one color parameter");
00322 
00323                         TexLib::Plain *Tex = new TexLib::Plain(C);
00324                         /* Add texture to scene so it will be freed
00325                            and to id list */
00326                         this->AddTexture(Tex);
00327                         TexMap.insert( make_pair(id, Tex) );
00328 
00329                 } else if (Type == "Checked") {
00330                         xmlNodePtr Child = Node->xmlChildrenNode;
00331                         OmitComments(Child);
00332                         /* First color */
00333                         EnsureColorTag(Child, Node);
00334                         Color A = ParseColor(Child);
00335 
00336                         /* Second color */
00337                         Child = Child->next;
00338                         OmitComments(Child);
00339                         EnsureColorTag(Child, Node);
00340                         Color B = ParseColor(Child);
00341 
00342                         Child = Child->next;
00343                         OmitComments(Child);
00344                         if (Child)
00345                                 throw XMLError(Node,
00346                                         "Checked texture requires"
00347                                         " two color parameter");
00348 
00349                         /* Additional parameters */
00350                         std::string Width_ =  GetProp(Node, "width");
00351                         std::string Height_ = GetProp(Node, "height");
00352                         std::string Tile_ = GetProp(Node, "tile");
00353                         Double Width, Height;
00354                         Bool Tile = true;
00355                         if (Width_ == "")
00356                                 Width = 1.0;
00357                         else    Width = ToDouble(Width_);
00358                         if (Height_ == "")
00359                                 Height = 1.0;
00360                         else    Height = ToDouble(Height_);
00361                         if (Tile_ == "false" || Tile_ == "no")
00362                                 Tile = false;
00363 
00364                         TexLib::Checked *Tex =
00365                                 new TexLib::Checked(A, B, Width, Height, Tile);
00366                         this->AddTexture(Tex);
00367 
00368                         TexMap.insert( make_pair(id, Tex) );
00369                 } else
00370                         throw XMLError(Node,
00371                                 "Invalid texture type specified");
00372         }
00373 
00374         Double Scene::ParseIdx(xmlNodePtr Node)
00375         {
00376                 std::string idx = GetProp(Node, "idx");
00377                 if (IsDouble(idx)) {
00378                         Double idx = GetDoubleProp(Node, "idx");
00379                         return idx;
00380                 } else {
00381                         if (idx != "") {
00382                                 IdxIter iter = IdxMap.find(idx);
00383                                 if (iter == IdxMap.end())
00384                                         throw XMLError(Node,
00385                                                        "No refractive index"
00386                                                        " with that name");
00387                                 return iter->second;
00388                         } else {
00389                                 return MatLib::IdxGlass;
00390                         }
00391                 }
00392         }
00393 
00394         void Scene::ParseMaterial(xmlNodePtr Node)
00395         {
00396                 std::string id = GetProp(Node, "id");
00397                 if (id == "")
00398                         throw XMLError("Material identifier not specified");
00399                 if (GetMaterial(id) != NULL)
00400                         throw XMLError("Material already defined");
00401 
00402                 /* Material parameters with default values */
00403                 const Texture
00404                         *Diffuse = &TexLib::Green(),
00405                         *Specular = &TexLib::White(),
00406                         *Reflect = &TexLib::Black(),
00407                         *Refract = &TexLib::Black();
00408 
00409                 std::string diffuse = GetProp(Node, "diffuse");
00410                 std::string specular = GetProp(Node, "specular");
00411                 std::string reflect = GetProp(Node, "reflect");
00412                 std::string refract = GetProp(Node, "refract");
00413                 Double Shininess = GetDoubleProp(Node, "shininess", 12.0);
00414                 Double Idx = ParseIdx(Node);
00415 
00416                 /* Decode given non-default textures */
00417                 if (diffuse != "") Diffuse = GetTexture(diffuse);
00418                 if (specular != "") Specular = GetTexture(specular);
00419                 if (reflect != "") Reflect = GetTexture(reflect);
00420                 if (refract != "") Refract = GetTexture(refract);
00421 
00422                 if (!Diffuse) throw XMLError(Node,
00423                                              "Undefined texture " + diffuse);
00424                 if (!Specular) throw XMLError(Node,
00425                                               "Undefined texture " + specular);
00426                 if (!Reflect) throw XMLError(Node,
00427                                              "Undefined texture " + reflect);
00428                 if (!Refract) throw XMLError(Node,
00429                                              "Undefined texture " + refract);
00430 
00431                 /* Everything read, insert to library */
00432                 Material *Mat = new Material(
00433                         *Diffuse, *Specular,
00434                         *Refract, *Reflect,
00435                         0.0, 0.0, 0.0,
00436                         Shininess, Idx);
00437 
00438                 MatMap.insert( make_pair(id, Mat) );
00439                 this->AddMaterial(Mat);
00440         }
00441 
00442         void Scene::ParseLight(xmlNodePtr Node)
00443         {
00444                 std::string Type = GetProp(Node, "type");
00445                 if (Type == "")
00446                         throw XMLError("Light type not given");
00447                 if (Type == "Ambient") {
00448                         xmlNodePtr Cur = Node->xmlChildrenNode;
00449                         OmitComments(Cur);
00450                         EnsureColorTag(Cur, Node);
00451                         Color C = ParseColor(Cur);
00452                         Cur = Cur->next;
00453                         OmitComments(Cur);
00454                         if (Cur)
00455                                 throw XMLError(Node,
00456                                         "Garbage after color declaration");
00457 
00458                         this->AddLight(new AmbientLight(C));
00459                 } else if (Type == "Point") {
00460                         xmlNodePtr Cur = Node->xmlChildrenNode;
00461                         Bool GotColor = false;
00462                         Bool GotPosition = false;
00463                         Color C;
00464                         Math::Vector Pos;
00465                         OmitComments(Cur);
00466                         for (; Cur != NULL;
00467                              Cur = Cur->next, OmitComments(Cur)) {
00468                                 if (!GotPosition && IsToken(Cur, "Position")) {
00469                                         Pos = ParseVector(Cur);
00470                                         GotPosition = true;
00471                                 }
00472                                 else if (!GotColor && IsToken(Cur, "Color")) {
00473                                         C = ParseColor(Cur);
00474                                         GotColor = true;
00475                                 } else {
00476                                         throw XMLError(Cur,
00477                                                 "Garbage in pointlight"
00478                                                 " declaration");
00479                                 }
00480                         }
00481                         if (!GotColor || !GotPosition)
00482                                 throw XMLError(Node,
00483                                                "Point light requires color"
00484                                                " and position data");
00485                         this->AddLight(new PointLight(Pos, C));
00486                 }
00487         }
00488 
00489         void Scene::ParseCamera(xmlNodePtr Node)
00490         {
00491                 xmlNodePtr Cur = Node->xmlChildrenNode;
00492                 Bool
00493                         GotPos = false,
00494                         GotDir = false,
00495                         GotTop = false;
00496 
00497                 Math::Vector
00498                         Pos(0.0, 0.0, 0.0),
00499                         Dir(0.0, 0.0, 1.0),
00500                         Top(0.0, 1.0, 0.0);
00501                 Double FOV = GetDoubleProp(Node, "FOV", 45.0);
00502 
00503                 OmitComments(Cur);
00504                 for (; Cur != NULL; Cur = Cur->next, OmitComments(Cur)) {
00505                         if (!GotPos && IsToken(Cur, "Pos")) {
00506                                 Pos = ParseVector(Cur);
00507                                 GotPos = true;
00508                         } else
00509                         if (!GotDir && IsToken(Cur, "Dir")) {
00510                                 Dir = ParseVector(Cur);
00511                                 GotDir = true;
00512                         } else
00513                         if (!GotTop && IsToken(Cur, "Top")) {
00514                                 Top = ParseVector(Cur);
00515                                 GotTop = true;
00516                         } else
00517                                 throw XMLError(
00518                                         "Garbage in camera"
00519                                         " declaration");
00520                 }
00521 
00522                 /* Create camera from read data */
00523                 this->C = Camera(Pos,
00524                                  Dir,
00525                                  Camera::DegreeToFOV(FOV),
00526                                  !GotTop,
00527                                  Top);
00528 
00529         }
00530 
00531         void Scene::ParseSphere(xmlNodePtr Node)
00532         {
00533                 xmlNodePtr Cur = Node->xmlChildrenNode;
00534                 Bool    GotPosition = false,
00535                         GotMaterial = false;
00536                 const Material *Material = &MatLib::Gray();;
00537                 Math::Vector Position(0.0, 0.0, 0.0);
00538                 Double Radius = GetDoubleProp(Node, "radius");
00539 
00540                 OmitComments(Cur);
00541                 for (; Cur != NULL; Cur = Cur->next, OmitComments(Cur)) {
00542                         if (!GotPosition && IsToken(Cur, "Position")) {
00543                                 Position = ParseVector(Cur);
00544                                 GotPosition = true;
00545                         } else
00546                         if (!GotMaterial && IsToken(Cur, "Material")) {
00547                                 std::string id = GetProp(Cur, "id");
00548                                 Material = GetMaterial(id);
00549                                 if (!Material)
00550                                         throw XMLError(Cur,
00551                                                 "Material doesn't exist");
00552                                 GotMaterial = true;
00553                         } else
00554                                 throw XMLError(
00555                                         "Garbage in Sphere"
00556                                         " declaration");
00557                 }
00558 
00559                 /* Create camera from read data */
00560                 Sphere *S = new Sphere(Position, Radius, *Material);
00561                 if (DEBUG)
00562                         std::cout
00563                                 << "Adding sphere " << *S << std::endl;
00564                 this->AddObject(S);
00565 
00566         }
00567 
00568         void Scene::ParsePlane(xmlNodePtr Node)
00569         {
00570                 xmlNodePtr Cur = Node->xmlChildrenNode;
00571                 Bool    GotNormal = false,
00572                         GotMaterial = false;
00573                 const Material *Material = &MatLib::Gray();;
00574                 Math::Vector Normal(0.0, 1.0, 0.0);
00575                 Double Distance = GetDoubleProp(Node, "distance");
00576 
00577                 OmitComments(Cur);
00578                 for (; Cur != NULL; Cur = Cur->next, OmitComments(Cur)) {
00579                         if (!GotNormal && IsToken(Cur, "Normal")) {
00580                                 Normal = ParseVector(Cur);
00581                                 GotNormal = true;
00582                         } else
00583                         if (!GotMaterial && IsToken(Cur, "Material")) {
00584                                 std::string id = GetProp(Cur, "id");
00585                                 Material = GetMaterial(id);
00586                                 if (!Material)
00587                                         throw XMLError(Cur,
00588                                                 "Material doesn't exist");
00589                                 GotMaterial = true;
00590                         } else
00591                                 throw XMLError(
00592                                         "Garbage in Plane"
00593                                         " declaration");
00594                 }
00595 
00596                 /* Create camera from read data */
00597                 this->AddObject(
00598                         new Plane(Normal, Distance, *Material));
00599         }
00600 
00601         Bool Scene::ParseFile(const std::string &File)
00602         {
00603                 xmlDocPtr doc = NULL;
00604                 xmlNodePtr cur;
00605                 xmlLineNumbersDefault(1);
00606                 xmlKeepBlanksDefault(0);
00607                 try {
00608                         doc = xmlParseFile(File.c_str());
00609                         if (doc == NULL)
00610                                 throw XMLError("Unable to initialize parsing");
00611 
00612                         cur = xmlDocGetRootElement(doc);
00613                         if (cur == NULL)
00614                                 throw XMLError("Document is empty");
00615 
00616                         if (xmlStrcmp(cur->name, (const xmlChar *) "Scene"))
00617                                 throw XMLError("Document has wrong type,"
00618                                                " root node != Scene");
00619 
00620                         /* Initialize scene object */
00621                         ColMap.clear();
00622                         MatMap.clear();
00623                         TexMap.clear();
00624                         CreateLibrary();
00625 
00626                         cur = cur->xmlChildrenNode;
00627                         OmitComments(cur);
00628                         for (; cur != NULL;
00629                              cur = cur->next, OmitComments(cur)) {
00630                                 if (IsToken(cur, "Background")) {
00631                                         this->Background = ParseColor(cur);
00632                                         continue;
00633                                 }
00634 
00635                                 if (IsToken(cur, "Atmosphere")) {
00636                                         this->AtmosphereIdx = ParseIdx(cur);
00637                                         continue;
00638                                 }
00639 
00640                                 if (IsToken(cur, "Color")) {
00641                                         ParseColor(cur);
00642                                         continue;
00643                                 }
00644 
00645                                 if (IsToken(cur, "Texture")) {
00646                                         ParseTexture(cur);
00647                                         continue;
00648                                 }
00649 
00650                                 if (IsToken(cur, "Material")) {
00651                                         ParseMaterial(cur);
00652                                         continue;
00653                                 }
00654 
00655                                 if (IsToken(cur, "Light")) {
00656                                         ParseLight(cur);
00657                                         continue;
00658                                 }
00659 
00660                                 if (IsToken(cur, "Camera")) {
00661                                         ParseCamera(cur);
00662                                         continue;
00663                                 }
00664 
00665                                 if (IsToken(cur, "Sphere")) {
00666                                         ParseSphere(cur);
00667                                         continue;
00668                                 }
00669 
00670                                 if (IsToken(cur, "Plane")) {
00671                                         ParsePlane(cur);
00672                                         continue;
00673                                 }
00674 
00675                                 if (IsToken(cur, "Dump")) {
00676                                         std::cout << "*** Dump requested ***" << std::endl;
00677                                         DumpLibrary();
00678                                         continue;
00679                                 }
00680 
00681                                 throw XMLError("Invalid token in file \""
00682                                                + ToStr(cur->name) + "\"");
00683                         }
00684                         xmlFreeDoc(doc);
00685                         return true;
00686                 } catch (std::exception &e) {
00687                         xmlFreeDoc(doc);
00688                         std::cout << "*** Error while parsing XML file:" << std::endl
00689                                   << e.what() << std::endl;
00690                         if (DEBUG) DumpLibrary();
00691                         return false;
00692                 }
00693 
00694         }
00695 }

Generated on Wed Mar 12 00:34:58 2008 for blaRAY by  doxygen 1.5.5