- Main Page
- Classes
- Files

- File List
- File Members

# flModel.c

Go to the documentation of this file.

    00001 #include "flGlobal.h"
    00002 #if FL_MODEL != 0
    00003 #include <stdlib.h>
    00004 #include <stdio.h>
    00005 #include <pspgu.h>
    00006 #include <pspgum.h>
    00007
    00008 #if FL_INCLUDE_ALL_C == 0
    00009 #include "flModel.h"
    00010 #include "flMemory.h"
    00011 #include "flMath.h"
    00012 #include "flColor.h"
    00013 #include "flFile.h"
    00014
    00015 #include "flTexture.h"
    00016 #include "flGraphics.h"
    00017
    00018 #if FL_MODEL_OBJ != 0
    00019 #include "flModelOBJ.h"
    00020 #endif
    00021
    00022 #if FL_MODEL_MD2 != 0
    00023 #include "flModelMD2.h"
    00024 #endif
    00025
    00026 #if FL_DEBUG != 0
    00027 #include "flDebug.h"
    00028 #endif
    00029 #endif
    00030
    00031 // Prototypes
    00032 void mdl3dStatDrawTextured(Model3dStatic* inModel);
    00033
    00034 void mdlInit() {
    00035      // Nothing to initialize (yet!)
    00036 }
    00037
    00038 Model3dStatic* mdl3dStatLoad(char* inPath) {
    00039      if(!inPath || (inPath[0] == 0)) {
    00040           #if FL_DEBUG_WARNING != 0
    00041           debugWarning("Invalid model file path.");
    00042           #endif
    00043           return NULL;
    00044      }
    00045      char* tempExt = fileExtension(inPath);
    00046      if(!tempExt) {
    00047           #if FL_DEBUG_WARNING != 0
    00048           debugWarning("Cannot determine file extension for model.");
    00049           #endif
    00050           return NULL;
    00051      }
    00052      strLCase((u8*)tempExt);
    00053
    00054      Model3dStatic* tempOut = NULL;
    00055      if(!strcmp(tempExt, "obj")) {
    00056           #if FL_MODEL_OBJ != 0
    00057           tempOut = mdl3dStatLoadOBJ(inPath);
    00058           #else
    00059           #if FL_DEBUG_DEVWARNING != 0
    00060           debugDevWarning("OBJ models not supported in this build\nSet FL_MODEL_OBJ to non-zero to enable them.");
    00061           #endif
    00062           #endif
    00063      }
    00064
    00065      memFree(tempExt);
    00066
    00067      if(!tempOut) {
    00068           #if FL_DEBUG_WARNING != 0
    00069           debugWarning("Cannot open this file type as model.");
    00070           #endif
    00071           return NULL;
    00072      }
    00073
    00074      mdl3dStatOptimize(tempOut);
    00075      return tempOut;
    00076 }
    00077
    00078 bool mdl3dStatSave(char* inPath, Model3dStatic* inModel) {
    00079      if(!inPath || (inPath[0] == 0)) {
    00080           #if FL_DEBUG_WARNING != 0
    00081           debugWarning("Invalid model file path.");
    00082           #endif
    00083           return false;
    00084      }
    00085
    00086      if(!inModel) {
    00087           #if FL_DEBUG_WARNING != 0
    00088           debugWarning("Cannot save NULL model.");
    00089           #endif
    00090           return false;
    00091      }
    00092
    00093      mdl3dStatOptimize(inModel);
    00094
    00095      char* tempExt = fileExtension(inPath);
    00096      if(!tempExt) {
    00097           #if FL_DEBUG_WARNING != 0
    00098           debugWarning("Cannot determine file extension for model.");
    00099           #endif
    00100           return false;
    00101      }
    00102      strLCase((u8*)tempExt);
    00103
    00104      bool tempOut = false;
    00105      if(!strcmp(tempExt, "obj")) {
    00106           #if FL_MODEL_OBJ != 0
    00107           tempOut = mdl3dStatSaveOBJ(inPath, inModel);
    00108           #else
    00109           #if FL_DEBUG_DEVWARNING != 0
    00110           debugDevWarning("OBJ models not supported in this build\nSet FL_MODEL_OBJ to non-zero to enable them.");
    00111           #endif
    00112           #endif
    00113      }
    00114
    00115      memFree(tempExt);
    00116
    00117      if(!tempOut) {
    00118           #if FL_DEBUG_WARNING != 0
    00119           debugWarning("Cannot save this model type.");
    00120           #endif
    00121           return false;
    00122      }
    00123
    00124      return tempOut;
    00125 }
    00126
    00127 void mdl3dStatDrawTextured(Model3dStatic* inModel) {
    00128      int i, j;
    00129      vertTfVf* tempVerts;
    00130      int tempVertCount = 0;
    00131      Texture* tempCurTex = NULL;
    00132      if(graphicsWireframe) {
    00133           for(i = 0; i < inModel->mdlFaceCount; i++)
    00134                tempVertCount += inModel->mdlFaces[i].mdlfVertCount;
    00135           tempVerts = sceGuGetMemory(sizeof(vertTfVf) * tempVertCount);
    00136           int tempVertIndex = 0;
    00137           for(i = 0; i < inModel->mdlFaceCount; i++) {
    00138                if(!tempCurTex || (inModel->mdlFaces[i].mdlfTexture != tempCurTex)) {
    00139                     texBind(inModel->mdlFaces[i].mdlfTexture);
    00140                     sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
    00141                     if(inModel->mdlFaces[i].mdlfTexture->texMipMaps)
    00142                          sceGuTexFilter(GU_LINEAR_MIPMAP_LINEAR, GU_LINEAR_MIPMAP_LINEAR);
    00143                     else
    00144                          sceGuTexFilter(GU_LINEAR, GU_LINEAR);
    00145                     tempCurTex = inModel->mdlFaces[i].mdlfTexture;
    00146                }
    00147                for(j = 0; j < inModel->mdlFaces[i].mdlfVertCount; j++) {
    00148                     tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[j]->x;
    00149                     tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[j]->y;
    00150                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j]->x;
    00151                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j]->y;
    00152                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j]->z;
    00153                     tempVertIndex++;
    00154
    00155                     if((j + 1) >= inModel->mdlFaces[i].mdlfVertCount) {
    00156                          tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[0]->x;
    00157                          tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[0]->y;
    00158                          tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[0]->x;
    00159                          tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[0]->y;
    00160                          tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[0]->z;
    00161                     } else {
    00162                          tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[j + 1]->x;
    00163                          tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[j + 1]->y;
    00164                          tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 1]->x;
    00165                          tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 1]->y;
    00166                          tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 1]->z;
    00167                     }
    00168                     tempVertIndex++;
    00169                }
    00170           }
    00171           sceGumDrawArray(GU_LINES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_3D, tempVertCount, 0, tempVerts);
    00172      } else {
    00173           for(i = 0; i < inModel->mdlFaceCount; i++)
    00174                tempVertCount += (inModel->mdlFaces[i].mdlfVertCount - 2);
    00175           tempVertCount += (tempVertCount << 1);
    00176           tempVerts = sceGuGetMemory(sizeof(vertTfVf) * tempVertCount);
    00177           int tempVertIndex = 0;
    00178           for(i = 0; i < inModel->mdlFaceCount; i++) {
    00179                if(!tempCurTex || (inModel->mdlFaces[i].mdlfTexture != tempCurTex)) {
    00180                     texBind(inModel->mdlFaces[i].mdlfTexture);
    00181                     sceGuTexFunc(GU_TFX_REPLACE, GU_TCC_RGBA);
    00182                     if(inModel->mdlFaces[i].mdlfTexture->texMipMaps)
    00183                          sceGuTexFilter(GU_LINEAR_MIPMAP_LINEAR, GU_LINEAR_MIPMAP_LINEAR);
    00184                     else
    00185                          sceGuTexFilter(GU_LINEAR, GU_LINEAR);
    00186                     tempCurTex = inModel->mdlFaces[i].mdlfTexture;
    00187                }
    00188                for(j = 0; j < (inModel->mdlFaces[i].mdlfVertCount - 2); j++) {
    00189                     tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[0]->x;
    00190                     tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[0]->y;
    00191                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[0]->x;
    00192                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[0]->y;
    00193                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[0]->z;
    00194                     tempVertIndex++;
    00195
    00196                     tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[j + 1]->x;
    00197                     tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[j + 1]->y;
    00198                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 1]->x;
    00199                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 1]->y;
    00200                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 1]->z;
    00201                     tempVertIndex++;
    00202
    00203                     tempVerts[tempVertIndex].vertU = inModel->mdlFaces[i].mdlfTexVerts[j + 2]->x;
    00204                     tempVerts[tempVertIndex].vertV = inModel->mdlFaces[i].mdlfTexVerts[j + 2]->y;
    00205                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 2]->x;
    00206                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 2]->y;
    00207                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 2]->z;
    00208                     tempVertIndex++;
    00209                }
    00210           }
    00211           sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_32BITF | GU_VERTEX_32BITF | GU_TRANSFORM_3D, tempVertCount, 0, tempVerts);
    00212      }
    00213 }
    00214
    00215 void mdl3dStatDraw(Model3dStatic* inModel) {
    00216      if(!inModel) {
    00217           #if FL_DEBUG_WARNING != 0
    00218           debugWarning("Trying to draw NULL model.");
    00219           #endif
    00220           return;
    00221      }
    00222      if(!inModel->mdlVerts) {
    00223           #if FL_DEBUG_WARNING != 0
    00224           debugWarning("Trying to draw model with NULL data.");
    00225           #endif
    00226           return;
    00227      }
    00228
    00229      if(inModel->mdlTextureCount > 0) {
    00230           mdl3dStatDrawTextured(inModel);
    00231           return;
    00232      }
    00233
    00234      sceGuDisable(GU_TEXTURE_2D);
    00235
    00236      int i, j;
    00237      vertVf* tempVerts;
    00238      int tempVertCount = 0;
    00239      if(graphicsWireframe) {
    00240           for(i = 0; i < inModel->mdlFaceCount; i++)
    00241                tempVertCount += inModel->mdlFaces[i].mdlfVertCount;
    00242           tempVerts = sceGuGetMemory(sizeof(vertVf) * tempVertCount);
    00243           int tempVertIndex = 0;
    00244           for(i = 0; i < inModel->mdlFaceCount; i++) {
    00245                for(j = 0; j < inModel->mdlFaces[i].mdlfVertCount; j++) {
    00246                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j]->x;
    00247                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j]->y;
    00248                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j]->z;
    00249                     tempVertIndex++;
    00250
    00251                     if((j + 1) >= inModel->mdlFaces[i].mdlfVertCount) {
    00252                          tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[0]->x;
    00253                          tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[0]->y;
    00254                          tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[0]->z;
    00255                     } else {
    00256                          tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 1]->x;
    00257                          tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 1]->y;
    00258                          tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 1]->z;
    00259                     }
    00260                     tempVertIndex++;
    00261                }
    00262           }
    00263           sceGumDrawArray(GU_LINES, GU_VERTEX_32BITF | GU_TRANSFORM_3D, tempVertCount, 0, tempVerts);
    00264      } else {
    00265           for(i = 0; i < inModel->mdlFaceCount; i++)
    00266                tempVertCount += (inModel->mdlFaces[i].mdlfVertCount - 2);
    00267           tempVertCount += (tempVertCount << 1);
    00268           tempVerts = sceGuGetMemory(sizeof(vertVf) * tempVertCount);
    00269           int tempVertIndex = 0;
    00270           for(i = 0; i < inModel->mdlFaceCount; i++) {
    00271                for(j = 0; j < (inModel->mdlFaces[i].mdlfVertCount - 2); j++) {
    00272                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[0]->x;
    00273                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[0]->y;
    00274                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[0]->z;
    00275                     tempVertIndex++;
    00276
    00277                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 1]->x;
    00278                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 1]->y;
    00279                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 1]->z;
    00280                     tempVertIndex++;
    00281
    00282                     tempVerts[tempVertIndex].vertX = inModel->mdlFaces[i].mdlfVerts[j + 2]->x;
    00283                     tempVerts[tempVertIndex].vertY = inModel->mdlFaces[i].mdlfVerts[j + 2]->y;
    00284                     tempVerts[tempVertIndex].vertZ = inModel->mdlFaces[i].mdlfVerts[j + 2]->z;
    00285                     tempVertIndex++;
    00286                }
    00287           }
    00288           sceGumDrawArray(GU_TRIANGLES, GU_VERTEX_32BITF | GU_TRANSFORM_3D, tempVertCount, 0, tempVerts);
    00289      }
    00290
    00291      sceGuEnable(GU_TEXTURE_2D);
    00292 }
    00293
    00294 void mdl3dStatOptimize(Model3dStatic* inModel) {
    00295      if(!inModel) {
    00296           #if FL_DEBUG_WARNING != 0
    00297           debugWarning("Trying to optimize a NULL model.");
    00298           #endif
    00299           return;
    00300      }
    00301      if(inModel->mdlOptimized) {
    00302           #if FL_DEBUG_WARNING != 0
    00303           debugWarning("Trying to optimize an already optimized model.");
    00304           #endif
    00305           return;
    00306      }
    00307      vect3f   tempVerts[inModel->mdlVertCount];
    00308      vect2f   tempTexVerts[inModel->mdlTexVertCount];
    00309      vect3f   tempNormals[inModel->mdlNormalCount];
    00310      Texture* tempTextures[inModel->mdlTextureCount];
    00311      int tempVertCount = 0;
    00312      int tempTexVertCount = 0;
    00313      int tempNormalCount = 0;
    00314      int tempTextureCount = 0;
    00315
    00316      int i, j;
    00317      bool tempDuped;
    00318
    00319      // Remove duped verts
    00320      for(i = 0; i < inModel->mdlVertCount; i++) {
    00321           tempDuped = false;
    00322           for(j = 0; j < tempVertCount; j++) {
    00323                if(vect3f_Cmp(tempVerts[j], inModel->mdlVerts[i])) {
    00324                     tempDuped = true;
    00325                     break;
    00326                }
    00327           }
    00328           if(!tempDuped) {
    00329                tempVerts[tempVertCount] = inModel->mdlVerts[i];
    00330                tempVertCount++;
    00331           }
    00332      }
    00333
    00334      // Remove duped tex verts
    00335      for(i = 0; i < inModel->mdlTexVertCount; i++) {
    00336           tempDuped = false;
    00337           for(j = 0; j < tempTexVertCount; j++) {
    00338                if(vect2f_Cmp(tempTexVerts[j], inModel->mdlTexVerts[i])) {
    00339                     tempDuped = true;
    00340                     break;
    00341                }
    00342           }
    00343           if(!tempDuped) {
    00344                tempTexVerts[tempTexVertCount] = inModel->mdlTexVerts[i];
    00345                tempTexVertCount++;
    00346           }
    00347      }
    00348
    00349      // Remove duped normals
    00350      for(i = 0; i < inModel->mdlNormalCount; i++) {
    00351           tempDuped = false;
    00352           for(j = 0; j < tempNormalCount; j++) {
    00353                if(vect3f_Cmp(tempNormals[j], inModel->mdlNormals[i])) {
    00354                     tempDuped = true;
    00355                     break;
    00356                }
    00357           }
    00358           if(!tempDuped) {
    00359                tempNormals[tempNormalCount] = inModel->mdlNormals[i];
    00360                tempNormalCount++;
    00361           }
    00362      }
    00363
    00364      // Remove duped textures
    00365      for(i = 0; i < inModel->mdlTextureCount; i++) {
    00366           tempDuped = false;
    00367           for(j = 0; j < tempTextureCount; j++) {
    00368                if(tempTextures[j] == inModel->mdlTextures[i]) {
    00369                     tempDuped = true;
    00370                     break;
    00371                }
    00372           }
    00373           if(!tempDuped) {
    00374                tempTextures[tempTextureCount] = inModel->mdlTextures[i];
    00375                tempTextureCount++;
    00376           }
    00377      }
    00378
    00379      Model3dStatic tempOut;
    00380
    00381      tempOut.mdlVertCount = tempVertCount;
    00382      tempOut.mdlTextureCount = tempTextureCount;
    00383      tempOut.mdlTexVertCount = tempTexVertCount;
    00384      tempOut.mdlNormalCount = tempNormalCount;
    00385      tempOut.mdlFaceCount = inModel->mdlFaceCount;
    00386
    00387      u32 tempSize = (sizeof(vect3f) * tempVertCount);
    00388      tempSize += (sizeof(vect2f) * tempTexVertCount);
    00389      tempSize += (sizeof(vect3f) * tempNormalCount);
    00390      tempSize += (sizeof(Model3dStaticFace) * inModel->mdlFaceCount);
    00391      tempSize += (sizeof(Texture*) * tempTextureCount);
    00392
    00393      u8* tempAllocBlock = memAlloc(tempSize);
    00394      if(!tempAllocBlock) {
    00395           #if FL_DEBUG_WARNING != 0
    00396           debugWarning("Couldn't allocate optimized model data.\nProbably out of memory.");
    00397           #endif
    00398           return;
    00399      }
    00400
    00401      u32 tempOffset = 0;
    00402      tempOut.mdlVerts = (vect3f*)(tempAllocBlock);
    00403      tempOffset += (sizeof(vect3f) * tempOut.mdlVertCount);
    00404      tempOut.mdlTexVerts = (vect2f*)((u32)(tempAllocBlock) + tempOffset);
    00405      tempOffset += (sizeof(vect2f) * tempOut.mdlTexVertCount);
    00406      tempOut.mdlNormals = (vect3f*)((u32)(tempAllocBlock) + tempOffset);
    00407      tempOffset += (sizeof(vect3f) * tempOut.mdlNormalCount);
    00408      tempOut.mdlFaces = (Model3dStaticFace*)((u32)(tempAllocBlock) + tempOffset);
    00409      tempOffset += (sizeof(Model3dStaticFace) * tempOut.mdlFaceCount);
    00410      tempOut.mdlTextures = (Texture**)((u32)(tempAllocBlock) + tempOffset);
    00411
    00412      for(i = 0; i < tempVertCount; i++)
    00413           tempOut.mdlVerts[i] = tempVerts[i];
    00414      for(i = 0; i < tempTexVertCount; i++)
    00415           tempOut.mdlTexVerts[i] = tempTexVerts[i];
    00416      for(i = 0; i < tempNormalCount; i++)
    00417           tempOut.mdlNormals[i] = tempNormals[i];
    00418      for(i = 0; i < tempTextureCount; i++)
    00419           tempOut.mdlTextures[i] = tempTextures[i];
    00420
    00421      int k;
    00422      // Apply new pointers to existing faces
    00423      for(i = 0; i < inModel->mdlFaceCount; i++) {
    00424           for(k = 0; k < inModel->mdlFaces[i].mdlfVertCount; k++) {
    00425                for(j = 0; j < tempOut.mdlVertCount; j++) {
    00426                     if(vect3f_Cmp(*inModel->mdlFaces[i].mdlfVerts[k], tempOut.mdlVerts[j])) {
    00427                          inModel->mdlFaces[i].mdlfVerts[k] = &tempOut.mdlVerts[j];
    00428                          break;
    00429                     }
    00430                }
    00431                for(j = 0; j < tempOut.mdlTexVertCount; j++) {
    00432                     if(vect2f_Cmp(*inModel->mdlFaces[i].mdlfTexVerts[k], tempOut.mdlTexVerts[j])) {
    00433                          inModel->mdlFaces[i].mdlfTexVerts[k] = &tempOut.mdlTexVerts[j];
    00434                          break;
    00435                     }
    00436                }
    00437                for(j = 0; j < tempOut.mdlNormalCount; j++) {
    00438                     if(vect3f_Cmp(*inModel->mdlFaces[i].mdlfNormals[k], tempOut.mdlNormals[j])) {
    00439                         inModel->mdlFaces[i].mdlfNormals[k] = &tempOut.mdlNormals[j];
    00440                         break;
    00441                     }
    00442                }
    00443           }
    00444           tempOut.mdlFaces[i] = inModel->mdlFaces[i];
    00445      }
    00446
    00447      memFree(inModel->mdlVerts);
    00448      inModel->mdlVertCount = tempOut.mdlVertCount;
    00449      inModel->mdlTexVertCount = tempOut.mdlTexVertCount;
    00450      inModel->mdlNormalCount = tempOut.mdlNormalCount;
    00451      inModel->mdlTextureCount = tempOut.mdlTextureCount;
    00452      inModel->mdlVerts = tempOut.mdlVerts;
    00453      inModel->mdlTexVerts = tempOut.mdlTexVerts;
    00454      inModel->mdlNormals = tempOut.mdlNormals;
    00455      inModel->mdlTextures = tempOut.mdlTextures;
    00456      inModel->mdlOptimized = true;
    00457
    00458      // TODO - Free textures by appropriate number of times.
    00459      // TODO - Remove duped faces
    00460 }
    00461
    00462 void mdl3dStatFree(Model3dStatic* inModel) {
    00463      if(!inModel) {
    00464           #if FL_DEBUG_WARNING != 0
    00465           debugWarning("Trying to free NULL model.");
    00466           #endif
    00467           return;
    00468      }
    00469      #if FL_MEMORY != 0
    00470      if(inModel->mdlVerts) {
    00471           int i;
    00472           for(i = 0; i < inModel->mdlFaceCount; i++) {
    00473                if(inModel->mdlFaces[i].mdlfVerts)
    00474                     memFree(inModel->mdlFaces[i].mdlfVerts);
    00475           }
    00476           for(i = 0; i < inModel->mdlTextureCount; i++)
    00477                texFree(inModel->mdlTextures[i]);
    00478           memFree(inModel->mdlVerts);
    00479      }
    00480      #else
    00481      int i;
    00482      for(i = 0; i < inModel->mdlFaceCount; i++) {
    00483           memFree(inModel->mdlFaces[i].mdlfVerts);
    00484      for(i = 0; i < inModel->mdlTextureCount; i++)
    00485           texFree(inModel->mdlTextures[i]);
    00486      memFree(inModel->mdlVerts);
    00487      #endif
    00488      memFree(inModel);
    00489 }
    00490
    00491 Model3dAnimated* mdl3dAnimLoad(char* inPath) {
    00492      if(!inPath || (inPath[0] == 0)) {
    00493           #if FL_DEBUG_WARNING != 0
    00494           debugWarning("Invalid model file path.");
    00495           #endif
    00496           return NULL;
    00497      }
    00498      char* tempExt = fileExtension(inPath);
    00499      if(!tempExt) {
    00500           #if FL_DEBUG_WARNING != 0
    00501           debugWarning("Cannot determine file extension for model.");
    00502           #endif
    00503           return NULL;
    00504      }
    00505      strLCase((u8*)tempExt);
    00506      Model3dAnimated* tempOut = NULL;
    00507      if(strncmp(tempExt, "md2", 4)) {
    00508           #if FL_MODEL_MD2 != 0
    00509           tempOut = mdl3dAnimLoadMD2(inPath);
    00510           #else
    00511           #if FL_DEBUG_DEVWARNING != 0
    00512           debugDevWarning("MD2 models not supported in this build\nSet FL_MODEL_MD2 to non-zero to enable them.");
    00513           #endif
    00514           #endif
    00515      }
    00516      #if FL_DEBUG_WARNING != 0
    00517      if(!tempOut)
    00518           debugWarning("Cannot open this file type as model.");
    00519      #endif
    00520      memFree(tempExt);
    00521
    00522      return tempOut;
    00523 }
    00524
    00525 bool mdl3dAnimSave(char* inPath, Model3dAnimated* inModel) {
    00526      return false;
    00527 }
    00528
    00529 void mdl3dAnimDraw(Model3dAnimated* inModel) {
    00530      if(!inModel)
    00531           return;
    00532      if(inModel->mdlType == MODEL_ANIM_TYPE_MD2)
    00533           mdl3dAnimDrawMD2(inModel->mdlData, 0.0f);
    00534 }
    00535
    00536 void mdl3dAnimFree(Model3dAnimated* inModel) {
    00537
    00538 }
    00539
    00540 #endif