/* orxonox - the future of 3D-vertical-scrollers Copyright (C) 2004 orx This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ### File Specific: main-programmer: Patrick Boenzli co-programmer: Christian Meyer co-programmer: Benjamin Grauer: injected ResourceManager/GraphicsEngine/GUI */ #include "orxonox.h" #include "gui.h" #include "world.h" #include "data_tank.h" #include "command_node.h" #include "game_loader.h" #include "graphics_engine.h" #include "resource_manager.h" #include "text_engine.h" #include "factory.h" #include int verbose = 4; using namespace std; /** \brief create a new Orxonox */ Orxonox::Orxonox () { this->pause = false; this->world = NULL; this->resources = NULL; this->localinput = NULL; } /** \brief remove Orxonox from memory */ Orxonox::~Orxonox () { int i =0; Orxonox::singletonRef = NULL; if( world != NULL) delete world; if( localinput != NULL) delete localinput; if( resources != NULL) delete resources; delete GraphicsEngine::getInstance(); // deleting the Graphics delete ResourceManager::getInstance(); // deletes the Resource Manager delete TextEngine::getInstance(); } /** \brief this is a singleton class to prevent duplicates */ Orxonox* Orxonox::singletonRef = 0; /** \returns reference or new Object of Orxonox if not existent. */ Orxonox* Orxonox::getInstance (void) { if (singletonRef == NULL) singletonRef = new Orxonox(); return singletonRef; } /** \brief this finds the config file Since the config file varies from user to user and since one may want to specify different config files for certain occasions or platforms this function finds the right config file for every occasion and stores it's path and name into configfilename */ void Orxonox::getConfigFile (int argc, char** argv) { strcpy (configfilename, "~/.orxonox/orxonox.conf"); } /** \brief initialize Orxonox with command line */ int Orxonox::init (int argc, char** argv) { // parse command line // config file getConfigFile (argc, argv); SDL_Init (SDL_INIT_TIMER); // initialize everything if( initVideo() == -1) return -1; if( initSound() == -1) return -1; printf("> Initializing input\n"); if( initInput() == -1) return -1; printf("> Initializing networking\n"); if( initNetworking () == -1) return -1; printf("> Initializing resources\n"); if( initResources () == -1) return -1; //printf("> Initializing world\n"); //if( init_world () == -1) return -1; PB: world will be initialized when started return 0; } /** \brief initializes SDL and OpenGL */ int Orxonox::initVideo() { PRINTF(3)("> Initializing video\n"); GraphicsEngine::getInstance(); return 0; } /** \brief initializes the sound engine */ int Orxonox::initSound() { printf("> Initializing sound\n"); // SDL_Init(SDL_INIT_AUDIO); printf("Not yet implemented\n"); return 0; } /** \brief initializes input functions */ int Orxonox::initInput() { // create localinput localinput = new CommandNode(configfilename); return 0; } /** \brief initializes network system */ int Orxonox::initNetworking() { printf("Not yet implemented\n"); return 0; } /** \brief initializes and loads resource files */ int Orxonox::initResources() { // printf("Not yet implemented\n"); PRINT(3)("initializing ResourceManager\n"); resourceManager = ResourceManager::getInstance(); if (!resourceManager->setDataDir("../data/")) { PRINTF(1)("Data Could not be located\n"); exit(-1); } PRINT(3)("initializing TextEngine\n"); TextEngine::getInstance(); } /** \brief initializes the world */ int Orxonox::initWorld() { //world = new World(); // TO DO: replace this with a menu/intro //world->load_debug_level(); return 0; } /** \brief starts the orxonox game or menu here is the central orxonox state manager. There are currently two states - menu - game-play both states manage their states themselfs again. */ void Orxonox::start() { this->gameLoader = GameLoader::getInstance(); this->gameLoader->loadCampaign("../data/worlds/DefaultCampaign.oxc"); // this->gameLoader->loadDebugCampaign(DEBUG_CAMPAIGN_0); this->gameLoader->init(); this->gameLoader->start(); } /** \brief exits Orxonox */ void Orxonox::quitGame() { bQuitOrxonox = true; } /** \brief handles sprecial events from localinput \param event: an event not handled by the CommandNode */ void Orxonox::eventHandler(SDL_Event* event) { // Handle special events such as reshape, quit, focus changes switch (event->type) { case SDL_VIDEORESIZE: GraphicsEngine* tmpGEngine = GraphicsEngine::getInstance(); tmpGEngine->resolutionChanged(&event->resize); break; } } /** \brief handle keyboard commands that are not meant for WorldEntities \param cmd: the command to handle \return true if the command was handled by the system or false if it may be passed to the WorldEntities */ bool Orxonox::systemCommand(Command* cmd) { /* if( !strcmp( cmd->cmd, "quit")) { if( !cmd->bUp) this->gameLoader->stop(); return true; } return false; */ return false; } /** \brief retrieve a pointer to the local CommandNode \return a pointer to localinput */ CommandNode* Orxonox::getLocalInput() { return localinput; } /** \brief retrieve a pointer to the local World \return a pointer to world */ World* Orxonox::getWorld() { return world; } /** \return The reference of the SDL-screen of orxonox */ SDL_Surface* Orxonox::getScreen () { return this->screen; } bool showGui = false; /** \brief main function here the journey begins */ int main(int argc, char** argv) { /* reading arguments currently supported arguments are: :: just starts orxonox --benchmark :: start the benchmark without starting orxonox this is a preselection: it matches to one of the start* functions, the finetuning is made in those functions. */ int i; for(i = 1; i < argc; ++i) { if(! strcmp( "--help", argv[i])) return startHelp(); else if(! strcmp( "--benchmark", argv[i])) return startBenchmarks(); else if(! strcmp( "--gui", argv[i]) || !strcmp("-g", argv[i])) showGui = true; else PRINTF(2)("Orxonox does not understand the arguments %s\n", argv[i]); } return startOrxonox(argc, argv); } int startHelp() { PRINT(0)("orxonox: starts the orxonox game - rules\n"); PRINT(0)("usage: orxonox [arg]\n\n"); PRINT(0)("valid options:\n"); PRINT(0)(" --benchmark\tstarts the orxonox benchmark\n"); PRINT(0)(" --help \tshows this menu\n"); PRINT(0)(" --gui/-g \tDisplays the Gui on startup\n"); } int startOrxonox(int argc, char** argv) { // checking for existence of the configuration-files if (showGui || !ResourceManager::isFile("~/.orxonox/orxonox.conf") || ResourceManager::isFile("~/.orxonox/orxonox.lock")) { if (ResourceManager::isFile("~/.orxonox/orxonox.lock")) ResourceManager::deleteFile("~/.orxonox/orxonox.lock"); // char* guiExec = new char[strlen(argv[0])+20]; // sprintf(guiExec,"%sGui --gui", argv[0]); Gui* gui = new Gui(argc, argv); if (! gui->startOrxonox) return 0; delete gui; } PRINT(0)(">>> Starting Orxonox <<<\n"); ResourceManager::touchFile("~/.orxonox/orxonox.lock"); Orxonox *orx = Orxonox::getInstance(); if((*orx).init(argc, argv) == -1) { PRINTF(1)("! Orxonox initialization failed\n"); return -1; } orx->start(); delete orx; ResourceManager::deleteFile("~/.orxonox/orxonox.lock"); } #if defined __linux__ #include "list.h" #include "world_entity.h" #include "vector.h" #include "player.h" #include "base_object.h" #include #include #define LIST_MAX 1000 #define VECTOR_MAX 1000000 #define ITERATIONS 10000 int startBenchmarks() { printf("===========================================================\n"); printf("= BENCHMARKS =\n"); printf("===========================================================\n"); printf(" the author is not paying any attention to cacheing effects\n"); printf(" of the CPU.\n\n"); printf("[title]\t\t\t\t\t [cycles]\t[loops]\n\n"); // printf("------------------------------------------------------------\n\n"); // first measure the time overhead: unsigned long ini, end, dt, tmp; rdtscl(ini); rdtscl(end); dt = end - ini; int type = -1; /* type -1 == all type 0 == framework type 1 == vector type 2 == quaternion type 3 == lists */ if(type == 0 || type == -1) { /* framework test*/ printf("Generating Objects:\t\t\t\t\t%i\n", ITERATIONS); /* ************WorldEntity class test************** */ WorldEntity* w = NULL; int i = 0; unsigned long mittel = 0; for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); WorldEntity* w = new WorldEntity(); rdtscl(end); delete w; mittel += (end - ini - dt); } float mi = mittel / (float)ITERATIONS; printf(" Generate a WorldEntity object:\t\t%11.2f\n", mi); /* mittel = 0; for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); WorldEntity* w = new Primitive(P_SPHERE); rdtscl(end); delete w; mittel += (end - ini - dt); } mi = mittel / (float)ITERATIONS; printf(" Generate a Primitive object:\t\t%11.2f\n", mi); */ mittel = 0; for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); Vector* v = new Vector(); rdtscl(end); delete v; mittel += (end - ini - dt); } mi = mittel / (float)ITERATIONS; printf(" Generate a Vector object:\t\t%11.2f\n", mi); mittel = 0; for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); Quaternion* q = new Quaternion(); rdtscl(end); delete q; mittel += (end - ini - dt); } mi = mittel / (float)ITERATIONS; printf(" Generate a Quaternion object:\t\t%11.2f\n", mi); printf("\nCalling function inline &| virtual, \t\t\t%i\n", ITERATIONS); mittel = 0; w = new WorldEntity(); for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); w->tick(0.0f); rdtscl(end); mittel += (end - ini - dt); } //delete w; mi = mittel / (float)ITERATIONS; printf(" Virt funct tick() of WE: \t\t%11.2f\n", mi); mittel = 0; WorldEntity wo; for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); wo.tick(0.0f); rdtscl(end); mittel += (end - ini - dt); } //delete w; mi = mittel / (float)ITERATIONS; printf(" Inl virt funct tick() of WE v2: \t%11.2f\n", mi); mittel = 0; BaseObject* bo = new BaseObject(); for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); bo->isFinalized(); rdtscl(end); mittel += (end - ini - dt); } //delete w; mi = mittel / (float)ITERATIONS; printf(" Inl funct BaseObject::isFinazlized(): \t%11.2f\n", mi); tList* list = new tList(); /* ************Primitvie class test************** */ list = new tList(); /* mittel = 0; w = new Primitive(P_SPHERE); for(i = 0; i < ITERATIONS; ++i) { rdtscl(ini); w->tick(0.0f); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)ITERATIONS; printf(" Call function tick() of Prim:\t\t%11.2f\n", mi); */ } if(type == 1 || type == -1) { printf("\nDoing some simple vector operations: \t\t\t%i\n", VECTOR_MAX); /* vector test */ Vector* a = new Vector(1.3, 5.3, 4.1); Vector* b = new Vector(0.4, 2.5, 6.2); Vector* c = new Vector(); unsigned long mittel, ini, end; float mi; int i = 0; // addition mittel = 0; for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); *c = *a + *b; rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)VECTOR_MAX; printf(" Addition of two vectors:\t\t%11.2f\n", mi); // multiplikation mittel = 0; for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); *c = a->cross( *b); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)VECTOR_MAX; printf(" CrossMult of two vectors:\t\t%11.2f\n", mi); } if( type == 2 || type == -1) { /* quaternion test */ printf("\nDoing some simple quaternion operations: \t\t%i\n", VECTOR_MAX); /* vector test */ Quaternion* a = new Quaternion(); Quaternion* b = new Quaternion(); Quaternion* c = new Quaternion(); unsigned long mittel, ini, end; float mi; int i = 0; // quaternion generieren mit spez konstruktor mittel = 0; Vector* qa = new Vector(4.6, 9.3, 0.4); Vector* qb = new Vector(3.5, 6.1, 4.3); for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); Quaternion* qu = new Quaternion(*qa, *qb); rdtscl(end); delete qu; mittel += (end - ini - dt); } delete a; delete b; mi = mittel / (float)VECTOR_MAX; printf(" Gen. quatern. betw. two vectors:\t%11.2f\n", mi); // multiplication mittel = 0; for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); *c = *a * *b; rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)VECTOR_MAX; printf(" Multiplying two quat.(=rot): a * b\t%11.2f\n", mi); // rotating a vector by a quaternion mittel = 0; for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); *qa = a->apply(*qb); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)VECTOR_MAX; printf(" Rot a vec by a quat: q->apply(v)\t%11.2f\n", mi); // generate rotation matrix mittel = 0; float matrix[4][4]; for(i = 0; i < VECTOR_MAX; ++i) { rdtscl(ini); a->matrix(matrix); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)VECTOR_MAX; printf(" Generate rot matrix: q->matrix(m)\t%11.2f\n", mi); } if( type == 3 || type == -1) { /* list tests*/ printf("\nList operations tests: \t\t\t\t\t%i\n", LIST_MAX); tList* list = new tList(); char* name; printf(" Adding[1..10] elements to list, found:\n"); list->add("1"); list->add("2"); list->add("3"); list->add("4"); list->add("5"); list->add("6"); list->add("7"); list->add("8"); list->add("9"); list->add("10"); /*give list out */ tIterator* iterator = list->getIterator(); name = iterator->nextElement(); printf(" List Elements: \t\t"); while( name != NULL) { printf("%s,", name); name = iterator->nextElement(); } delete iterator; printf("\n"); /*removing some elements from the list*/ printf(" Removing elements [2,3,6,8,10], adding [11] now found:\n"); list->remove("2"); list->remove("3"); list->remove("6"); list->remove("8"); list->remove("10"); list->add("11"); /*give list out */ iterator = list->getIterator(); name = iterator->nextElement(); printf(" List Elements: \t\t"); while( name != NULL) { printf("%s,", name); name = iterator->nextElement(); } delete iterator; printf("\n"); delete list; printf("\nChecking list performance:\t\t\t\t%i\n", LIST_MAX); tList* plist = new tList(); unsigned long mittel, ini, end; float mi; int i = 0; mittel = 0; for(i = 0; i < LIST_MAX; ++i) { rdtscl(ini); plist->add(&i); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)LIST_MAX; printf(" Adding reference to list:\t\t%11.2f\n", mi); mittel = 0; for(i = 0; i < LIST_MAX; ++i) { rdtscl(ini); plist->remove(&i); rdtscl(end); mittel += (end - ini - dt); } mi = mittel / (float)LIST_MAX; printf(" Removing 1st reference from list:\t%11.2f\n", mi); printf("\nList operations tests: \t\t\t\t\t%i\n", LIST_MAX); list = new tList(); printf(" Adding[1..10] elements to list, found:\n"); list->add("1"); list->add("2"); list->add("3"); list->add("4"); list->add("5"); list->add("6"); list->add("7"); list->add("8"); list->add("9"); list->add("10"); /*give list out */ iterator = list->getIterator(); name = iterator->nextElement(); printf(" List Elements: \t\t"); while( name != NULL) { printf("%s,", name); name = iterator->nextElement(); } delete iterator; printf("\n"); int c = 0; printf(" Going trough list with nextElement(el) func: "); name = list->firstElement(); while(c < 20) { printf("%s,", name); name = list->nextElement(name); c++; } printf("\n"); } } #else int startBenchmarks() { PRINTF(1)("Benchmark is not implemented in this system\n"); } #endif