/* 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. ### File Specific: main-programmer: Benjamin Grauer co-programmer: ... */ #include "objModel.h" /** \brief Crates a 3D-Model and loads in a File. \param fileName file to parse and load (must be a .obj file) */ OBJModel::OBJModel(char* fileName) { this->initializeOBJ(); this->importFile (fileName); this->importToGL (); this->cleanup(); } /** \brief Crates a 3D-Model, loads in a File and scales it. \param fileName file to parse and load (must be a .obj file) \param scaling The factor that the model will be scaled with. */ OBJModel::OBJModel(char* fileName, float scaling) { this->initializeOBJ(); this->scaleFactor = scaling; this->importFile (fileName); this->importToGL (); this->cleanup(); } /** \brief deletes an OBJModel. Looks if any from model allocated space is still in use, and if so deleted it. */ OBJModel::~OBJModel() { PRINTF(4)("Deleting the obj-names\n"); if (this->objPath) delete []this->objPath; if (this->objFileName) delete []this->objFileName; if (this->mtlFileName) delete []this->mtlFileName; } /** \brief Initializes an obj-model */ void OBJModel::initializeOBJ(void) { this->objPath = NULL; this->objFileName = NULL; this->mtlFileName = NULL; this->initialize(); } /** \brief Imports a obj file and handles the the relative location \param fileName The file to import */ bool OBJModel::importFile (char* fileName) { PRINTF(3)("preparing to read in file: %s\n", fileName); #ifdef __WIN32__ // win32 path reading char pathSplitter= '\\'; #else /* __WIN32__ */ // unix path reading char pathSplitter='/'; #endif /* __WIN32__ */ char* tmpName = fileName; if (tmpName[0] == pathSplitter) tmpName++; char* name = tmpName; while (( tmpName = strchr (tmpName+1, pathSplitter))) { name = tmpName+1; } this->objPath = new char[name-fileName+1]; strncpy(this->objPath, fileName, name-fileName); this->objPath[name-fileName] = '\0'; if (verbose>=2) if (strlen(objPath)> 0) PRINTF(0)("Resolved file %s to folder: %s.\n", name, objPath); else PRINTF(0)("Resolved file %s.\n", name); this->setName(name); if (this->material) this->material->addTexturePath(this->objPath); this->objFileName = new char[strlen(name)+1]; strcpy (this->objFileName, name); this->readFromObjFile (); return true; } /** \brief Reads in the .obj File and sets all the Values. This function does read the file, parses it for the occurence of things like vertices, faces and so on, and executes the specific tasks */ bool OBJModel::readFromObjFile (void) { char* fileName = new char [strlen(objPath)+strlen(objFileName)+1]; if (this->objFileName != NULL && !strcmp(this->objFileName, "")) return false; strcpy(fileName, this->objPath); strcat(fileName, this->objFileName); ifstream* OBJ_FILE = new ifstream(fileName); if (OBJ_FILE->fail()) { PRINTF(1)("unable to open .OBJ file: %s\n Loading cube-Model instead.\n", fileName); cubeModel(); OBJ_FILE->close(); delete []fileName; delete OBJ_FILE; return false; } PRINTF(2)("Reading from opened file %s\n", fileName); char Buffer[10000]; while(!OBJ_FILE->eof()) { OBJ_FILE->getline(Buffer, 10000); PRINTF(3)("Read input line: %s\n", Buffer); // case vertice if (!strncmp(Buffer, "v ", 2)) { this->addVertex(Buffer+2); } // case face else if (!strncmp(Buffer, "f ", 2)) { this->addFace (Buffer+2); } else if (!strncmp(Buffer, "mtllib ", 7)) { this->readMtlLib (Buffer+7); } else if (!strncmp(Buffer, "usemtl ", 7)) { this->addUseMtl (Buffer+7); } // case VertexNormal else if (!strncmp(Buffer, "vn ", 3)) { this->addVertexNormal(Buffer+3); } // case VertexTextureCoordinate else if (!strncmp(Buffer, "vt ", 3)) { this->addVertexTexture(Buffer+3); } // case group else if (!strncmp(Buffer, "g ", 2)) { this->addGroup (Buffer+2); } else if (!strncmp(Buffer, "s ", 2)) //! \todo smoothing groups have to be implemented { if (verbose >= 2) PRINTF(2)("smoothing groups not supportet yet. line: %s\n", Buffer); } } OBJ_FILE->close(); delete OBJ_FILE; delete []fileName; return true; } /** \brief Function to read in a mtl File. \param mtlFile The .mtl file to read This Function parses all Lines of an mtl File. The reason for it not to be in the materials-class is, that a material does not have to be able to read itself in from a File. */ bool OBJModel::readMtlLib (char* mtlFile) { this->mtlFileName = new char [strlen(mtlFile)+1]; strcpy(this->mtlFileName, mtlFile); char* fileName = new char [strlen(objPath) + strlen(this->mtlFileName)+1]; strcpy(fileName, this->objPath); strcat(fileName, this->mtlFileName); PRINTF(3)("Opening mtlFile: %s\n", fileName); ifstream* MTL_FILE = new ifstream (fileName); if (MTL_FILE->fail()) { PRINTF(1)("unable to open file: %s\n", fileName); MTL_FILE->close(); delete []fileName; delete MTL_FILE; return false; } char Buffer[500]; Material* tmpMat = material; while(!MTL_FILE->eof()) { MTL_FILE->getline(Buffer, 500); PRINTF(4)("found line in mtlFile: %s\n", Buffer); // create new Material if (!strncmp(Buffer, "newmtl ", 7)) { tmpMat = tmpMat->addMaterial(Buffer+7); // PRINTF(2)("%s, %p\n", tmpMat->getName(), tmpMat); } // setting a illumMode else if (!strncmp(Buffer, "illum ", 6)) { tmpMat->setIllum(Buffer+6); } // setting Diffuse Color else if (!strncmp(Buffer, "Kd ", 3)) { tmpMat->setDiffuse(Buffer+3); } // setting Ambient Color else if (!strncmp(Buffer, "Ka ", 3)) { tmpMat->setAmbient(Buffer+3); } // setting Specular Color else if (!strncmp(Buffer, "Ks ", 3)) { tmpMat->setSpecular(Buffer+3); } // setting The Specular Shininess else if (!strncmp(Buffer, "Ns ", 3)) { tmpMat->setShininess(Buffer+3); } // setting up transparency else if (!strncmp(Buffer, "d ", 2)) { tmpMat->setTransparency(Buffer+2); } else if (!strncmp(Buffer, "Tf ", 3)) { tmpMat->setTransparency(Buffer+3); } else if (!strncmp(Buffer, "map_Kd ", 7)) { tmpMat->setDiffuseMap(Buffer+7); } else if (!strncmp(Buffer, "map_Ka ", 7)) { tmpMat->setAmbientMap(Buffer+7); } else if (!strncmp(Buffer, "map_Ks ", 7)) { tmpMat->setSpecularMap(Buffer+7); } else if (!strncmp(Buffer, "bump ", 5)) { tmpMat->setBump(Buffer+7); } } MTL_FILE->close(); delete []fileName; delete MTL_FILE; return true; }