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];
00044 inFacePtr->mdlfTexVerts = (vect2f**)&tempBlockAlloc[sizeof(vect3f*) * inFacePtr->mdlfVertCount];
00045 inFacePtr->mdlfNormals = (vect3f**)&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];
00203 tempOffset += (sizeof(vect3f) * tempOut->mdlVertCount);
00204 tempOut->mdlTexVerts = (vect2f*)&tempAllocBlock[tempOffset];
00205 tempOffset += (sizeof(vect2f) * tempOut->mdlTexVertCount);
00206 tempOut->mdlNormals = (vect3f*)&tempAllocBlock[tempOffset];
00207 tempOffset += (sizeof(vect3f) * tempOut->mdlNormalCount);
00208 tempOut->mdlFaces = (Model3dStaticFace*)&tempAllocBlock[tempOffset];
00209 tempOffset += (sizeof(Model3dStaticFace) * tempOut->mdlFaceCount);
00210 tempOut->mdlTextures = (Texture**)&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