- Main Page
- Classes
- Files

- File List
- File Members

# flModelOBJ.c

Go to the documentation of this file.

    00001 #include "flGlobal.h"
    00002 #if FL_MODEL_OBJ != 0
    00003 #include <stdlib.h>
    00004 #include <stdio.h>
    00005 #include <psprtc.h>
    00006
    00007 #if FL_INCLUDE_ALL_C == 0
    00008 #include "flModelOBJ.h"
    00009 #include "flModel.h"
    00010 #include "flMemory.h"
    00011 #include "flMath.h"
    00012 #include "flColor.h"
    00013 #include "flFile.h"
    00014 #include "flString.h"
    00015
    00016 #include "flTexture.h"
    00017
    00018 #if FL_DEBUG != 0
    00019 #include "flDebug.h"
    00020 #endif
    00021 #endif
    00022
    00023 bool mdl3dStatLoadOBJ_faceRead(u8* inFaceStr, Model3dStaticFace* inFacePtr, Model3dStatic* inModel, Texture* inCurTexture, int inVertPtr, int inTexVertPtr, int inNormPtr) {
    00024      u8* tempLinePtr = inFaceStr;
    00025      inFacePtr->mdlfVertCount = 0;
    00026      while((tempLinePtr[0] != '\n') && (tempLinePtr[0] != 0)) {
    00027           while((tempLinePtr[0] == ' ') || (tempLinePtr[0] == ASCII_TAB))
    00028                tempLinePtr++;
    00029           if((tempLinePtr[0] == '\n') || (tempLinePtr[0] == 0) || (tempLinePtr[0] == '\r'))
    00030                break;
    00031           inFacePtr->mdlfVertCount++;
    00032           while((tempLinePtr[0] != ' ') && (tempLinePtr[0] != ASCII_TAB) && (tempLinePtr[0] != '\n') && (tempLinePtr[0] != 0))
    00033                tempLinePtr++;
    00034      }
    00035      u8* tempBlockAlloc = memAlloc(sizeof(vect3f*) * inFacePtr->mdlfVertCount * 3);
    00036      if(!tempBlockAlloc) {
    00037           #if FL_DEBUG_WARNING != 0
    00038           debugWarning("Couldn't read OBJ face data.\nProbably out of memory.");
    00039           #endif
    00040           return false;
    00041      }
    00042      memClear(tempBlockAlloc, (sizeof(vect3f*) * inFacePtr->mdlfVertCount * 3));
    00043      inFacePtr->mdlfVerts = (vect3f**)&tempBlockAlloc[0]; //(vect3f**)tempBlockAlloc;
    00044      inFacePtr->mdlfTexVerts = (vect2f**)&tempBlockAlloc[sizeof(vect3f*) * inFacePtr->mdlfVertCount]; //(vect2f**)((u32)tempBlockAlloc + (sizeof(vect3f*) * inFacePtr->mdlfVertCount));
    00045      inFacePtr->mdlfNormals = (vect3f**)&tempBlockAlloc[(sizeof(vect3f*) << 1) * inFacePtr->mdlfVertCount]; //(vect3f**)((u32)tempBlockAlloc + ((sizeof(vect3f*) << 1) * inFacePtr->mdlfVertCount));
    00046      tempLinePtr = inFaceStr;
    00047      int i, tempIndex;
    00048      for(i = (inFacePtr->mdlfVertCount - 1); i >= 0 ; i--) {
    00049           while((tempLinePtr[0] == ' ') || (tempLinePtr[0] == ASCII_TAB) || (tempLinePtr[0] == '\r'))
    00050                tempLinePtr++;
    00051           if(tempLinePtr[0] == 0)
    00052                return false;
    00053           tempIndex = strToInt(tempLinePtr);
    00054           if(tempLinePtr[0] == '-') {
    00055                tempIndex += inVertPtr;
    00056                tempLinePtr++;
    00057           } else if(tempLinePtr[0] == '+') {
    00058                tempIndex += (inVertPtr - 1);
    00059                tempLinePtr++;
    00060           } else {
    00061                tempIndex -= 1;
    00062           }
    00063           if(tempIndex < 0) {
    00064                #if FL_DEBUG_WARNING != 0
    00065                debugWarning("Invalid obj file, contains reference to vertex < 1.");
    00066                #endif
    00067                return false;
    00068           }
    00069           inFacePtr->mdlfVerts[i] = &inModel->mdlVerts[tempIndex];
    00070           while((tempLinePtr[0] >= '0') && (tempLinePtr[0] <= '9'))
    00071                tempLinePtr++;
    00072           if(tempLinePtr[0] == '/') {
    00073                tempLinePtr++;
    00074                if(tempLinePtr[0] != '/') {
    00075                     tempIndex = strToInt(tempLinePtr);
    00076                     if(tempLinePtr[0] == '-') {
    00077                          tempIndex += inTexVertPtr;
    00078                          tempLinePtr++;
    00079                     } else if(tempLinePtr[0] == '+') {
    00080                          tempIndex += (inTexVertPtr - 1);
    00081                          tempLinePtr++;
    00082                     } else {
    00083                          tempIndex -= 1;
    00084                     }
    00085                     if(tempIndex < 0) {
    00086                          #if FL_DEBUG_WARNING != 0
    00087                          debugWarning("Invalid obj file, contains reference to texture vert < 1.");
    00088                          #endif
    00089                          return false;
    00090                     }
    00091                     inFacePtr->mdlfTexVerts[i] = &inModel->mdlTexVerts[tempIndex];
    00092                     while((tempLinePtr[0] >= '0') && (tempLinePtr[0] <= '9'))
    00093                          tempLinePtr++;
    00094                } else {
    00095                     inFacePtr->mdlfTexVerts[i] = NULL;
    00096                }
    00097                if(tempLinePtr[0] == '/') {
    00098                     tempLinePtr++;
    00099                     tempIndex = strToInt(tempLinePtr);
    00100                     if(tempLinePtr[0] == '-') {
    00101                          tempIndex += inNormPtr;
    00102                          tempLinePtr++;
    00103                     } else if(tempLinePtr[0] == '+') {
    00104                          tempIndex += (inNormPtr - 1);
    00105                          tempLinePtr++;
    00106                     } else {
    00107                          tempIndex -= 1;
    00108                     }
    00109                     if(tempIndex < 0) {
    00110                          #if FL_DEBUG_WARNING != 0
    00111                          debugWarning("Invalid obj file, contains reference to normal < 1.");
    00112                          #endif
    00113                          return false;
    00114                     }
    00115                     inFacePtr->mdlfNormals[i] = &inModel->mdlNormals[tempIndex];
    00116                     while((tempLinePtr[0] >= '0') && (tempLinePtr[0] <= '9'))
    00117                          tempLinePtr++;
    00118                     while(tempLinePtr[0] == '/') {
    00119                          if((tempLinePtr[0] == '-') || (tempLinePtr[0] == '+'))
    00120                               tempLinePtr++;
    00121                          while((tempLinePtr[0] >= '0') && (tempLinePtr[0] <= '9'))
    00122                               tempLinePtr++;
    00123                     }
    00124                } else {
    00125                     inFacePtr->mdlfNormals[i] = NULL;
    00126                }
    00127           } else {
    00128                inFacePtr->mdlfTexVerts[i] = NULL;
    00129                inFacePtr->mdlfNormals[i] = NULL;
    00130           }
    00131      }
    00132      inFacePtr->mdlfTexture = inCurTexture;
    00133      return true;
    00134 }
    00135
    00136 Model3dStatic* mdl3dStatLoadOBJ(char* inPath) {
    00137      if(!inPath || !fileExists(inPath)) {
    00138           #if FL_DEBUG_WARNING != 0
    00139           debugWarning("Cannot open OBJ file.");
    00140           #endif
    00141           return NULL;
    00142      }
    00143
    00144      #if FL_FILE != 0
    00145      File* tempFile = fileOpen(inPath, FILE_MODE_READ);
    00146      #else
    00147      FILE* tempFile = fopen(inPath, "r");
    00148      #endif
    00149
    00150      Model3dStatic* tempOut = memAlloc(sizeof(Model3dStatic));
    00151      if(!tempOut) {
    00152           fileClose(tempFile);
    00153           #if FL_DEBUG_WARNING != 0
    00154           debugWarning("Couldn't create model struct.\nProbably out of memory.");
    00155           #endif
    00156           return NULL;
    00157      }
    00158      tempOut->mdlOptimized = false;
    00159      tempOut->mdlTexVertCount = 0;
    00160      tempOut->mdlVertCount = 0;
    00161      tempOut->mdlTextureCount = 0;
    00162      tempOut->mdlTexVertCount = 0;
    00163      tempOut->mdlNormalCount = 0;
    00164      tempOut->mdlFaceCount = 0;
    00165
    00166      u8 tempLine[256];
    00167      u8* tempLinePtr;
    00168
    00169      while(fileGets((char*)tempLine, 256, tempFile)) {
    00170           tempLinePtr = tempLine;
    00171           while((tempLinePtr[0] == ' ') || (tempLinePtr[0] == ASCII_TAB))
    00172                tempLinePtr++;
    00173           if(strncmp((char*)tempLinePtr, "vt", 2) == 0)
    00174                tempOut->mdlTexVertCount++;
    00175           else if(strncmp((char*)tempLinePtr, "vn", 2) == 0)
    00176                tempOut->mdlNormalCount++;
    00177           else if(tempLinePtr[0] == 'v')
    00178                tempOut->mdlVertCount++;
    00179           else if(tempLinePtr[0] == 'f')
    00180                tempOut->mdlFaceCount++;
    00181           else if(strncmp((char*)tempLinePtr, "usemtl", 6) == 0)
    00182                tempOut->mdlTextureCount++;
    00183      }
    00184
    00185      u32 tempSize = (sizeof(vect3f) * tempOut->mdlVertCount);
    00186      tempSize += (sizeof(vect2f) * tempOut->mdlTexVertCount);
    00187      tempSize += (sizeof(vect3f) * tempOut->mdlNormalCount);
    00188      tempSize += (sizeof(Model3dStaticFace) * tempOut->mdlFaceCount);
    00189      tempSize += (sizeof(Texture*) * tempOut->mdlTextureCount);
    00190
    00191      u8* tempAllocBlock = memAlloc(tempSize);
    00192      if(!tempAllocBlock) {
    00193           fileClose(tempFile);
    00194           mdl3dStatFree(tempOut);
    00195           #if FL_DEBUG_WARNING != 0
    00196           debugWarning("Couldn't allocate model data.\nProbably out of memory.");
    00197           #endif
    00198           return NULL;
    00199      }
    00200
    00201      u32 tempOffset = 0;
    00202      tempOut->mdlVerts = (vect3f*)&tempAllocBlock[tempOffset]; //(vect3f*)(tempAllocBlock);
    00203      tempOffset += (sizeof(vect3f) * tempOut->mdlVertCount);
    00204      tempOut->mdlTexVerts = (vect2f*)&tempAllocBlock[tempOffset]; //(vect2f*)((u32)(tempAllocBlock) + tempOffset);
    00205      tempOffset += (sizeof(vect2f) * tempOut->mdlTexVertCount);
    00206      tempOut->mdlNormals = (vect3f*)&tempAllocBlock[tempOffset]; //(vect3f*)((u32)(tempAllocBlock) + tempOffset);
    00207      tempOffset += (sizeof(vect3f) * tempOut->mdlNormalCount);
    00208      tempOut->mdlFaces = (Model3dStaticFace*)&tempAllocBlock[tempOffset]; //(Model3dStaticFace*)((u32)(tempAllocBlock) + tempOffset);
    00209      tempOffset += (sizeof(Model3dStaticFace) * tempOut->mdlFaceCount);
    00210      tempOut->mdlTextures = (Texture**)&tempAllocBlock[tempOffset]; //(Texture**)((u32)(tempAllocBlock) + tempOffset);
    00211
    00212      fileSeek(tempFile, 0, FILE_SEEK_SET);
    00213
    00214      u32 tempVertPtr = 0;
    00215      u32 tempTexVertPtr = 0;
    00216      u32 tempNormPtr = 0;
    00217      u32 tempFacePtr = 0;
    00218      u32 tempTexPtr = 0;
    00219
    00220      Texture* tempCurTexture = NULL;
    00221
    00222      int tempLineNum = 0;
    00223      while(fileGets((char*)tempLine, 256, tempFile)) {
    00224           tempLineNum++;
    00225           tempLinePtr = tempLine;
    00226           while((tempLinePtr[0] == ' ') || (tempLinePtr[0] == ASCII_TAB))
    00227                tempLinePtr++;
    00228           if(strncmp((char*)tempLinePtr, "vt", 2) == 0) {
    00229                tempLinePtr += 2;
    00230                tempOut->mdlTexVerts[tempTexVertPtr] = strToVect2f(tempLinePtr);
    00231                tempTexVertPtr++;
    00232           } else if(strncmp((char*)tempLinePtr, "vn", 2) == 0) {
    00233                tempLinePtr += 2;
    00234                tempOut->mdlNormals[tempNormPtr] = strToVect3f(tempLinePtr);
    00235                tempNormPtr++;
    00236           } else if(tempLinePtr[0] == 'v') {
    00237                tempLinePtr++;
    00238                tempOut->mdlVerts[tempVertPtr] = strToVect3f(tempLinePtr);
    00239                tempVertPtr++;
    00240           } else if(tempLinePtr[0] == 'f') {
    00241                tempLinePtr++;
    00242                if(!mdl3dStatLoadOBJ_faceRead(tempLinePtr, &tempOut->mdlFaces[tempFacePtr],tempOut, tempCurTexture, (int)tempVertPtr, (int)tempTexVertPtr, (int)tempNormPtr)) {
    00243                     fileClose(tempFile);
    00244                     mdl3dStatFree(tempOut);
    00245                     #if FL_DEBUG_WARNING != 0
    00246                     char tempString[256];
    00247                     sprintf(tempString, "Error reading face data on line %i while loading OBJ.", tempLineNum);
    00248                     debugWarning(tempString);
    00249                     #endif
    00250                     return NULL;
    00251                }
    00252                tempFacePtr++;
    00253           } else if(strncmp((char*)tempLinePtr, "usemtl", 6) == 0) {
    00254                tempLinePtr += 6;
    00255                while((tempLinePtr[0] == ' ') || (tempLinePtr[0] == ASCII_TAB))
    00256                     tempLinePtr++;
    00257                tempLine[strlen((char*)tempLine) - 1] = 0;
    00258                tempOut->mdlTextures[tempTexPtr] = texLoad((char*)tempLinePtr);
    00259                if(!tempOut->mdlTextures[tempTexPtr]) {
    00260                     fileClose(tempFile);
    00261                     mdl3dStatFree(tempOut);
    00262                     #if FL_DEBUG_WARNING != 0
    00263                     char tempString[256];
    00264                     sprintf(tempString, "Error reading texture data on line %i while loading OBJ.", tempLineNum);
    00265                     debugWarning(tempString);
    00266                     #endif
    00267                     return NULL;
    00268                }
    00269                tempLine[strlen((char*)tempLine) - 1] = '\n';
    00270                tempCurTexture = tempOut->mdlTextures[tempTexPtr];
    00271                tempTexPtr++;
    00272           }
    00273      }
    00274
    00275      return tempOut;
    00276 }
    00277
    00278 bool mdl3dStatSaveOBJ(char* inPath, Model3dStatic* inModel) {
    00279      #if FL_FILE != 0
    00280      File* tempFile = fileOpen(inPath, FILE_MODE_WRITE);
    00281      #else
    00282      FILE* tempFile = fopen(inPath, "w");
    00283      #endif
    00284
    00285      if(!tempFile) {
    00286           #if FL_DEBUG_WARNING != 0
    00287           debugWarning("Couldn't open obj file for saving.");
    00288           #endif
    00289           return false;
    00290      }
    00291
    00292      char tempString[256];
    00293      int i, j, k;
    00294      pspTime tempTime;
    00295      sceRtcGetCurrentClockLocalTime(&tempTime);
    00296
    00297      #if FL_DEBUG_DATEFORMAT_AMERICAN != 0
    00298      sprintf(tempString, "# Created by funcLib on %02i/%02i/%04i at %02i:%02i:%02i\n", tempTime.month, tempTime.day, tempTime.year, tempTime.hour, tempTime.minutes, tempTime.seconds);
    00299      #else
    00300      sprintf(tempString, "# Created by funcLib on %02i/%02i/%04i at %02i:%02i:%02i\n", tempTime.day, tempTime.month, tempTime.year, tempTime.hour, tempTime.minutes, tempTime.seconds);
    00301      #endif
    00302      filePuts(tempString, tempFile);
    00303      sprintf(tempString, "# Verts: %i\n", (int)inModel->mdlVertCount);
    00304      filePuts(tempString, tempFile);
    00305      sprintf(tempString, "# TexCoords: %i\n", (int)inModel->mdlTexVertCount);
    00306      filePuts(tempString, tempFile);
    00307      sprintf(tempString, "# Normals: %i\n", (int)inModel->mdlNormalCount);
    00308      filePuts(tempString, tempFile);
    00309      sprintf(tempString, "# Materials: %i\n", (int)inModel->mdlTextureCount);
    00310      filePuts(tempString, tempFile);
    00311      sprintf(tempString, "# Faces: %i\n", (int)inModel->mdlFaceCount);
    00312      filePuts(tempString, tempFile);
    00313      j = 0;
    00314      for(i = 0; i < inModel->mdlFaceCount; i++)
    00315           j += (inModel->mdlFaces[i].mdlfVertCount - 2);
    00316      sprintf(tempString, "# Triangles: %i\n", j);
    00317      filePuts(tempString, tempFile);
    00318
    00319      sprintf(tempString, "\n# Verteces\n");
    00320      filePuts(tempString, tempFile);
    00321      for(i = 0; i < inModel->mdlVertCount; i++) {
    00322           sprintf(tempString, "v %f %f %f\n", inModel->mdlVerts[i].x, inModel->mdlVerts[i].y, inModel->mdlVerts[i].z);
    00323           filePuts(tempString, tempFile);
    00324      }
    00325
    00326      sprintf(tempString, "\n# TexCoords\n");
    00327      filePuts(tempString, tempFile);
    00328      for(i = 0; i < inModel->mdlTexVertCount; i++) {
    00329           sprintf(tempString, "vt %f %f\n", inModel->mdlTexVerts[i].x, inModel->mdlTexVerts[i].y);
    00330           filePuts(tempString, tempFile);
    00331      }
    00332
    00333      sprintf(tempString, "\n# Normals\n");
    00334      filePuts(tempString, tempFile);
    00335      for(i = 0; i < inModel->mdlNormalCount; i++) {
    00336           sprintf(tempString, "vn %f %f %f\n", inModel->mdlNormals[i].x, inModel->mdlNormals[i].y, inModel->mdlNormals[i].z);
    00337           filePuts(tempString, tempFile);
    00338      }
    00339
    00340      sprintf(tempString, "\n# Faces\n");
    00341      filePuts(tempString, tempFile);
    00342      char tempStringAdd[256];
    00343      u32 tempCurTexture = 0;
    00344      for(i = 0; i < inModel->mdlFaceCount; i++) {
    00345           if(inModel->mdlTextureCount > 0) {
    00346                if(!tempCurTexture || (tempCurTexture != (unsigned int)inModel->mdlFaces[i].mdlfTexture)) {
    00347                     sprintf(tempString, "usemtl %s\n", texPath(inModel->mdlFaces[i].mdlfTexture));
    00348                     tempCurTexture = (unsigned int)inModel->mdlFaces[i].mdlfTexture;
    00349                     filePuts(tempString, tempFile);
    00350                }
    00351           }
    00352           tempString[0] = 'f';
    00353           tempString[1] = 0;
    00354           for(j = (inModel->mdlFaces[i].mdlfVertCount - 1); j >= 0 ; j--) {
    00355                for(k = 0; k < inModel->mdlVertCount; k++) {
    00356                     if(vect3f_Cmp(*inModel->mdlFaces[i].mdlfVerts[j], inModel->mdlVerts[k])) {
    00357                          sprintf(tempStringAdd, " %i", (k + 1));
    00358                          strcat(tempString, tempStringAdd);
    00359                          break;
    00360                     }
    00361                }
    00362                if(inModel->mdlFaces[i].mdlfTexVerts[j]) {
    00363                     for(k = 0; k < inModel->mdlTexVertCount; k++) {
    00364                          if(vect2f_Cmp(*inModel->mdlFaces[i].mdlfTexVerts[j], inModel->mdlTexVerts[k])) {
    00365                               sprintf(tempStringAdd, "/%i", (k + 1));
    00366                               strcat(tempString, tempStringAdd);
    00367                               break;
    00368                          }
    00369                     }
    00370                }
    00371                if(inModel->mdlFaces[i].mdlfNormals[j]) {
    00372                     if(!inModel->mdlFaces[i].mdlfTexVerts[j]) {
    00373                          sprintf(tempStringAdd, "/");
    00374                          strcat(tempString, tempStringAdd);
    00375                     }
    00376                     for(k = 0; k < inModel->mdlNormalCount; k++) {
    00377                          if(vect2f_Cmp(*inModel->mdlFaces[i].mdlfNormals[j], inModel->mdlNormals[k])) {
    00378                               sprintf(tempStringAdd, "/%i", (k + 1));
    00379                               strcat(tempString, tempStringAdd);
    00380                               break;
    00381                          }
    00382                     }
    00383                }
    00384           }
    00385           filePuts(tempString, tempFile);
    00386           filePuts("\n", tempFile);
    00387      }
    00388
    00389      sprintf(tempString, "\n# End of OBJ\n");
    00390      filePuts(tempString, tempFile);
    00391
    00392      fileClose(tempFile);
    00393
    00394      return true;
    00395 }
    00396
    00397 #endif