pm_md3.c

Go to the documentation of this file.
00001 /* -----------------------------------------------------------------------------
00002 
00003  PicoModel Library
00004 
00005  Copyright (c) 2002, Randy Reddig & seaw0lf
00006  All rights reserved.
00007 
00008  Redistribution and use in source and binary forms, with or without modification,
00009  are permitted provided that the following conditions are met:
00010 
00011  Redistributions of source code must retain the above copyright notice, this list
00012  of conditions and the following disclaimer.
00013 
00014  Redistributions in binary form must reproduce the above copyright notice, this
00015  list of conditions and the following disclaimer in the documentation and/or
00016  other materials provided with the distribution.
00017 
00018  Neither the names of the copyright holders nor the names of its contributors may
00019  be used to endorse or promote products derived from this software without
00020  specific prior written permission.
00021 
00022  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
00023  ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
00024  WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
00025  DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
00026  ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
00027  (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
00029  ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
00030  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
00031  SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
00032 
00033  ----------------------------------------------------------------------------- */
00034 
00035 /* marker */
00036 #define PM_MD3_C
00037 
00038 /* dependencies */
00039 #include "picointernal.h"
00040 
00041 /* md3 model format */
00042 #define MD3_MAGIC           "IDP3"
00043 #define MD3_VERSION         15
00044 
00045 /* md3 vertex scale */
00046 #define MD3_SCALE         (1.0f / 64.0f)
00047 
00048 /* md3 model frame information */
00049 typedef struct md3Frame_s
00050 {
00051     float bounds[2][3];
00052     float localOrigin[3];
00053     float radius;
00054     char creator[16];
00055 } md3Frame_t;
00056 
00057 /* md3 model tag information */
00058 typedef struct md3Tag_s
00059 {
00060     char name[64];
00061     float origin[3];
00062     float axis[3][3];
00063 } md3Tag_t;
00064 
00065 /* md3 surface md3 (one object mesh) */
00066 typedef struct md3Surface_s
00067 {
00068     char magic[4];
00069     char name[64]; /* polyset name */
00070     int flags;
00071     int numFrames; /* all model surfaces should have the same */
00072     int numShaders; /* all model surfaces should have the same */
00073     int numVerts;
00074     int numTriangles;
00075     int ofsTriangles;
00076     int ofsShaders; /* offset from start of md3Surface_t */
00077     int ofsSt; /* texture coords are common for all frames */
00078     int ofsVertexes; /* numVerts * numFrames */
00079     int ofsEnd; /* next surface follows */
00080 } md3Surface_t;
00081 
00082 typedef struct md3Shader_s
00083 {
00084     char name[64];
00085     int shaderIndex; /* for ingame use */
00086 } md3Shader_t;
00087 
00088 typedef struct md3Triangle_s
00089 {
00090     int indexes[3];
00091 } md3Triangle_t;
00092 
00093 typedef struct md3TexCoord_s
00094 {
00095     float st[2];
00096 } md3TexCoord_t;
00097 
00098 typedef struct md3Vertex_s
00099 {
00100     short xyz[3];
00101     short normal;
00102 } md3Vertex_t;
00103 
00104 /* md3 model file md3 structure */
00105 typedef struct md3_s
00106 {
00107     char magic[4]; /* MD3_MAGIC */
00108     int version;
00109     char name[64]; /* model name */
00110     int flags;
00111     int numFrames;
00112     int numTags;
00113     int numSurfaces;
00114     int numSkins; /* number of skins for the mesh */
00115     int ofsFrames; /* offset for first frame */
00116     int ofsTags; /* numFrames * numTags */
00117     int ofsSurfaces; /* first surface, others follow */
00118     int ofsEnd; /* end of file */
00119 } md3_t;
00120 
00126 static int _md3_canload (PM_PARAMS_CANLOAD)
00127 {
00128     md3_t *md3;
00129 
00130     /* sanity check */
00131     if (bufSize < (sizeof(*md3) * 2))
00132         return PICO_PMV_ERROR_SIZE;
00133 
00134     /* set as md3 */
00135     md3 = (md3_t*) buffer;
00136 
00137     /* check md3 magic */
00138     if (*((int*) md3->magic) != *((int*) MD3_MAGIC))
00139         return PICO_PMV_ERROR_IDENT;
00140 
00141     /* check md3 version */
00142     if (_pico_little_long(md3->version) != MD3_VERSION)
00143         return PICO_PMV_ERROR_VERSION;
00144 
00145     /* file seems to be a valid md3 */
00146     return PICO_PMV_OK;
00147 }
00148 
00152 static picoModel_t *_md3_load (PM_PARAMS_LOAD)
00153 {
00154     int i, j;
00155     picoByte_t *bb;
00156     md3_t *md3;
00157     md3Surface_t *surface;
00158     md3Shader_t *shader;
00159     md3TexCoord_t *texCoord;
00160     md3Frame_t *frame;
00161     md3Triangle_t *triangle;
00162     md3Vertex_t *vertex;
00163     double lat, lng;
00164 
00165     picoModel_t *picoModel;
00166     picoSurface_t *picoSurface;
00167     picoShader_t *picoShader;
00168     picoVec3_t xyz, normal;
00169     picoVec2_t st;
00170     picoColor_t color;
00171 
00172     /* -------------------------------------------------
00173      md3 loading
00174      ------------------------------------------------- */
00175 
00176     /* set as md3 */
00177     bb = (picoByte_t*) buffer;
00178     md3 = (md3_t*) buffer;
00179 
00180     /* check ident and version */
00181     if (*((int*) md3->magic) != *((int*) MD3_MAGIC) || _pico_little_long(md3->version) != MD3_VERSION) {
00182         /* not an md3 file (todo: set error) */
00183         return NULL;
00184     }
00185 
00186     /* swap md3; sea: swaps fixed */
00187     md3->version = _pico_little_long(md3->version);
00188     md3->numFrames = _pico_little_long(md3->numFrames);
00189     md3->numTags = _pico_little_long(md3->numTags);
00190     md3->numSurfaces = _pico_little_long(md3->numSurfaces);
00191     md3->numSkins = _pico_little_long(md3->numSkins);
00192     md3->ofsFrames = _pico_little_long(md3->ofsFrames);
00193     md3->ofsTags = _pico_little_long(md3->ofsTags);
00194     md3->ofsSurfaces = _pico_little_long(md3->ofsSurfaces);
00195     md3->ofsEnd = _pico_little_long(md3->ofsEnd);
00196 
00197     /* do frame check */
00198     if (md3->numFrames < 1) {
00199         _pico_printf(PICO_ERROR, "MD3 with 0 frames");
00200         return NULL;
00201     }
00202 
00203     if (frameNum < 0 || frameNum >= md3->numFrames) {
00204         _pico_printf(PICO_ERROR, "Invalid or out-of-range MD3 frame specified");
00205         return NULL;
00206     }
00207 
00208     /* swap frames */
00209     frame = (md3Frame_t*) (bb + md3->ofsFrames);
00210     for (i = 0; i < md3->numFrames; i++, frame++) {
00211         frame->radius = _pico_little_float(frame->radius);
00212         for (j = 0; j < 3; j++) {
00213             frame->bounds[0][j] = _pico_little_float(frame->bounds[0][j]);
00214             frame->bounds[1][j] = _pico_little_float(frame->bounds[1][j]);
00215             frame->localOrigin[j] = _pico_little_float(frame->localOrigin[j]);
00216         }
00217     }
00218 
00219     /* swap surfaces */
00220     surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
00221     for (i = 0; i < md3->numSurfaces; i++) {
00222         /* swap surface md3; sea: swaps fixed */
00223         surface->flags = _pico_little_long(surface->flags);
00224         surface->numFrames = _pico_little_long(surface->numFrames);
00225         surface->numShaders = _pico_little_long(surface->numShaders);
00226         surface->numTriangles = _pico_little_long(surface->numTriangles);
00227         surface->ofsTriangles = _pico_little_long(surface->ofsTriangles);
00228         surface->numVerts = _pico_little_long(surface->numVerts);
00229         surface->ofsShaders = _pico_little_long(surface->ofsShaders);
00230         surface->ofsSt = _pico_little_long(surface->ofsSt);
00231         surface->ofsVertexes = _pico_little_long(surface->ofsVertexes);
00232         surface->ofsEnd = _pico_little_long(surface->ofsEnd);
00233 
00234         /* swap triangles */
00235         triangle = (md3Triangle_t*) ((picoByte_t*) surface + surface->ofsTriangles);
00236         for (j = 0; j < surface->numTriangles; j++, triangle++) {
00237             /* sea: swaps fixed */
00238             triangle->indexes[0] = _pico_little_long(triangle->indexes[0]);
00239             triangle->indexes[1] = _pico_little_long(triangle->indexes[1]);
00240             triangle->indexes[2] = _pico_little_long(triangle->indexes[2]);
00241         }
00242 
00243         /* swap st coords */
00244         texCoord = (md3TexCoord_t*) ((picoByte_t*) surface + surface->ofsSt);
00245         for (j = 0; j < surface->numVerts; j++, texCoord++) {
00246             texCoord->st[0] = _pico_little_float(texCoord->st[0]);
00247             texCoord->st[1] = _pico_little_float(texCoord->st[1]);
00248         }
00249 
00250         /* swap xyz/normals */
00251         vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes);
00252         for (j = 0; j < (surface->numVerts * surface->numFrames); j++, vertex++) {
00253             vertex->xyz[0] = _pico_little_short(vertex->xyz[0]);
00254             vertex->xyz[1] = _pico_little_short(vertex->xyz[1]);
00255             vertex->xyz[2] = _pico_little_short(vertex->xyz[2]);
00256             vertex->normal = _pico_little_short(vertex->normal);
00257         }
00258 
00259         /* get next surface */
00260         surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
00261     }
00262 
00263     /* -------------------------------------------------
00264      pico model creation
00265      ------------------------------------------------- */
00266 
00267     /* create new pico model */
00268     picoModel = PicoNewModel();
00269     if (picoModel == NULL) {
00270         _pico_printf(PICO_ERROR, "Unable to allocate a new model");
00271         return NULL;
00272     }
00273 
00274     /* do model setup */
00275     PicoSetModelFrameNum(picoModel, frameNum);
00276     PicoSetModelNumFrames(picoModel, md3->numFrames); /* sea */
00277     PicoSetModelName(picoModel, fileName);
00278     PicoSetModelFileName(picoModel, fileName);
00279 
00280     /* md3 surfaces become picomodel surfaces */
00281     surface = (md3Surface_t*) (bb + md3->ofsSurfaces);
00282 
00283     /* run through md3 surfaces */
00284     for (i = 0; i < md3->numSurfaces; i++) {
00285         /* allocate new pico surface */
00286         picoSurface = PicoNewSurface(picoModel);
00287         if (picoSurface == NULL) {
00288             _pico_printf(PICO_ERROR, "Unable to allocate a new model surface");
00289             PicoFreeModel(picoModel); /* sea */
00290             return NULL;
00291         }
00292 
00293         /* md3 model surfaces are all triangle meshes */
00294         PicoSetSurfaceType(picoSurface, PICO_TRIANGLES);
00295 
00296         /* set surface name */
00297         PicoSetSurfaceName(picoSurface, surface->name);
00298 
00299         /* create new pico shader -sea */
00300         picoShader = PicoNewShader(picoModel);
00301         if (picoShader == NULL) {
00302             _pico_printf(PICO_ERROR, "Unable to allocate a new model shader");
00303             PicoFreeModel(picoModel);
00304             return NULL;
00305         }
00306 
00307         /* detox and set shader name */
00308         shader = (md3Shader_t*) ((picoByte_t*) surface + surface->ofsShaders);
00309         _pico_setfext(shader->name, "");
00310         _pico_unixify(shader->name);
00311         PicoSetShaderName(picoShader, shader->name);
00312 
00313         /* associate current surface with newly created shader */
00314         PicoSetSurfaceShader(picoSurface, picoShader);
00315 
00316         /* copy indexes */
00317         triangle = (md3Triangle_t *) ((picoByte_t*) surface + surface->ofsTriangles);
00318 
00319         for (j = 0; j < surface->numTriangles; j++, triangle++) {
00320             PicoSetSurfaceIndex(picoSurface, (j * 3 + 0), (picoIndex_t) triangle->indexes[0]);
00321             PicoSetSurfaceIndex(picoSurface, (j * 3 + 1), (picoIndex_t) triangle->indexes[1]);
00322             PicoSetSurfaceIndex(picoSurface, (j * 3 + 2), (picoIndex_t) triangle->indexes[2]);
00323         }
00324 
00325         /* copy vertexes */
00326         texCoord = (md3TexCoord_t*) ((picoByte_t *) surface + surface->ofsSt);
00327         vertex = (md3Vertex_t*) ((picoByte_t*) surface + surface->ofsVertexes + surface->numVerts * frameNum
00328                 * sizeof(md3Vertex_t));
00329         _pico_set_color(color, 255, 255, 255, 255);
00330 
00331         for (j = 0; j < surface->numVerts; j++, texCoord++, vertex++) {
00332             /* set vertex origin */
00333             xyz[0] = MD3_SCALE * vertex->xyz[0];
00334             xyz[1] = MD3_SCALE * vertex->xyz[1];
00335             xyz[2] = MD3_SCALE * vertex->xyz[2];
00336             PicoSetSurfaceXYZ(picoSurface, j, xyz);
00337 
00338             /* decode lat/lng normal to 3 float normal */
00339             lat = (float) ((vertex->normal >> 8) & 0xff);
00340             lng = (float) (vertex->normal & 0xff);
00341             lat *= PICO_PI / 128;
00342             lng *= PICO_PI / 128;
00343             normal[0] = (picoVec_t) cos(lat) * (picoVec_t) sin(lng);
00344             normal[1] = (picoVec_t) sin(lat) * (picoVec_t) sin(lng);
00345             normal[2] = (picoVec_t) cos(lng);
00346             PicoSetSurfaceNormal(picoSurface, j, normal);
00347 
00348             /* set st coords */
00349             st[0] = texCoord->st[0];
00350             st[1] = texCoord->st[1];
00351             PicoSetSurfaceST(picoSurface, 0, j, st);
00352 
00353             /* set color */
00354             PicoSetSurfaceColor(picoSurface, 0, j, color);
00355         }
00356 
00357         /* get next surface */
00358         surface = (md3Surface_t*) ((picoByte_t*) surface + surface->ofsEnd);
00359     }
00360 
00361     /* return the new pico model */
00362     return picoModel;
00363 }
00364 
00365 /* pico file format module definition */
00366 const picoModule_t picoModuleMD3 = { "1.3", /* module version string */
00367 "Quake 3 Arena", /* module display name */
00368 "Randy Reddig", /* author's name */
00369 "2002 Randy Reddig", /* module copyright */
00370 { "md3", NULL, NULL, NULL /* default extensions to use */
00371 }, _md3_canload, /* validation routine */
00372 _md3_load, /* load routine */
00373 NULL, /* save validation routine */
00374 NULL /* save routine */
00375 };

Generated by  doxygen 1.6.2