| [3396] | 1 | /*  | 
|---|
 | 2 |    orxonox - the future of 3D-vertical-scrollers | 
|---|
 | 3 |  | 
|---|
 | 4 |    Copyright (C) 2004 orx | 
|---|
 | 5 |  | 
|---|
 | 6 |    This program is free software; you can redistribute it and/or modify | 
|---|
 | 7 |    it under the terms of the GNU General Public License as published by | 
|---|
 | 8 |    the Free Software Foundation; either version 2, or (at your option) | 
|---|
 | 9 |    any later version. | 
|---|
 | 10 |  | 
|---|
 | 11 |    ### File Specific: | 
|---|
 | 12 |    main-programmer: Benjamin Grauer | 
|---|
 | 13 |    co-programmer: ... | 
|---|
 | 14 | */ | 
|---|
 | 15 |  | 
|---|
 | 16 | #include "objModel.h" | 
|---|
 | 17 |  | 
|---|
| [3427] | 18 | #include <fstream> | 
|---|
 | 19 |  | 
|---|
| [3475] | 20 | #include "debug.h" | 
|---|
| [3427] | 21 |  | 
|---|
| [3396] | 22 | /** | 
|---|
 | 23 |    \brief Crates a 3D-Model and loads in a File. | 
|---|
 | 24 |    \param fileName file to parse and load (must be a .obj file) | 
|---|
 | 25 | */ | 
|---|
 | 26 | OBJModel::OBJModel(char* fileName) | 
|---|
 | 27 | { | 
|---|
 | 28 |   this->initializeOBJ(); | 
|---|
 | 29 |  | 
|---|
 | 30 |   this->importFile (fileName); | 
|---|
 | 31 |  | 
|---|
 | 32 |   this->importToGL (); | 
|---|
 | 33 |  | 
|---|
 | 34 |   this->cleanup(); | 
|---|
 | 35 | } | 
|---|
 | 36 |  | 
|---|
 | 37 | /** | 
|---|
 | 38 |    \brief Crates a 3D-Model, loads in a File and scales it. | 
|---|
 | 39 |    \param fileName file to parse and load (must be a .obj file) | 
|---|
 | 40 |    \param scaling The factor that the model will be scaled with. | 
|---|
 | 41 | */ | 
|---|
 | 42 | OBJModel::OBJModel(char* fileName, float scaling) | 
|---|
 | 43 | { | 
|---|
 | 44 |   this->initializeOBJ(); | 
|---|
 | 45 |   this->scaleFactor = scaling; | 
|---|
 | 46 |  | 
|---|
 | 47 |   this->importFile (fileName); | 
|---|
 | 48 |  | 
|---|
 | 49 |   this->importToGL (); | 
|---|
 | 50 |  | 
|---|
 | 51 |   this->cleanup(); | 
|---|
 | 52 | } | 
|---|
 | 53 |  | 
|---|
 | 54 | /** | 
|---|
 | 55 |    \brief deletes an OBJModel. | 
|---|
 | 56 |  | 
|---|
 | 57 |    Looks if any from model allocated space is still in use, and if so deleted it. | 
|---|
 | 58 | */ | 
|---|
 | 59 | OBJModel::~OBJModel() | 
|---|
 | 60 | { | 
|---|
 | 61 |   PRINTF(4)("Deleting the obj-names\n"); | 
|---|
 | 62 |   if (this->objPath) | 
|---|
 | 63 |     delete []this->objPath; | 
|---|
 | 64 |   if (this->objFileName) | 
|---|
 | 65 |     delete []this->objFileName; | 
|---|
 | 66 |   if (this->mtlFileName) | 
|---|
 | 67 |     delete []this->mtlFileName; | 
|---|
 | 68 | } | 
|---|
 | 69 |  | 
|---|
 | 70 | /** | 
|---|
 | 71 |    \brief Initializes an obj-model | 
|---|
 | 72 | */ | 
|---|
 | 73 | void OBJModel::initializeOBJ(void) | 
|---|
 | 74 | { | 
|---|
 | 75 |   this->objPath = NULL; | 
|---|
 | 76 |   this->objFileName = NULL; | 
|---|
 | 77 |   this->mtlFileName = NULL; | 
|---|
 | 78 |  | 
|---|
 | 79 |   this->initialize(); | 
|---|
 | 80 | } | 
|---|
 | 81 |  | 
|---|
 | 82 | /** | 
|---|
 | 83 |    \brief Imports a obj file and handles the the relative location | 
|---|
 | 84 |    \param fileName The file to import | 
|---|
 | 85 | */ | 
