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