/* 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" /** * 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 std::string& fileName, float scaling) : StaticModel(fileName) { this->setClassID(CL_OBJ_MODEL, "OBJModel"); this->objPath = "./"; this->scaleFactor = scaling; this->importFile (fileName); this->finalize(); } /** * deletes an OBJModel. Looks if any from model allocated space is still in use, and if so deleted it. */ OBJModel::~OBJModel() { } /** * 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 std::string& fileNameInput) { const char* fileName = fileNameInput.c_str(); 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 = fileName; this->objPath.erase(len, this->objPath.size()); this->objPath[len] = '\0'; PRINTF(4)("Resolved file %s to Path %s.\n", fileName, this->objPath.c_str()); } else this->objPath = "./"; Material::addTexturePath(this->objPath); this->readFromObjFile (fileName); return true; } /** * 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 std::string& fileName) { FILE* stream; if( (stream = fopen (fileName.c_str(), "r")) == NULL) { PRINTF(2)("Object File Could not be Opened %s\n", fileName.c_str()); 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(3)("smoothing groups not supportet yet. line: %s\n", buffer); } } fclose (stream); return true; } /** * 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 std::string& mtlFile) { std::string fileName = this->objPath + mtlFile; FILE* stream; if( (stream = fopen (fileName.c_str(), "r")) == NULL) { PRINTF(2)("MaterialLibrary could not be opened %s\n", fileName.c_str()); return false; } char buffer[PARSELINELENGTH]; Material* tmpMat = NULL; while(fgets(buffer, PARSELINELENGTH, stream) != NULL) { 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); return true; }