|---|
 | 86 | bool OBJModel::importFile (char* fileName) | 
|---|
 | 87 | { | 
|---|
 | 88 |   PRINTF(3)("preparing to read in file: %s\n", fileName); | 
|---|
 | 89 |  | 
|---|
 | 90 |  | 
|---|
 | 91 | #ifdef __WIN32__ | 
|---|
 | 92 |   // win32 path reading | 
|---|
 | 93 |   char pathSplitter= '\\'; | 
|---|
 | 94 | #else /* __WIN32__ */ | 
|---|
 | 95 |   // unix path reading | 
|---|
 | 96 |   char pathSplitter='/'; | 
|---|
 | 97 | #endif /* __WIN32__ */ | 
|---|
 | 98 |   char* tmpName = fileName; | 
|---|
 | 99 |   if (tmpName[0] == pathSplitter) | 
|---|
 | 100 |     tmpName++; | 
|---|
 | 101 |   char* name = tmpName; | 
|---|
 | 102 |   while (( tmpName = strchr (tmpName+1, pathSplitter))) | 
|---|
 | 103 |     { | 
|---|
 | 104 |       name = tmpName+1; | 
|---|
 | 105 |     } | 
|---|
 | 106 |   this->objPath = new char[name-fileName+1]; | 
|---|
 | 107 |   strncpy(this->objPath, fileName, name-fileName); | 
|---|
 | 108 |   this->objPath[name-fileName] = '\0'; | 
|---|
 | 109 |   if (verbose>=2) | 
|---|
 | 110 |     if (strlen(objPath)> 0) | 
|---|
 | 111 |       PRINTF(0)("Resolved file %s to folder: %s.\n", name, objPath); | 
|---|
 | 112 |     else | 
|---|
 | 113 |       PRINTF(0)("Resolved file %s.\n", name); | 
|---|
 | 114 |    | 
|---|
| [3398] | 115 |   this->setName(name); | 
|---|
| [3396] | 116 |   if (this->material) | 
|---|
 | 117 |     this->material->addTexturePath(this->objPath); | 
|---|
 | 118 |   this->objFileName = new char[strlen(name)+1]; | 
|---|
 | 119 |   strcpy (this->objFileName, name); | 
|---|
 | 120 |   this->readFromObjFile (); | 
|---|
 | 121 |   return true; | 
|---|
 | 122 | } | 
|---|
 | 123 |  | 
|---|
 | 124 | /** | 
|---|
 | 125 |    \brief Reads in the .obj File and sets all the Values. | 
|---|
 | 126 |    This function does read the file, parses it for the occurence of things like vertices, faces and so on, and executes the specific tasks | 
|---|
 | 127 | */ | 
|---|
 | 128 | bool OBJModel::readFromObjFile (void) | 
