/* 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 #define PARSELINELENGTH 8192 #include "debug.h" #include "compiler.h" ObjectListDefinition(OBJModel); /** * @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 std::string& fileName, float scaling) : StaticModel(fileName) { this->registerObject(this, OBJModel::_objectList); this->objPath = "./"; this->setScaleFactor(scaling); this->importFile (fileName); this->finalize(); } /** * @brief deletes an OBJModel. */ 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; } /** * @brief Reads in the .obj File and sets all the Values. * @param fileName the FileName of the Model. * * 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; } /** * @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 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)) setIllum(tmpMat, buffer+6); } // setting Diffuse Color else if (!strncmp(buffer, "Kd ", 3)) { if (likely(tmpMat != NULL)) setDiffuse(tmpMat, buffer+3); } // setting Ambient Color else if (!strncmp(buffer, "Ka ", 3)) { if (likely(tmpMat != NULL)) setAmbient(tmpMat, buffer+3); } // setting Specular Color else if (!strncmp(buffer, "Ks ", 3)) { if (likely(tmpMat != NULL)) setSpecular(tmpMat, buffer+3); } // setting The Specular Shininess else if (!strncmp(buffer, "Ns ", 3)) { if (likely(tmpMat != NULL)) setShininess(tmpMat, buffer+3); } // setting up transparency else if (!strncmp(buffer, "d ", 2)) { if (likely(tmpMat != NULL)) setTransparency(tmpMat, buffer+2); } else if (!strncmp(buffer, "Tf ", 3)) { if (likely(tmpMat != NULL)) setTransparency(tmpMat, 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; } /** * @brief Sets the Material Illumination Model. * @param material: the Material to apply the change to. * @param illu: illumination Model in char* form */ void OBJModel::setIllum (Material* material, const char* illum) { material->setIllum (atoi(illum)); } /** * @brief Sets the Material Diffuse Color. * @param material: the Material to apply the change to. * @param rgb The red, green, blue channel in char format (with spaces between them) */ void OBJModel::setDiffuse (Material* material, const char* rgb) { float r,g,b; sscanf (rgb, "%f %f %f", &r, &g, &b); material->setDiffuse (r, g, b); } /** * @brief Sets the Material Ambient Color. * @param material: the Material to apply the change to. * @param rgb The red, green, blue channel in char format (with spaces between them) */ void OBJModel::setAmbient (Material* material, const char* rgb) { float r,g,b; sscanf (rgb, "%f %f %f", &r, &g, &b); material->setAmbient (r, g, b); } /** * @brief Sets the Material Specular Color. * @param material: the Material to apply the change to. * @param rgb The red, green, blue channel in char format (with spaces between them) */ void OBJModel::setSpecular (Material* material, const char* rgb) { float r,g,b; sscanf (rgb, "%f %f %f", &r, &g, &b); material->setSpecular (r, g, b); } /** * @brief Sets the Material Shininess. * @param material: the Material to apply the change to. * @param shini stes the Shininess from char*. */ void OBJModel::setShininess (Material* material, const char* shini) { material->setShininess (atof(shini)); } /** * @brief Sets the Material Transparency. * @param material: the Material to apply the change to. * @param trans stes the Transparency from char*. */ void OBJModel::setTransparency (Material* material, const char* trans) { material->setTransparency (atof(trans)); }