- Main Page
- Classes
- Files

- File List
- File Members

# flModelMD2.c

Go to the documentation of this file.

    00001 #include "flGlobal.h"
    00002 #if FL_MODEL_MD2 != 0
    00003 #include <stdlib.h>
    00004 #include <stdio.h>
    00005 #include <psprtc.h>
    00006
    00007 #if FL_INCLUDE_ALL_C == 0
    00008 #include "flModelMD2.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 typedef struct {
    00024      char md2Ident[4];
    00025      int  md2Version;
    00026      int  md2SkinWidth;
    00027      int  md2SkinHeight;
    00028      int  md2FrameSize;
    00029
    00030      int  md2TextureCount;
    00031      int  md2VertCount;
    00032      int  md2TexVertCount;
    00033      int  md2TriCount;
    00034      int  md2GlCmdCount;
    00035      int  md2FrameCount;
    00036
    00037      int  md2TextureOffset;
    00038      int  md2TexVertOffset;
    00039      int  md2TriOffset;
    00040      int  md2FrameOffset;
    00041      int  md2GlCmdOffset;
    00042      int  md2EndOffset;
    00043 } md2Header;
    00044
    00045 typedef struct {
    00046      char md2TextureName[64];
    00047 } md2Texture;
    00048
    00049 typedef struct {
    00050      s16 md2TexVertU;
    00051      s16 md2TexVertV;
    00052 } md2TexVert;
    00053
    00054 typedef struct {
    00055      u16 md2TriVerts[3];
    00056      u16 md2TriTexVerts[3];
    00057 } md2Tri;
    00058
    00059 typedef struct {
    00060      u8 md2VertexPos[3];
    00061      u8 md2VertexNormal;
    00062 } md2Vertex;
    00063
    00064 typedef struct {
    00065      vect3f     md2FrameScale;
    00066      vect3f     md2FrameTranslate;
    00067      char       md2FrameName[16];
    00068      md2Vertex* md2FrameVerts;
    00069 } md2Frame;
    00070
    00071 typedef struct {
    00072      u32         md2TextureCount;
    00073      u32         md2TexVertCount;
    00074      u32         md2VertCount;
    00075      u32         md2TriCount;
    00076      u32         md2FrameCount;
    00077
    00078      Texture**   md2Textures;
    00079      md2TexVert* md2TexVerts;
    00080      md2Tri*     md2Tris;
    00081      md2Frame*   md2Frames;
    00082 } Model3dAnimatedMD2;
    00083
    00084 Model3dAnimated* mdl3dAnimLoadMD2(char* inPath) {
    00085      Model3dAnimatedMD2* tempModel = (Model3dAnimatedMD2*)memAlloc(sizeof(Model3dAnimatedMD2));
    00086      if(!tempModel) {
    00087           #if FL_DEBUG_WARNING != 0
    00088           debugWarning("Can't create md2 model struct.\nProbably out of memory.");
    00089           #endif
    00090           return NULL;
    00091      }
    00092      Model3dAnimated* tempOut = (Model3dAnimated*)memAlloc(sizeof(Model3dAnimated));
    00093      if(!tempOut) {
    00094           memFree(tempModel);
    00095           #if FL_DEBUG_WARNING != 0
    00096           debugWarning("Can't create model struct.\nProbably out of memory.");
    00097           #endif
    00098           return NULL;
    00099      }
    00100      tempOut->mdlType = MODEL_ANIM_TYPE_MD2;
    00101      tempOut->mdlData = (void*)tempModel;
    00102
    00103
    00104      md2Header tempHeader;
    00105      int i, j;
    00106
    00107      #if FL_FILE != 0
    00108      File* tempFile = fileOpen(inPath, FILE_MODE_READ | FILE_MODE_BINARY);
    00109      #else
    00110      FILE* tempFile = fopen(inPath, "rb");
    00111      #endif
    00112
    00113      fileRead(tempHeader.md2Ident, 4, tempFile);
    00114      fileRead(&tempHeader.md2Version, 4, tempFile);
    00115      if(strncmp(tempHeader.md2Ident, "IDP2", 4) || (tempHeader.md2Version != 8)) {
    00116           fileClose(tempFile);
    00117           memFree(tempModel);
    00118           memFree(tempOut);
    00119           #if FL_DEBUG_WARNING != 0
    00120           debugWarning("Only IDP2 version 8 md2 files are supported.");
    00121           #endif
    00122           return NULL;
    00123      }
    00124      fileRead(&tempHeader.md2SkinWidth, 4, tempFile);
    00125      fileRead(&tempHeader.md2SkinHeight, 4, tempFile);
    00126      fileRead(&tempHeader.md2FrameSize, 4, tempFile);
    00127      fileRead(&tempHeader.md2TextureCount, 4, tempFile);
    00128      fileRead(&tempHeader.md2VertCount, 4, tempFile);
    00129      fileRead(&tempHeader.md2TexVertCount, 4, tempFile);
    00130      fileRead(&tempHeader.md2TriCount, 4, tempFile);
    00131      fileRead(&tempHeader.md2GlCmdCount, 4, tempFile);
    00132      fileRead(&tempHeader.md2FrameCount, 4, tempFile);
    00133      fileRead(&tempHeader.md2TextureOffset, 4, tempFile);
    00134      fileRead(&tempHeader.md2TexVertOffset, 4, tempFile);
    00135      fileRead(&tempHeader.md2TriOffset, 4, tempFile);
    00136      fileRead(&tempHeader.md2FrameOffset, 4, tempFile);
    00137      fileRead(&tempHeader.md2GlCmdOffset, 4, tempFile);
    00138      fileRead(&tempHeader.md2EndOffset, 4, tempFile);
    00139
    00140      tempModel->md2TextureCount = tempHeader.md2TextureCount;
    00141      tempModel->md2TexVertCount = tempHeader.md2TexVertCount;
    00142      tempModel->md2VertCount = tempHeader.md2VertCount;
    00143      tempModel->md2TriCount = tempHeader.md2TriCount;
    00144      tempModel->md2FrameCount = tempHeader.md2FrameCount;
    00145
    00146      u32 tempSize = (sizeof(Texture*) * tempHeader.md2TextureCount);
    00147      tempSize += (sizeof(md2TexVert) * tempHeader.md2TexVertCount);
    00148      tempSize += (sizeof(md2Tri) * tempHeader.md2TriCount);
    00149      tempSize += (sizeof(md2Frame) * tempHeader.md2FrameCount);
    00150      tempSize += (sizeof(md2Vertex) * tempHeader.md2VertCount * tempHeader.md2FrameCount);
    00151      void* tempBlockAlloc = memAlloc(tempSize);
    00152      if(!tempBlockAlloc) {
    00153           memFree(tempOut);
    00154           memFree(tempModel);
    00155           fileClose(tempFile);
    00156           #if FL_DEBUG_WARNING != 0
    00157           debugWarning("Can't allocate memory for model data.\nProbably out of memory.");
    00158           #endif
    00159           return NULL;
    00160      }
    00161
    00162      tempModel->md2Textures = (Texture**)tempBlockAlloc;
    00163      u32 tempOffset = (sizeof(Texture*) * tempHeader.md2TextureCount);
    00164      tempModel->md2TexVerts = (md2TexVert*)((u32)tempBlockAlloc + tempOffset);
    00165      tempOffset += (sizeof(md2TexVert) * tempHeader.md2TexVertCount);
    00166      tempModel->md2Tris = (md2Tri*)((u32)tempBlockAlloc + tempOffset);
    00167      tempOffset += (sizeof(md2Tri) * tempHeader.md2TexVertCount);
    00168      tempModel->md2Frames = (md2Frame*)((u32)tempBlockAlloc + tempOffset);
    00169      tempOffset += (sizeof(md2Frame) * tempHeader.md2FrameCount);
    00170
    00171      char tempTexPath[64];
    00172      fileSeek(tempFile, tempHeader.md2TextureOffset, FILE_SEEK_SET);
    00173      for(i = 0; i < tempHeader.md2TextureCount; i++) {
    00174           fileRead(tempTexPath, 64, tempFile);
    00175           tempModel->md2Textures[i] = texLoad(tempTexPath);
    00176           if(!tempModel->md2Textures[i]) {
    00177                mdl3dAnimFree(tempOut);
    00178                fileClose(tempFile);
    00179                #if FL_DEBUG_WARNING != 0
    00180                debugWarning("Can't open texture file in MD2.");
    00181                #endif
    00182                return NULL;
    00183           }
    00184      }
    00185
    00186      fileSeek(tempFile, tempHeader.md2TexVertOffset, FILE_SEEK_SET);
    00187      for(i = 0; i < tempHeader.md2TexVertCount; i++) {
    00188           fileRead(&tempModel->md2TexVerts[i].md2TexVertU, 2, tempFile);
    00189           fileRead(&tempModel->md2TexVerts[i].md2TexVertV, 2, tempFile);
    00190      }
    00191
    00192      fileSeek(tempFile, tempHeader.md2TriOffset, FILE_SEEK_SET);
    00193      for(i = 0; i < tempHeader.md2TriCount; i++) {
    00194           for(j = 0; j < 3; j++)
    00195                fileRead(&tempModel->md2Tris[i].md2TriVerts[j], 2, tempFile);
    00196           for(j = 0; j < 3; j++)
    00197                fileRead(&tempModel->md2Tris[i].md2TriTexVerts[j], 2, tempFile);
    00198      }
    00199
    00200      fileSeek(tempFile, tempHeader.md2FrameOffset, FILE_SEEK_SET);
    00201      for(i = 0; i < tempHeader.md2FrameCount; i++) {
    00202           fileRead(&tempModel->md2Frames[i].md2FrameScale.x, 4, tempFile);
    00203           fileRead(&tempModel->md2Frames[i].md2FrameScale.y, 4, tempFile);
    00204           fileRead(&tempModel->md2Frames[i].md2FrameScale.z, 4, tempFile);
    00205           fileRead(&tempModel->md2Frames[i].md2FrameTranslate.x, 4, tempFile);
    00206           fileRead(&tempModel->md2Frames[i].md2FrameTranslate.x, 4, tempFile);
    00207           fileRead(&tempModel->md2Frames[i].md2FrameTranslate.x, 4, tempFile);
    00208           fileRead(tempModel->md2Frames[i].md2FrameName, 16, tempFile);
    00209           tempModel->md2Frames[i].md2FrameVerts = (md2Vertex*)((u32)tempBlockAlloc + tempOffset);
    00210           tempOffset += (sizeof(md2Vertex) * tempHeader.md2VertCount);
    00211           for(j = 0; j < tempHeader.md2VertCount; j++) {
    00212                fileRead(tempModel->md2Frames[i].md2FrameVerts[j].md2VertexPos, 3, tempFile);
    00213                fileRead(&tempModel->md2Frames[i].md2FrameVerts[j].md2VertexNormal, 1, tempFile);
    00214           }
    00215      }
    00216
    00217      fileClose(tempFile);
    00218
    00219      return tempOut;
    00220 }
    00221
    00222 void mdl3dAnimDrawMD2(void* inModel, float inFrame) {
    00223      if(!inModel) {
    00224           #if FL_DEBUG_WARNING != 0
    00225           debugWarning("Trying to draw NULL md2.");
    00226           #endif
    00227           return;
    00228      }
    00229
    00230      Model3dAnimatedMD2* tempModel = (Model3dAnimatedMD2*)inModel;
    00231
    00232      while(inFrame >= (float)tempModel->md2FrameCount)
    00233           inFrame -= (float)tempModel->md2FrameCount;
    00234
    00235      int tempFrames[2] = { (int)inFrame, (int)(inFrame + 1.0f) };
    00236      if(tempFrames[1] >= tempModel->md2FrameCount)
    00237           tempFrames[1] -= tempModel->md2FrameCount;
    00238      float tempFract = (inFrame - (float)tempFrames[0]);
    00239
    00240      vect3f tempScale = vect3f_Mulf(tempModel->md2Frames[tempFrames[0]].md2FrameScale, (1.0f - tempFract));
    00241      tempScale = vect3f_Add(tempScale, vect3f_Mulf(tempModel->md2Frames[tempFrames[1]].md2FrameScale, tempFract));
    00242      vect3f tempTranslate = vect3f_Mulf(tempModel->md2Frames[tempFrames[0]].md2FrameTranslate, (1.0f - tempFract));
    00243      tempTranslate = vect3f_Add(tempTranslate, vect3f_Mulf(tempModel->md2Frames[tempFrames[1]].md2FrameTranslate, tempFract));
    00244
    00245      texBind(tempModel->md2Textures[0]);
    00246
    00247      sceGumPushMatrix();
    00248      sceGumScale(&tempScale);
    00249      sceGumTranslate(&tempTranslate);
    00250
    00251      int i, j;
    00252      vertTsVf* tempVerts = (vertTsVf*)sceGuGetMemory(sizeof(vertTsVf) * (tempModel->md2TriCount * 3));
    00253      for(i = 0; i < tempModel->md2TriCount; i++) {
    00254           for(j = 0; j < 3; j++) {
    00255                tempVerts[(i * 3) + j].vertX = (float)tempModel->md2Frames[tempFrames[0]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[0] * (1.0f - tempFract);
    00256                tempVerts[(i * 3) + j].vertX += (float)tempModel->md2Frames[tempFrames[1]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[0] * tempFract;
    00257                tempVerts[(i * 3) + j].vertY = (float)tempModel->md2Frames[tempFrames[0]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[1] * (1.0f - tempFract);
    00258                tempVerts[(i * 3) + j].vertY += (float)tempModel->md2Frames[tempFrames[1]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[1] * tempFract;
    00259                tempVerts[(i * 3) + j].vertZ = (float)tempModel->md2Frames[tempFrames[0]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[2] * (1.0f - tempFract);
    00260                tempVerts[(i * 3) + j].vertZ += (float)tempModel->md2Frames[tempFrames[1]].md2FrameVerts[tempModel->md2Tris[i].md2TriVerts[j]].md2VertexPos[2] * tempFract;
    00261                tempVerts[(i * 3) + j].vertU += tempModel->md2TexVerts[tempModel->md2Tris[i].md2TriTexVerts[j]].md2TexVertU;
    00262                tempVerts[(i * 3) + j].vertV += tempModel->md2TexVerts[tempModel->md2Tris[i].md2TriTexVerts[j]].md2TexVertV;
    00263           }
    00264      }
    00265      sceGumDrawArray(GU_TRIANGLES, GU_TEXTURE_16BIT | GU_VERTEX_32BITF | GU_TRANSFORM_3D, (tempModel->md2TriCount * 3), 0, tempVerts);
    00266      sceGumPopMatrix();
    00267 }
    00268
    00269 bool mdl3dAnimSaveMD2(char* inPath, Model3dAnimated* inModel) {
    00270      #if FL_DEBUG_DEVWARNING != 0
    00271      debugDevWarning("MD2 saving is not yet implemented.");
    00272      #endif
    00273      return false;
    00274 }
    00275
    00276 #endif