|---|
 | 129 | { | 
|---|
 | 130 |   char* fileName = new char [strlen(objPath)+strlen(objFileName)+1]; | 
|---|
 | 131 |   if (this->objFileName != NULL && !strcmp(this->objFileName, "")) | 
|---|
 | 132 |     return false; | 
|---|
 | 133 |   strcpy(fileName, this->objPath); | 
|---|
 | 134 |   strcat(fileName, this->objFileName); | 
|---|
 | 135 |  | 
|---|
 | 136 |   ifstream* OBJ_FILE = new ifstream(fileName); | 
|---|
 | 137 |   if (OBJ_FILE->fail()) | 
|---|
 | 138 |     { | 
|---|
| [3400] | 139 |       PRINTF(1)("unable to open .OBJ file: %s\n Loading cube-Model instead.\n", fileName); | 
|---|
 | 140 |       cubeModel(); | 
|---|
| [3396] | 141 |       OBJ_FILE->close(); | 
|---|
 | 142 |       delete []fileName; | 
|---|
 | 143 |       delete OBJ_FILE; | 
|---|
 | 144 |       return false; | 
|---|
 | 145 |     } | 
|---|
 | 146 |   PRINTF(2)("Reading from opened file %s\n", fileName); | 
|---|
 | 147 |   char Buffer[10000]; | 
|---|
 | 148 |   while(!OBJ_FILE->eof()) | 
|---|
 | 149 |     { | 
|---|
 | 150 |       OBJ_FILE->getline(Buffer, 10000); | 
|---|
 | 151 |       PRINTF(3)("Read input line: %s\n", Buffer); | 
|---|
 | 152 |        | 
|---|
 | 153 |  | 
|---|
 | 154 |       // case vertice | 
|---|
 | 155 |       if (!strncmp(Buffer, "v ", 2)) | 
|---|
 | 156 |         { | 
|---|
 | 157 |           this->addVertex(Buffer+2); | 
|---|
 | 158 |         } | 
|---|
 | 159 |  | 
|---|
 | 160 |       // case face | 
|---|
 | 161 |       else if (!strncmp(Buffer, "f ", 2)) | 
|---|
 | 162 |         { | 
|---|
 | 163 |           this->addFace (Buffer+2); | 
|---|
 | 164 |         } | 
|---|
 | 165 |        | 
|---|
 | 166 |       else if (!strncmp(Buffer, "mtllib ", 7)) | 
|---|
 | 167 |         { | 
|---|
 | 168 |           this->readMtlLib (Buffer+7); | 
|---|
 | 169 |         } | 
|---|
 | 170 |  | 
|---|
 | 171 |       else if (!strncmp(Buffer, "usemtl ", 7)) | 
|---|
 | 172 |         { | 
|---|
 | 173 |           this->addUseMtl (Buffer+7); | 
|---|
 | 174 |         } | 
|---|
 | 175 |  | 
|---|
 | 176 |       // case VertexNormal | 
|---|
 | 177 |       else if (!strncmp(Buffer, "vn ", 3)) | 
|---|
 | 178 |         { | 
|---|
 | 179 |           this->addVertexNormal(Buffer+3); | 
|---|
 | 180 |         } | 
|---|
 | 181 |        | 
|---|
 | 182 |       // case VertexTextureCoordinate | 
|---|
 | 183 |       else if (!strncmp(Buffer, "vt ", 3)) | 
|---|
 | 184 |         { | 
|---|
 | 185 |           this->addVertexTexture(Buffer+3); | 
|---|
 | 186 |         } | 
|---|
 | 187 |       // case group | 
|---|
 | 188 |       else if (!strncmp(Buffer, "g ", 2)) | 
|---|
 | 189 |         { | 
|---|
 | 190 |           this->addGroup (Buffer+2); | 
|---|
 | 191 |         } | 
|---|
 | 192 |       else if (!strncmp(Buffer, "s ", 2)) //! \todo smoothing groups have to be implemented | 
|---|
 | 193 |         { | 
|---|
 | 194 |           if (verbose >= 2) | 
|---|
 | 195 |             PRINTF(2)("smoothing groups not supportet yet. line: %s\n", Buffer); | 
|---|
 | 196 |         } | 
|---|
 | 197 |     } | 
|---|
 | 198 |   OBJ_FILE->close(); | 
|---|
 | 199 |   delete OBJ_FILE; | 
|---|
 | 200 |   delete []fileName; | 
|---|
 | 201 |   return true; | 
|---|
 | 202 |  | 
|---|
 | 203 | } | 
|---|
 | 204 |  | 
|---|
 | 205 | /**  | 
|---|
 | 206 |     \brief Function to read in a mtl File. | 
|---|
 | 207 |     \param mtlFile The .mtl file to read | 
|---|
 | 208 |  | 
|---|
 | 209 |     This Function parses all Lines of an mtl File. | 
|---|
 | 210 |     The reason for it not to be in the materials-class is, | 
|---|
 | 211 |     that a material does not have to be able to read itself in from a File. | 
|---|
 | 212 |  | 
|---|
 | 213 | */ | 
|---|
 | 214 | bool OBJModel::readMtlLib (char* mtlFile) | 
