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