/* 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: ... */ #define DEBUG_SPECIAL_MODULE DEBUG_MODULE_IMPORTER #include "objModel.h" #include #include #include #define PARSELINELENGTH 8192 #include "debug.h" #include "compiler.h" /** \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(const char* fileName, float scaling) : Model(fileName) { this->objPath = "./"; this->scaleFactor = scaling; this->importFile (fileName); this->finalize(); } /** \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; } /** \brief Imports a obj file and handles the the relative location \param fileName The file to import Splits the FileName from the DirectoryName */ bool OBJModel::importFile (const char* fileName) { PRINTF(4)("preparing to read in file: %s\n", fileName); // splitting the char* split = NULL; if (!(split = strrchr(fileName, '/'))) split = strrchr(fileName, '\\'); // windows Case if (split) { int len = split - fileName+1; this->objPath = new char[len +2]; strncpy(this->objPath, fileName, len); this->objPath[len] = '\0'; PRINTF(1)("Resolved file %s to Path %s.\n", fileName, this->objPath); } this->readFromObjFile (fileName); 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(const char* fileName) { FILE* stream; if( (stream = fopen (fileName, "r")) == NULL) { printf("Object File Could not be Opened %s\n", fileName); return false; } char buffer[PARSELINELENGTH]; while(fgets(buffer, PARSELINELENGTH, stream)) { // line termiated with \0 not \n if (buffer[strlen(buffer)-1] == '\n') buffer[strlen(buffer)-1] = '\0'; // 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->setMaterial (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 { PRINTF(2)("smoothing groups not supportet yet. line: %s\n", buffer); } } fclose (stream); 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 (const char* mtlFile) { char* fileName = new char [strlen(this->objPath) + strlen(mtlFile)+1]; sprintf(fileName, "%s%s", this->objPath, mtlFile); FILE* stream; if( (stream = fopen (fileName, "r")) == NULL) { PRINTF(2)("MaterialLibrary could not be opened %s\n", fileName); delete []fileName; return false; } char buffer[PARSELINELENGTH]; Material* tmpMat = NULL; while(fgets(buffer, PARSELINELENGTH, stream)) { PRINTF(5)("found line in mtlFile: %s\n", buffer); // line termiated with \0 not \n if (buffer[strlen(buffer)-1] == '\n') buffer[strlen(buffer)-1] = '\0'; // create new Material if (!strncmp(buffer, "newmtl ", 7)) { tmpMat = this->addMaterial(buffer+7);//tmpMat->addMaterial(buffer+7); } // setting a illumMode else if (!strncmp(buffer, "illum ", 6)) { if (likely(tmpMat != NULL)) tmpMat->setIllum(buffer+6); } // setting Diffuse Color else if (!strncmp(buffer, "Kd ", 3)) { if (likely(tmpMat != NULL)) tmpMat->setDiffuse(buffer+3); } // setting Ambient Color else if (!strncmp(buffer, "Ka ", 3)) { if (likely(tmpMat != NULL)) tmpMat->setAmbient(buffer+3); } // setting Specular Color else if (!strncmp(buffer, "Ks ", 3)) { if (likely(tmpMat != NULL)) tmpMat->setSpecular(buffer+3); } // setting The Specular Shininess else if (!strncmp(buffer, "Ns ", 3)) { if (likely(tmpMat != NULL)) tmpMat->setShininess(buffer+3); } // setting up transparency else if (!strncmp(buffer, "d ", 2)) { if (likely(tmpMat != NULL)) tmpMat->setTransparency(buffer+2); } else if (!strncmp(buffer, "Tf ", 3)) { if (likely(tmpMat != NULL)) tmpMat->setTransparency(buffer+3); } else if (!strncmp(buffer, "map_Kd ", 7)) { if (likely(tmpMat != NULL)) tmpMat->setDiffuseMap(buffer+7); } else if (!strncmp(buffer, "map_Ka ", 7)) { if (likely(tmpMat != NULL)) tmpMat->setAmbientMap(buffer+7); } else if (!strncmp(buffer, "map_Ks ", 7)) { if (likely(tmpMat != NULL)) tmpMat->setSpecularMap(buffer+7); } else if (!strncmp(buffer, "bump ", 5)) { if (likely(tmpMat != NULL)) tmpMat->setBump(buffer+7); } } fclose(stream); delete []fileName; return true; }