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