r_model_md3.c

Go to the documentation of this file.
00001 
00006 /*
00007 Copyright (C) 1997-2001 Id Software, Inc.
00008 
00009 This program is free software; you can redistribute it and/or
00010 modify it under the terms of the GNU General Public License
00011 as published by the Free Software Foundation; either version 2
00012 of the License, or (at your option) any later version.
00013 
00014 This program is distributed in the hope that it will be useful,
00015 but WITHOUT ANY WARRANTY; without even the implied warranty of
00016 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
00017 
00018 See the GNU General Public License for more details.
00019 
00020 You should have received a copy of the GNU General Public License
00021 along with this program; if not, write to the Free Software
00022 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
00023 
00024 */
00025 
00026 #include "r_local.h"
00027 
00028 /*
00029 ==============================================================================
00030 MD3 ALIAS MODELS
00031 ==============================================================================
00032 */
00033 
00038 void R_ModLoadAliasMD3Model (model_t *mod, byte *buffer, int bufSize)
00039 {
00040     int version, i, j, l;
00041     const dmd3_t *md3;
00042     const dmd3frame_t *pinframe;
00043     const dmd3tag_t *pintag;
00044     const dmd3mesh_t *pinmesh;
00045     const dmd3skin_t *pinskin;
00046     const dmd3coord_t *pincoord;
00047     const dmd3vertex_t *pinvert;
00048     const int32_t *pinindex;
00049     int32_t *poutindex;
00050     mAliasVertex_t *poutvert;
00051     mAliasMesh_t *poutmesh;
00052     mAliasTag_t *pouttag;
00053     mAliasFrame_t *poutframe;
00054     float lat, lng;
00055 
00056     md3 = (dmd3_t *)buffer;
00057     version = LittleLong(md3->version);
00058 
00059     if (version != MD3_ALIAS_VERSION) {
00060         Com_Error(ERR_DROP, "%s has wrong version number (%i should be %i)",
00061                 mod->name, version, MD3_ALIAS_VERSION);
00062     }
00063 
00064     mod->type = mod_alias_md3;
00065     /* byte swap the header fields and sanity check */
00066     mod->alias.num_frames = LittleLong(md3->num_frames);
00067     mod->alias.num_tags = LittleLong(md3->num_tags);
00068     mod->alias.num_meshes = LittleLong(md3->num_meshes);
00069 
00070     if (mod->alias.num_frames <= 0)
00071         Com_Error(ERR_DROP, "model %s has no frames", mod->name);
00072     else if (mod->alias.num_frames > MD3_MAX_FRAMES)
00073         Com_Error(ERR_DROP, "model %s has too many frames", mod->name);
00074 
00075     if (mod->alias.num_tags > MD3_MAX_TAGS)
00076         Com_Error(ERR_DROP, "model %s has too many tags", mod->name);
00077     else if (mod->alias.num_tags < 0)
00078         Com_Error(ERR_DROP, "model %s has invalid number of tags", mod->name);
00079 
00080     if (mod->alias.num_meshes <= 0)
00081         Com_Error(ERR_DROP, "model %s has no meshes", mod->name);
00082     else if (mod->alias.num_meshes > MD3_MAX_MESHES)
00083         Com_Error(ERR_DROP, "model %s has too many meshes", mod->name);
00084 
00085     /* load the frames */
00086     pinframe = (const dmd3frame_t *)((const byte *)md3 + LittleLong(md3->ofs_frames));
00087     poutframe = mod->alias.frames = Mem_PoolAlloc(sizeof(mAliasFrame_t) * mod->alias.num_frames, vid_modelPool, 0);
00088 
00089     mod->radius = 0;
00090     ClearBounds(mod->mins, mod->maxs);
00091 
00092     for (i = 0; i < mod->alias.num_frames; i++, pinframe++, poutframe++) {
00093         for (j = 0; j < 3; j++) {
00094             poutframe->mins[j] = LittleFloat(pinframe->mins[j]);
00095             poutframe->maxs[j] = LittleFloat(pinframe->maxs[j]);
00096             poutframe->translate[j] = LittleFloat(pinframe->translate[j]);
00097         }
00098 
00099         poutframe->radius = LittleFloat(pinframe->radius);
00100         mod->radius = max(mod->radius, poutframe->radius);
00101         AddPointToBounds(poutframe->mins, mod->mins, mod->maxs);
00102         AddPointToBounds(poutframe->maxs, mod->mins, mod->maxs);
00103     }
00104 
00105     /* load the tags */
00106     if (mod->alias.num_tags) {
00107         pintag = (const dmd3tag_t *)((const byte *)md3 + LittleLong(md3->ofs_tags));
00108         pouttag = mod->alias.tags = Mem_PoolAlloc(sizeof(mAliasTag_t) * mod->alias.num_frames * mod->alias.num_tags, vid_modelPool, 0);
00109 
00110         for (i = 0; i < mod->alias.num_frames; i++) {
00111             for (l = 0; l < mod->alias.num_tags; l++, pintag++, pouttag++) {
00112                 memcpy(pouttag->name, pintag->name, MD3_MAX_PATH);
00113                 for (j = 0; j < 3; j++) {
00114                     pouttag->orient.origin[j] = LittleFloat(pintag->orient.origin[j]);
00115                     pouttag->orient.axis[0][j] = LittleFloat(pintag->orient.axis[0][j]);
00116                     pouttag->orient.axis[1][j] = LittleFloat(pintag->orient.axis[1][j]);
00117                     pouttag->orient.axis[2][j] = LittleFloat(pintag->orient.axis[2][j]);
00118                 }
00119                 /*Com_Printf("X: (%f %f %f) Y: (%f %f %f) Z: (%f %f %f)\n",
00120                     pouttag->orient.axis[0][0], pouttag->orient.axis[0][1], pouttag->orient.axis[0][2],
00121                     pouttag->orient.axis[1][0], pouttag->orient.axis[1][1], pouttag->orient.axis[1][2],
00122                     pouttag->orient.axis[2][0], pouttag->orient.axis[2][1], pouttag->orient.axis[2][2]); */
00123             }
00124         }
00125     }
00126 
00127     /* load the meshes */
00128     pinmesh = (const dmd3mesh_t *)((const byte *)md3 + LittleLong(md3->ofs_meshes));
00129     poutmesh = mod->alias.meshes = Mem_PoolAlloc(sizeof(mAliasMesh_t) * mod->alias.num_meshes, vid_modelPool, 0);
00130 
00131     for (i = 0; i < mod->alias.num_meshes; i++, poutmesh++) {
00132         memcpy(poutmesh->name, pinmesh->name, MD3_MAX_PATH);
00133 
00134         if (strncmp(pinmesh->id, "IDP3", 4)) {
00135             Com_Error(ERR_DROP, "mesh %s in model %s has wrong id (%s should be %i)",
00136                     poutmesh->name, mod->name, pinmesh->id, IDMD3HEADER);
00137         }
00138 
00139         poutmesh->num_tris = LittleLong(pinmesh->num_tris);
00140         poutmesh->num_skins = LittleLong(pinmesh->num_skins);
00141         poutmesh->num_verts = LittleLong(pinmesh->num_verts);
00142 
00143         if (poutmesh->num_skins <= 0)
00144             Com_Error(ERR_DROP, "mesh %i in model %s has no skins", i, mod->name);
00145         else if (poutmesh->num_skins > MD3_MAX_SHADERS)
00146             Com_Error(ERR_DROP, "mesh %i in model %s has too many skins", i, mod->name);
00147 
00148         if (poutmesh->num_tris <= 0)
00149             Com_Error(ERR_DROP, "mesh %i in model %s has no triangles", i, mod->name);
00150         else if (poutmesh->num_tris > MD3_MAX_TRIANGLES)
00151             Com_Error(ERR_DROP, "mesh %i in model %s has too many triangles", i, mod->name);
00152 
00153         if (poutmesh->num_verts <= 0)
00154             Com_Error(ERR_DROP, "mesh %i in model %s has no vertices", i, mod->name);
00155         else if (poutmesh->num_verts > MD3_MAX_VERTS)
00156             Com_Error(ERR_DROP, "mesh %i in model %s has too many vertices", i, mod->name);
00157 
00158         /* register all skins */
00159         pinskin = (const dmd3skin_t *)((const byte *)pinmesh + LittleLong(pinmesh->ofs_skins));
00160         poutmesh->skins = Mem_PoolAlloc(sizeof(mAliasSkin_t) * poutmesh->num_skins, vid_modelPool, 0);
00161 
00162         for (j = 0; j < mod->alias.meshes[i].num_skins; j++) {
00163             mod->alias.meshes[i].skins[j].skin = R_AliasModelGetSkin(mod->name, pinskin->name);
00164             Q_strncpyz(mod->alias.meshes[i].skins[j].name,
00165                 mod->alias.meshes[i].skins[j].skin->name, MODEL_MAX_PATH);
00166         }
00167 
00168         /* load the indexes */
00169         pinindex = (const int32_t *)((const byte *)pinmesh + LittleLong(pinmesh->ofs_tris));
00170         poutindex = poutmesh->indexes = Mem_PoolAlloc(sizeof(int32_t) * poutmesh->num_tris * 3, vid_modelPool, 0);
00171 
00172         for (j = 0; j < poutmesh->num_tris; j++, pinindex += 3, poutindex += 3) {
00173             poutindex[0] = (int32_t)LittleLong(pinindex[0]);
00174             poutindex[1] = (int32_t)LittleLong(pinindex[1]);
00175             poutindex[2] = (int32_t)LittleLong(pinindex[2]);
00176         }
00177 
00178         /* load the texture coordinates */
00179         pincoord = (const dmd3coord_t *)((const byte *)pinmesh + LittleLong(pinmesh->ofs_tcs));
00180         poutmesh->stcoords = Mem_PoolAlloc(sizeof(mAliasCoord_t) * poutmesh->num_verts, vid_modelPool, 0);
00181 
00182         for (j = 0; j < poutmesh->num_verts; j++, pincoord++) {
00183             poutmesh->stcoords[j][0] = LittleFloat(pincoord->st[0]);
00184             poutmesh->stcoords[j][1] = LittleFloat(pincoord->st[1]);
00185         }
00186 
00187         /* load the vertexes and normals */
00188         pinvert = (const dmd3vertex_t *)((const byte *)pinmesh + LittleLong(pinmesh->ofs_verts));
00189         poutvert = poutmesh->vertexes = Mem_PoolAlloc(mod->alias.num_frames * poutmesh->num_verts * sizeof(mAliasVertex_t), vid_modelPool, 0);
00190 
00191         for (l = 0; l < mod->alias.num_frames; l++) {
00192             for (j = 0; j < poutmesh->num_verts; j++, pinvert++, poutvert++) {
00193                 poutvert->point[0] = LittleShort(pinvert->point[0]) * MD3_XYZ_SCALE;
00194                 poutvert->point[1] = LittleShort(pinvert->point[1]) * MD3_XYZ_SCALE;
00195                 poutvert->point[2] = LittleShort(pinvert->point[2]) * MD3_XYZ_SCALE;
00196 
00197                 lat = (pinvert->norm >> 8) & 0xff;
00198                 lng = (pinvert->norm & 0xff);
00199 
00200                 lat *= M_PI / 128.0f;
00201                 lng *= M_PI / 128.0f;
00202 
00203                 poutvert->normal[0] = cos(lat) * sin(lng);
00204                 poutvert->normal[1] = sin(lat) * sin(lng);
00205                 poutvert->normal[2] = cos(lng);
00206             }
00207         }
00208         pinmesh = (const dmd3mesh_t *)((const byte *)pinmesh + LittleLong(pinmesh->meshsize));
00209 
00210         R_ModLoadArrayData(&mod->alias, poutmesh, qtrue);
00211     }
00212 }

Generated by  doxygen 1.6.2