//#ident "$Id: Loader.cpp,v 1.33 2003/06/16 13:06:12 rzr Exp $" /*************************************************************************** Loader.cpp - description ------------------- begin : Thu Mar 9 2000 copyright : (C) 2000 by Henrik Enqvist email : henqvist@excite.com ***************************************************************************/ #include #include #include #include #include #include #include #include #include "Private.h" #include "Config.h" #include "Loader.h" #include "Pinball.h" #include "Keyboard.h" #include "Menu.h" #include "Engine.h" #include "ArmBehavior.h" #include "CollisionBounds.h" #include "Camera.h" #include "Light.h" #include "Cube.h" #include "BigSphere.h" #include "Cylinder.h" #include "BounceBehavior.h" #include "KeyBehavior.h" #include "Grid.h" #include "KeyRotBehavior.h" #include "Polygon.h" #include "BumperBehavior.h" #include "TextureUtil.h" #include "SoundUtil.h" #include "Score.h" #include "StdAnimation.h" #include "StateBehavior.h" #include "Script.h" #include "FakeModuleBehavior.h" #include "PlungerBehavior.h" #include "LoaderModule.h" #ifdef RZR_PATCHES_3DS #include "Obj3dsUtil.h" #endif #define EmReadCmp(file_, ist_, str_, cmp_) \ this->readNextToken(file_, ist_, str_); \ if (str_ != cmp_) throw string("Parse error, unexpected token \'") + str_ + \ string("\' expecting \'") + cmp_ + string("\'"); /******************************************************* * Singleton suff ******************************************************/ Loader * Loader::p_Loader = NULL; Loader::Loader() { m_iNextSignal = LOADER_FIRSTSIGNAL; m_iNextVariable = LOADER_FIRSTVARIABLE; m_bModules = true; m_LoaderModule = 0; #ifdef RZR_PATCHES_3DS m_Obj3dsUtil = 0; #endif } Loader::~Loader() { delete m_LoaderModule; #ifdef RZR_PATCHES_3DS delete m_Obj3dsUtil; #endif }; Loader * Loader::getInstance() { if (p_Loader == NULL) { p_Loader = new Loader(); } return p_Loader; } /******************************************************* * Reader functions, this wierd things is done to * enable line counting ******************************************************/ void Loader::readNextToken(ifstream & file, istringstream & ist, string & str) { ist >> str; while(file && !ist) { string buf; getline(file, buf); ist.clear(); ist.str(buf); ist >> str; ++m_iLineNumber; } } void Loader::readNextToken(ifstream & file, istringstream & ist, int & i) { ist >> i; while(file && !ist) { string buf; getline(file, buf); ist.clear(); ist.str(buf); ist >> i; ++m_iLineNumber; } } void Loader::readNextToken(ifstream & file, istringstream & ist, float & f) { ist >> f; while(file && !ist) { string buf; getline(file, buf); ist.clear(); ist.str(buf); ist >> f; ++m_iLineNumber; } } /******************************************************* * Signal and variable to string conv ******************************************************/ int Loader::getSignal(const char * signal) { // some defualt signals if (signal == NULL) return PBL_SIG_NULL; if (strncmp(signal, "null", 63) == 0) return PBL_SIG_NULL; if (strncmp(signal, "reset", 63) == 0) return PBL_SIG_RESET_ALL; if (strncmp(signal, "tilt", 63) == 0) return PBL_SIG_TILT; if (strncmp(signal, "game_over", 63) == 0) return PBL_SIG_GAME_OVER; if (strncmp(signal, "game_start", 63) == 0) return PBL_SIG_GAME_START; if (strncmp(signal, "game_pause", 63) == 0) return PBL_SIG_GAME_PAUSE; // other signals map::iterator element = m_hSignalInt.find(string(signal)); if (element != m_hSignalInt.end()) { return (*element).second; } else { //cerr << "*** insert signal " << signal << " " << m_iNextSignal << endl; m_hSignalInt.insert(pair(string(signal), m_iNextSignal)); m_hSignalString.insert(pair(m_iNextSignal, string(signal))); ++m_iNextSignal; return m_iNextSignal-1; } } int Loader::getVariable(const char * var) { if (var == NULL) return -1; map::iterator element = m_hVariableInt.find(string(var)); if (element != m_hVariableInt.end()) { return (*element).second; } else { //cerr << "*** insert variable " << var << " " << m_iNextVariable << endl; m_hVariableInt.insert(pair(string(var), m_iNextVariable)); m_hVariableString.insert(pair(m_iNextVariable, string(var))); ++m_iNextVariable; return m_iNextVariable-1; } } const char * Loader::getSignal(int signal) { // default signals if (signal < 0) return "null"; switch (signal) { case PBL_SIG_NULL : return "null"; case PBL_SIG_RESET_ALL : return "reset"; case PBL_SIG_TILT : return "tilt"; case PBL_SIG_GAME_OVER : return "game_over"; case PBL_SIG_GAME_START : return "game_start"; case PBL_SIG_GAME_PAUSE : return "game_pause"; } // other signals map::iterator element = m_hSignalString.find(signal); if (element != m_hSignalString.end()) { return (*element).second.c_str(); } else { return NULL; } } const char * Loader::getVariable(int var) { map::iterator element = m_hVariableString.find(var); if (element != m_hVariableString.end()) { return (*element).second.c_str(); } else { return NULL; } } /* This on must be called each time we load a new level */ void Loader::clearSignalVariable() { m_iNextSignal = LOADER_FIRSTSIGNAL; m_iNextVariable = LOADER_FIRSTVARIABLE; m_hSignalInt.clear(); m_hSignalString.clear(); m_hVariableInt.clear(); m_hVariableString.clear(); }; /******************************************************* * Set properties for a group ******************************************************/ void Loader::loadProperties(ifstream & file, istringstream & ist, Group * group) { EM_COUT("Loader::loadProperties", 0); string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); while (str != "}") { if (str == "transform_once") { group->setProperty(EM_GROUP_TRANSFORM_ONCE); EM_COUT("Loader::loadProperties - transform once", 0); } else if (str == "no_light") { group->setProperty(EM_GROUP_NO_LIGHT); EM_COUT("Loader::loadProperties - no light", 0); } else if (str == "light_once") { group->setProperty(EM_GROUP_LIGHT_ONCE); EM_COUT("Loader::loadProperties - light once", 0); // TODO we don't need this } else if (str == "no_signal") { group->setProperty(EM_GROUP_NO_SIGNAL); EM_COUT("Loader::loadProperties - no signal - deprecated", 0); } else if (str == "wall") { group->setUserProperty(PBL_WALLS); EM_COUT("Loader::loadProperties - wall", 0); } else if (str == "wall_one_way") { group->setUserProperty(PBL_WALLS_ONE); EM_COUT("Loader::loadProperties - wall_one_way", 0); } else if (str == "group_1") { //group->setUserProperty(PBL_GROUP1); group->setCollisionGroup(1); EM_COUT("Loader::loadProperties - group_1", 0); } else if (str == "alpha_test") { for (int a=0; agetShape3DSize(); a++) { group->getShape3D(a)->setProperty(EM_SHAPE3D_ALPHATEST); } EM_COUT("Loader::loadProperties - alpha test", 0); /* I don't think we need this } else if (str == "transparent") { for (int a=0; agetShape3DSize(); a++) { Shape3D* shape = group->getShape3D(a); shape->setProperty(EM_SHAPE3D_USE_TRANS); vector::iterator polyIter = shape->m_vPolygon.begin(); vector::iterator polyEnd = shape->m_vPolygon.end(); for (; polyIter != polyEnd; polyIter++) { (*polyIter)->setProperty(EM_POLY_TRANS); } } EM_COUT("Loader::loadProperties - transparent", 0); */ } else if (str == "collision") { Shape3D * shape = group->getShape3D(0); if (shape == NULL) { EM_COUT("Loader::loadProperties - no shape", 0); } else { CollisionBounds* bounds = new CollisionBounds(shape->getCollisionSize()); if (shape->getCollisionSize() > 16) { bounds->setShape3D(shape, 4); //4 } else if (shape->getCollisionSize() > 8) { bounds->setShape3D(shape, 3); //4 } else if (shape->getCollisionSize() > 4) { bounds->setShape3D(shape, 2); //4 } else if (shape->getCollisionSize() > 2) { bounds->setShape3D(shape, 1); //4 } else { bounds->setShape3D(shape, 1); } group->setCollisionBounds(bounds); } EM_COUT("Loader::loadProperties - collision", 0); } else { throw string("--UNKNOWN property in property block"); } this->readNextToken(file, ist, str); } } /************************************************************** ** Behaviors **************************************************************/ void Loader::loadArmBehavior(ifstream & file, istringstream & ist, Group * group) { EM_COUT("Loader::loadArmBehavior", 0); string str; ArmBehavior* beh = NULL; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); if (str == "right") { beh = new ArmBehavior(true); } else { beh = new ArmBehavior(false); } group->setBehavior(beh); this->readNextToken(file, ist, str); if (str == "sound") { string soundname; this->readNextToken(file, ist, soundname); string filename = string(Config::getInstance()->getDataSubDir()) + "/" + soundname; int sound = SoundUtil::getInstance()->loadSample(filename.c_str()); beh->setSound(sound); } else if (str == "no_sound"){ } else { throw string("No sound field in ArmBehavior"); } EmReadCmp(file, ist, str, "}"); } void Loader::loadAnimation(ifstream & file, istringstream & ist, Engine *, Group * group, Behavior * beh) { EM_COUT("Loader::loadAnimation", 0); string str; EmAssert(beh != NULL, "Behavior NULL in loadAnimation"); EmReadCmp(file, ist, str, "{"); int type = EM_LIGHT; this->readNextToken(file, ist, str); if (str == "rotation") { type = EM_ROTATION; } else if (str == "translation") { type = EM_TRANSLATION; } else if (str == "light") { type = EM_LIGHT; } else { throw string("Expecting rotation, translation or light in anim field"); } int count, step; this->readNextToken(file, ist, step); this->readNextToken(file, ist, count); StdAnimation* anim = new StdAnimation(step, type); for (; count > 0; count--) { float a, b, c; this->readNextToken(file, ist, a); this->readNextToken(file, ist, b); this->readNextToken(file, ist, c); cerr << "****** " << a <<" "<< b <<" "<< c << endl; if (count == 1) { anim->setEnd(a, b, c); } else { anim->add(a, b, c); } } group->setBehavior(anim); EmReadCmp(file, ist, str, "}"); } void Loader::loadBehaviorLight(ifstream & file, istringstream & ist, Engine * engine, Group * group, Behavior * beh) { EM_COUT("Loader::loadBehaviorLight", 0); string str; EmAssert(beh != NULL, "Behavior NULL in loadBehaviorLight"); EmReadCmp(file, ist, str, "{"); float r, g, b, x, y, z; this->readNextToken(file, ist, r); this->readNextToken(file, ist, g); this->readNextToken(file, ist, b); this->readNextToken(file, ist, x); this->readNextToken(file, ist, y); this->readNextToken(file, ist, z); Light * light = new Light(1.0f, 0.0f, 0.1f, r, g, b); light->setOn(false); light->setProperty(EM_IGNORE_ANGLE_FULL); //light->setProperty(EM_IGNORE_DISTANCE); light->setProperty(EM_USE_BOUNDS); light->setBounds(10.0); Group * gl = new Group(); gl->setName("#light"); gl->addTranslation(x, y, z); gl->setLight(light); group->add(gl); engine->addLight(light); beh->setLight(light); this->loadMisc(file, ist, engine, gl, beh); } void Loader::loadBumperBehavior(ifstream & file, istringstream & ist, Engine * engine, Group * group) { EM_COUT("Loader::loadBumperBehavior", 0); string str; EmReadCmp(file, ist, str, "{"); BumperBehavior* beh = new BumperBehavior(); group->setBehavior(beh); if (this->cmpVersion(m_FileVersion, 0, 3, 0) >= 0) { // 0.3.0 and above float power; this->readNextToken(file, ist, power); beh->setPower(power); } this->readNextToken(file, ist, str); if (str == "sound") { string soundname; this->readNextToken(file, ist, soundname); string filename = string(Config::getInstance()->getDataSubDir()) + "/" + soundname; int sound = SoundUtil::getInstance()->loadSample(filename.c_str()); beh->setSound(sound); } else if (str == "no_sound"){ } else { throw string("No sound field in BumperBehavior"); } group->setUserProperty(PBL_BUMPER); this->loadMisc(file, ist, engine, group, beh); } void Loader::loadPlungerBehavior(ifstream & file, istringstream & ist, Engine * engine, Group * group) { EM_COUT("Loader::loadPlungerBehavior", 0); string str; EmReadCmp(file, ist, str, "{"); PlungerBehavior* beh = new PlungerBehavior(); group->setBehavior(beh); this->readNextToken(file, ist, str); if (str == "sound") { string soundname; this->readNextToken(file, ist, soundname); string filename = string(Config::getInstance()->getDataSubDir()) + "/" + soundname; int sound = SoundUtil::getInstance()->loadSample(filename.c_str()); beh->setSound(sound); } else if (str == "no_sound"){ } else { throw string("No sound field in PlungerBehavior"); } group->setUserProperty(PBL_PLUNGER); this->loadMisc(file, ist, engine, group, beh); } void Loader::loadStateItem(ifstream & file, istringstream & ist, Engine * engine, Group * group, Behavior * beh) { EM_COUT("Loader::loadStateItem", 0); string str; EmAssert(beh != NULL, "Behavior NULL in loadBehaviorLight"); EmAssert(beh->getType() == PBL_TYPE_STATEBEH, "Not StateBehavior"); EmReadCmp(file, ist, str, "{"); string asig; string csig; int cstate, delay, dstate; this->readNextToken(file, ist, asig); this->readNextToken(file, ist, csig); this->readNextToken(file, ist, cstate); this->readNextToken(file, ist, dstate); this->readNextToken(file, ist, delay); StateItem* stateitem = new StateItem(); stateitem->setActSig(this->getSignal(asig.c_str())); stateitem->setCollSig(this->getSignal(csig.c_str())); stateitem->setCollState(cstate); stateitem->setDelayState(dstate, delay); ((StateBehavior*)beh)->addStateItem(stateitem); this->readNextToken(file, ist, str); if (str == "move") { ((StateBehavior*)beh)->useMove(true); float tx, ty, tz, rx, ry, rz; int steps; this->readNextToken(file, ist, steps); this->readNextToken(file, ist, tx); this->readNextToken(file, ist, ty); this->readNextToken(file, ist, tz); this->readNextToken(file, ist, rx); this->readNextToken(file, ist, ry); this->readNextToken(file, ist, rz); stateitem->setMoveSteps(steps); stateitem->setTr(tx, ty, tz); stateitem->setRot(rx, ry, rz); } else if (str == "no_move") { } else { throw string("No move field in StateItem"); } this->readNextToken(file, ist, str); if (str == "light") { stateitem->setLight(true); } else if (str == "no_light"){ stateitem->setLight(false); } else { throw string("No light field in StateItem"); } this->readNextToken(file, ist, str); if (str == "sound") { string soundname; this->readNextToken(file, ist, soundname); string filename = string(Config::getInstance()->getDataSubDir()) + "/" + soundname; int sound = SoundUtil::getInstance()->loadSample(filename.c_str()); stateitem->setSound(sound); } else if (str == "no_sound"){ } else { throw string("No sound field in StateItem"); } this->readNextToken(file, ist, str); if (str == "music") { string musicname; this->readNextToken(file, ist, musicname); string filename = string(Config::getInstance()->getDataSubDir()) + "/" + musicname; int music = SoundUtil::getInstance()->loadMusic(filename.c_str()); stateitem->setMusic(music); } else if (str == "no_music"){ } else { throw string("No music field in StateItem"); } // version hack if (this->cmpVersion(m_FileVersion, 0, 2 ,1) < 0) { // 0.2.0 this->readNextToken(file, ist, str); if (str == "property") { int p; this->readNextToken(file, ist, p); stateitem->setUserProperty(p); } else if (str == "no_property") { } else { throw string("No user property field in StateItem"); } } else { // 0.2.1 and above this->readNextToken(file, ist, str); if (str == "user_property") { int p; this->readNextToken(file, ist, p); stateitem->setUserProperty(p); } else if (str == "no_user_property") { } else { throw string("No user property field in StateItem"); } this->readNextToken(file, ist, str); if (str == "shape_property") { int p; this->readNextToken(file, ist, p); stateitem->setShapeProperty(p); } else if (str == "no_shape_property") { } else { throw string("No shape property field in StateItem"); } } this->readNextToken(file, ist, str); if (str == "texcoord") { ((StateBehavior*)beh)->useTexCoord(true); int count; this->readNextToken(file, ist, count); for (int a=0; areadNextToken(file, ist, u); this->readNextToken(file, ist, v); stateitem->addTexCoord(u, v); } } else if (str == "no_texcoord") { ((StateBehavior*)beh)->useTexCoord(false); } else { throw string("No texcoord field in StateItem"); } // shape this->readNextToken(file, ist, str); if (str == "shape") { ((StateBehavior*)beh)->useShape(true); int count; this->readNextToken(file, ist, count); for (int a=0; areadNextToken(file, ist, s); if (s == 1) { stateitem->addShapeEnable(a, true); } else { stateitem->addShapeEnable(a, false); } } } else if (str == "no_shape") { ((StateBehavior*)beh)->useShape(false); } else { throw string("No shape field in StateItem"); } this->loadMisc(file, ist, engine, group, beh); } void Loader::loadStateBehavior(ifstream & file, istringstream & ist, Engine * engine, Group * group) { EM_COUT("state", 0); string str; EmReadCmp(file, ist, str, "{"); StateBehavior* b = new StateBehavior(); group->setBehavior(b); this->loadMisc(file, ist, engine, group, b); } /**************************************************************** ** Script loading - deprecated ****************************************************************/ void Loader::loadScript(ifstream & file, istringstream & ist, Engine *, Group * group) { EM_COUT("Loader::loadScript", 0); EmAssert(group != NULL, "Group NULL in loadMisc"); string str; this->clearSignalVariable(); Script * script = new Script(); EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); while (str != "}") { QueryItem * qi = new QueryItem(); // read query if (str == "onsignal") { qi->setQuery(EM_SCRIPT_ONSIGNAL); int isig; this->readNextToken(file, ist, isig); for (; isig > 0; --isig) { int sig; this->readNextToken(file, ist, sig); qi->addQueryParm(sig); } } else { throw string("UNKNOWN in script query block ") + str; } // read action this->readNextToken(file, ist, str); if (str == "sendsignal") { qi->setAction(EM_SCRIPT_SENDSIGNAL); int sig, delay; this->readNextToken(file, ist, sig); this->readNextToken(file, ist, delay); qi->addActionParm(sig); qi->addActionParm(delay); } else if (str == "setvar") { qi->setAction(EM_SCRIPT_SETVAR); int id, val; this->readNextToken(file, ist, id); this->readNextToken(file, ist, val); qi->addActionParm(id); qi->addActionParm(val); } else { throw string("UNKNOWN in script action block ") + str; } // done script->addQueryItem(qi); this->readNextToken(file, ist, str); } group->setBehavior(script); } /**************************************************************** ** Module (plugin) loading ****************************************************************/ void Loader::loadModule(ifstream & file, istringstream & ist, Engine *, Group * group) { EM_COUT("+Loader::loadModule", 1); EmAssert(group != NULL, "Group NULL in loadMisc"); m_LoaderModule = LoaderModule::getInstance(); string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); //string filename = string(Config::getInstance()->getDataSubDir()) + "/" + str; string filename = string(EM_LIBDIR) + "/" + str; Behavior *beh=0; if (m_bModules) { beh = m_LoaderModule->read(filename); if (beh == NULL) { throw string("Could not allocate behavior object"); } else { group->setBehavior(beh); } } else { group->setBehavior(new FakeModuleBehavior(filename.c_str())); } EmReadCmp(file, ist, str, "}"); EM_COUT("-Loader::loadModule", 1); } /**************************************************************** ** Top level loading ****************************************************************/ int Loader::cmpVersion(const FileVersion & version, const int major, const int minor, const int micro) { if (version.major > major) return 1; else if (version.minor < major) return -1; else { if (version.minor > minor) return 1; else if (version.minor < minor) return -1; else { if (version.micro > micro) return 1; else if (version.micro < micro) return -1; } } return 0; } /* Things added to objects, e.g. lights, animation, behavior*/ void Loader::loadMisc(ifstream & file, istringstream & ist, Engine * engine, Group * group, Behavior * beh) { EM_COUT("Loader::loadMisc", 0); EmAssert(engine != NULL && group != NULL, "Engine or group NULL in loadMisc"); string str; this->readNextToken(file, ist, str); while (str != "}") { if (str == "properties"){ this->loadProperties(file, ist, group); } else if (str == "arm_behavior") { this->loadArmBehavior(file, ist, group); } else if (str == "state_behavior") { this->loadStateBehavior(file, ist, engine, group); } else if (str == "bumper_behavior") { this->loadBumperBehavior(file, ist, engine, group); } else if (str == "plunger_behavior") { this->loadPlungerBehavior(file, ist, engine, group); } else if (str == "light") { this->loadBehaviorLight(file, ist, engine, group, beh); } else if (str == "state_item") { this->loadStateItem(file, ist, engine, group, beh); } else if (str == "animation") { this->loadAnimation(file, ist, engine, group, beh); } else if (str == "shape") { this->loadShape(file, ist, engine, group, beh); } else if (str == "script") { this->loadScript(file, ist, engine, group); } else if (str == "module") { this->loadModule(file, ist, engine, group); } else if (str == "sub_object") { Group * g = this->loadStdObject(file, ist, engine); group->add(g); #ifdef RZR_PATCHES_3DS // version 0.3.0 and above } else if (str == "shape_include_3ds_ascii") { this->loadShape3dsAscii(file, ist, engine, group, beh); } else if (str == "group_include_3ds_ascii") { this->loadGroup3dsAscii(file, ist, engine, group, beh); #endif //ok but I'd like set as option unless it get fully usable (bugless too) } else { cerr << str << endl; throw string("UNKNOWN in misc block"); } this->readNextToken(file, ist, str); } } /* Top level object */ Group * Loader::loadStdObject(ifstream & file, istringstream & ist, Engine * engine) { string str; this->readNextToken(file, ist, str); Group * group = new Group(); group->setName(str.c_str()); EM_COUT("Loader::loadStdObject " << str, 0); EmReadCmp(file, ist, str, "{"); float tx, ty, tz, rx, ry, rz, sx, sy, sz; this->readNextToken(file, ist, tx); this->readNextToken(file, ist, ty); this->readNextToken(file, ist, tz); this->readNextToken(file, ist, rx); this->readNextToken(file, ist, ry); this->readNextToken(file, ist, rz); if (this->cmpVersion(m_FileVersion, 0, 3, 0) >= 0) { // 0.3.0 and above this->readNextToken(file, ist, sx); this->readNextToken(file, ist, sy); this->readNextToken(file, ist, sz); } else { // below 0.3.0 sx = 1.0f; sy = 1.0f; sz = 1.0f; } group->setTransform(tx, ty, tz, rx, ry, rz); group->setScale(sx, sy, sz); this->loadMisc(file, ist, engine, group, NULL); return group; } /**************************************************************** ** Shape specific loads ****************************************************************/ void Loader::loadShape(ifstream & file, istringstream & ist, Engine *, Group * group, Behavior *) { EM_COUT("Loader::loadShape", 0); string str; Shape3D * s = this->loadShape3DChunk(file, ist); if (s != NULL) { group->addShape3D(s); } else { cerr << "could not load shape" << endl; } } void Loader::readUnknown(ifstream & file, istringstream & ist) { EM_COUT("Loader::readUnknown", 0); string str; EmReadCmp(file, ist, str, "{"); int brackets = 1; while (brackets > 0) { this->readNextToken(file, ist, str); if (str == "{") brackets++; if (str == "}") brackets--; } } void Loader::readPolygon(ifstream & file, istringstream & ist, Shape3D* shape) { EM_COUT("Loader::readPolygon", 0); string str; Polygon3D * poly = new Polygon3D(shape); EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); while (str != "}") { if (str == "pes") { // TODO reserce space for this->readUnknown(file, ist); } else if (str == "tpt") { this->readUnknown(file, ist); poly->setProperty(EM_POLY_TRANS); shape->setProperty(EM_SHAPE3D_USE_TRANS); // } else if (str == "dbl") { // this->readUnknown(file, ist); // poly->setProperty(EM_POLY_DOUBLE); // } else if (str == "flt") { // this->readUnknown(file, ist); // poly->setProperty(EM_POLY_FLAT); } else if (str == "ple") { this->readPolygonEdge(file, ist, poly); } else { this->readUnknown(file, ist); } this->readNextToken(file, ist, str); } shape->add(poly); } void Loader::readPolygonEdge(ifstream & file, istringstream & ist, Polygon3D* poly) { EM_COUT("Loader::readPolygonEdge", 0); string str; int i; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, i); poly->add(i); EmReadCmp(file, ist, str, "}"); } void Loader::readVertex(ifstream & file, istringstream & ist, Shape3D* shape) { EM_COUT("Loader::readVertex", 0); float x, y, z, r, g, b, a, u, v; string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, x); this->readNextToken(file, ist, y); this->readNextToken(file, ist, z); this->readNextToken(file, ist, r); this->readNextToken(file, ist, g); this->readNextToken(file, ist, b); this->readNextToken(file, ist, a); this->readNextToken(file, ist, u); this->readNextToken(file, ist, v); EmReadCmp(file, ist, str, "}"); shape->add(x, y, z, r, g, b, a, u, v); } void Loader::readTexture(ifstream & file, istringstream & ist, Shape3D* shape) { EM_COUT("Loader::readTexture", 0); string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); // hack to load pcx files instead of png files for allegro #if EM_USE_ALLEGRO str += ".pcx"; #endif string filename = string(Config::getInstance()->getDataSubDir()) + "/" + str; EmTexture * tex = TextureUtil::getInstance()->loadTexture(filename.c_str()); if (tex != NULL) { shape->setTexture(tex); } else { throw string("Loader::readTexture error loading: ") + filename; } EmReadCmp(file, ist, str, "}"); } /* Assumes that the word 'shape' is already read and that we wish read stuff * between { and } */ Shape3D* Loader::loadShape3DChunk(ifstream & file, istringstream & ist) { EM_COUT("Loader::loadShape3DChunk loading shape", 0); Shape3D* shape = new Shape3D(); string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); while (str != "}") { if (str == "vtx") { this->readVertex(file, ist, shape); } else if (str == "ply") { this->readPolygon(file, ist, shape); } else if (str == "tex") { this->readTexture(file, ist, shape); } else if (str == "hid") { shape->setProperty(EM_SHAPE3D_HIDDEN); this->readUnknown(file, ist); } else if (str == "bhi") { shape->setProperty(EM_SHAPE3D_BEHIND); this->readUnknown(file, ist); } else if (str == "bh2") { shape->setProperty(EM_SHAPE3D_BEHIND2); this->readUnknown(file, ist); } else if (str == "lit") { shape->setProperty(EM_SHAPE3D_ALWAYSLIT); this->readUnknown(file, ist); } else { this->readUnknown(file, ist); } this->readNextToken(file, ist, str); } shape->countNormals(); return shape; } /**************************************************************** ** The main loader function ****************************************************************/ int Loader::loadFile(const char* fn, Engine * engine) { ifstream file(fn); try { if (!file) { throw string("Loader::loadFile file not found: ") + string(fn); } if (engine == NULL) { throw string("Engine NULL"); } string str(""); istringstream ist(""); m_iLineNumber = 0; m_FileVersion.major = 0; m_FileVersion.minor = 2; m_FileVersion.micro = 0; this->readNextToken(file, ist, str); if (str == "version") { EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, m_FileVersion.major); this->readNextToken(file, ist, m_FileVersion.minor); this->readNextToken(file, ist, m_FileVersion.micro); EmReadCmp(file, ist, str, "}"); if (this->cmpVersion(m_FileVersion, 0, 3, 0) > 0) { cerr << "WARNING! Version above 0.3.0 not supported, file is " << m_FileVersion.major <<" "<< m_FileVersion.minor <<" "<< m_FileVersion.micro << endl; } } else { cerr << "Version string not found assuming, 0.2.0" << endl; } while (file) { if (str == "object") { Group * group = this->loadStdObject(file, ist, engine); engine->add(group); } this->readNextToken(file, ist, str); //cerr << str << endl; } } catch (string str) { cerr << "Loader::loadFile caught exception ************" << endl; cerr << str << endl; cerr << "When loading file: " << fn << endl; cerr << "At line: " << m_iLineNumber << endl; cerr << "Loader::loadFile *****************************" << endl; return -1; } return 0; } #ifdef RZR_PATCHES_3DS //----------------------------------------------------- /// load all scene in one shape void Loader::loadShape3dsAscii(ifstream & file, istringstream & ist, Engine *, Group * group, Behavior *) { string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); Shape3D* shape = 0; string filename = string(Config::getInstance()->getDataSubDir()) + "/" + str; //EM_COUT( filename , 1); int t = 0; shape = new Shape3D; t = Obj3dsUtil::read( *shape , filename.c_str()); if ( t < 0 || shape == 0 ) { delete shape; return;} if ( shape->m_sMaterialName != "" ) { //EM_COUT( shape->m_sMaterialName , 1); filename = string(Config::getInstance()->getDataSubDir()) + "/" + shape->m_sMaterialName; EmTexture * tex = TextureUtil::getInstance()->loadTexture(filename.c_str()); if (tex != NULL) { shape->setTexture(tex); shape->setColor(1,1,1,0); //EM_COUT("loaded and asssigned :"<countNormals(); group->addShape3D(shape); this->readNextToken(file, ist, str); while (str != "}") { this->readNextToken(file, ist, str); } //EM_COUT("- Loader::loadShape3dsAscii", 0); } void Loader::loadGroup3dsAscii(ifstream & file, istringstream & ist, Engine *, Group * group, Behavior *) { EM_COUT("Loader::loadShape3dsAscii", 0); string str; EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, str); Group* arg = new Group; Shape3D* shape = 0; string filename = string(Config::getInstance()->getDataSubDir()) + "/" + str; //EM_COUT( filename , 1); int t = 0; t = Obj3dsUtil::read( *arg , filename.c_str()); if ( t < 0 ) { delete arg; return;} EmReadCmp(file, ist, str, "}"); //debug("copy to current group"); #if 1 group->add(arg); #else for(int i=0;igetShape3DSize(); i++) { shape = arg->getShape3D(i); shape->countNormals(); group->addShape3D( shape); } //TODO delete group #endif #if 0 //debug("read aliases"); /* material { overide "Material #1" { texture "file.png" } overide "Material #1" { color "rbga" } overide "*" { texture "file2.png" } } */ string key,value; map aliases; this->readNextToken(file, ist, str); if (str == "material") { EmReadCmp(file, ist, str, "{"); this->readNextToken(file, ist, key); this->readNextToken(file, ist, value); EmReadCmp(file, ist, str, "}"); //map.insert(key, value); } //this->readNextToken(file, ist, str); #endif //debug("assign textures"); for(int i=0; i < arg->getShape3DSize() ; i++) { shape = arg->getShape3D(i); if ( shape->m_sMaterialName != "" ) { EM_COUT( shape->m_sMaterialName , 1); filename = string(Config::getInstance()->getDataSubDir()) + "/" + shape->m_sMaterialName; EmTexture * tex = TextureUtil::getInstance()->loadTexture(filename.c_str()); if (tex != NULL) { shape->setTexture(tex); shape->setColor(1,1,1,0); } } } #if 0 //collision part , need some help float size = group->getCollisionSize(); debugf(". add collision_size=%f\n",size); CollisionBounds* bounds = new CollisionBounds(size); for(int i=0;igetShape3DSize(); i++) { shape = arg->getShape3D(i); if ( size > 16) { bounds->setShape3D(shape, 4); //4 } else if ( size > 8) { bounds->setShape3D(shape, 3); //4 } else if ( size > 4) { bounds->setShape3D(shape, 2); //4 } else if ( size > 2) { bounds->setShape3D(shape, 1); //4 } else { bounds->setShape3D(shape, 1); } } //debugf(". group collision slow\n"); group->setCollisionBounds(bounds); #endif EM_COUT("-Loader::loadShape3dsAscii", 0); } #endif //-------------------------------------------------------------------- //EOF $Id: Loader.cpp,v 1.33 2003/06/16 13:06:12 rzr Exp $