|---|
 | 215 | { | 
|---|
 | 216 |   this->mtlFileName = new char [strlen(mtlFile)+1]; | 
|---|
 | 217 |   strcpy(this->mtlFileName, mtlFile); | 
|---|
 | 218 |   char* fileName = new char [strlen(objPath) + strlen(this->mtlFileName)+1]; | 
|---|
 | 219 |   strcpy(fileName, this->objPath); | 
|---|
 | 220 |   strcat(fileName, this->mtlFileName); | 
|---|
 | 221 |    | 
|---|
 | 222 |  | 
|---|
 | 223 |   PRINTF(3)("Opening mtlFile: %s\n", fileName); | 
|---|
 | 224 |  | 
|---|
 | 225 |   ifstream* MTL_FILE = new ifstream (fileName); | 
|---|
 | 226 |   if (MTL_FILE->fail()) | 
|---|
 | 227 |     { | 
|---|
 | 228 |       PRINTF(1)("unable to open file: %s\n", fileName); | 
|---|
 | 229 |       MTL_FILE->close(); | 
|---|
 | 230 |       delete []fileName; | 
|---|
 | 231 |       delete MTL_FILE; | 
|---|
 | 232 |       return false; | 
|---|
 | 233 |     } | 
|---|
 | 234 |   char Buffer[500]; | 
|---|
 | 235 |   Material* tmpMat = material; | 
|---|
 | 236 |   while(!MTL_FILE->eof()) | 
|---|
 | 237 |     { | 
|---|
 | 238 |       MTL_FILE->getline(Buffer, 500); | 
|---|
 | 239 |       PRINTF(4)("found line in mtlFile: %s\n", Buffer); | 
|---|
 | 240 |        | 
|---|
 | 241 |  | 
|---|
 | 242 |       // create new Material | 
|---|
 | 243 |       if (!strncmp(Buffer, "newmtl ", 7)) | 
|---|
 | 244 |         { | 
|---|
 | 245 |           tmpMat = tmpMat->addMaterial(Buffer+7); | 
|---|
 | 246 |           //      PRINTF(2)("%s, %p\n", tmpMat->getName(), tmpMat); | 
|---|
 | 247 |         } | 
|---|
 | 248 |       // setting a illumMode | 
|---|
 | 249 |       else if (!strncmp(Buffer, "illum ", 6)) | 
|---|
 | 250 |         { | 
|---|
 | 251 |           tmpMat->setIllum(Buffer+6); | 
|---|
 | 252 |  | 
|---|
 | 253 |         } | 
|---|
 | 254 |       // setting Diffuse Color | 
|---|
 | 255 |       else if (!strncmp(Buffer, "Kd ", 3)) | 
|---|
 | 256 |         { | 
|---|
 | 257 |           tmpMat->setDiffuse(Buffer+3); | 
|---|
 | 258 |         } | 
|---|
 | 259 |       // setting Ambient Color | 
|---|
 | 260 |       else if (!strncmp(Buffer, "Ka ", 3)) | 
|---|
 | 261 |         { | 
|---|
 | 262 |           tmpMat->setAmbient(Buffer+3); | 
|---|
 | 263 |         } | 
|---|
 | 264 |       // setting Specular Color | 
|---|
 | 265 |       else if (!strncmp(Buffer, "Ks ", 3)) | 
|---|
 | 266 |         { | 
|---|
 | 267 |           tmpMat->setSpecular(Buffer+3); | 
|---|
 | 268 |         } | 
|---|
 | 269 |       // setting The Specular Shininess | 
|---|
 | 270 |       else if (!strncmp(Buffer, "Ns ", 3)) | 
|---|
 | 271 |         { | 
|---|
 | 272 |           tmpMat->setShininess(Buffer+3); | 
|---|
 | 273 |         } | 
|---|
 | 274 |       // setting up transparency | 
|---|
 | 275 |       else if (!strncmp(Buffer, "d ", 2)) | 
|---|
 | 276 |         { | 
|---|
 | 277 |           tmpMat->setTransparency(Buffer+2); | 
|---|
 | 278 |         } | 
|---|
 | 279 |       else if (!strncmp(Buffer, "Tf ", 3)) | 
|---|
 | 280 |         { | 
|---|
 | 281 |           tmpMat->setTransparency(Buffer+3); | 
|---|
 | 282 |         } | 
|---|
 | 283 |        | 
|---|
 | 284 |       else if (!strncmp(Buffer, "map_Kd ", 7)) | 
|---|
 | 285 |         { | 
|---|
 | 286 |           tmpMat->setDiffuseMap(Buffer+7); | 
|---|
 | 287 |         } | 
|---|
 | 288 |       else if (!strncmp(Buffer, "map_Ka ", 7)) | 
|---|
 | 289 |         { | 
|---|
 | 290 |           tmpMat->setAmbientMap(Buffer+7); | 
|---|
 | 291 |         } | 
|---|
 | 292 |       else if (!strncmp(Buffer, "map_Ks ", 7)) | 
|---|
 | 293 |         { | 
|---|
 | 294 |           tmpMat->setSpecularMap(Buffer+7); | 
|---|
 | 295 |         } | 
|---|
 | 296 |       else if (!strncmp(Buffer, "bump ", 5)) | 
|---|
 | 297 |         { | 
|---|
 | 298 |           tmpMat->setBump(Buffer+7); | 
|---|
 | 299 |         } | 
|---|
 | 300 |       | 
|---|
 | 301 |  | 
|---|
 | 302 |     } | 
|---|
 | 303 |   MTL_FILE->close(); | 
|---|
 | 304 |   delete []fileName; | 
|---|
 | 305 |   delete MTL_FILE; | 
|---|
 | 306 |   return true; | 
|---|
 | 307 | } | 
|---|