diff --git a/include/model.h b/include/model.h index 8f09317..52adf54 100644 --- a/include/model.h +++ b/include/model.h @@ -318,21 +318,12 @@ typedef struct mtriangle_s { #define MAX_SKINS 32 typedef struct { - int ident; - int version; - vec3_t scale; - vec3_t scale_origin; - float boundingradius; - vec3_t eyeposition; - int numskins; - int skinwidth; - int skinheight; - int numverts; - int numtris; - int numframes; - synctype_t synctype; - int flags; - float size; + int model; + int stverts; + int skindesc; + int triangles; + + mdl_t mdl; int numposes; int poseverts; @@ -340,11 +331,8 @@ typedef struct { int commands; // gl command list with embedded s/t int gl_texturenum[MAX_SKINS][4]; int gl_fb_texturenum[MAX_SKINS][4]; - int model; - int stverts; - int skindesc; - int triangles; int texels[MAX_SKINS]; // only for player skins + maliasframedesc_t frames[1]; } aliashdr_t; diff --git a/source/Makefile.am b/source/Makefile.am index 27b57c1..e6f8d5c 100644 --- a/source/Makefile.am +++ b/source/Makefile.am @@ -49,7 +49,7 @@ common_ASM= sys_ia32.S worlda.S $(math_ASM) #endif common_SOURCES= crc.c cvar.c cmd.c mathlib.c wad.c world.c \ - model.c model_brush.c model_sprite.c \ + model.c model_alias.c model_brush.c model_sprite.c \ msg.c r_part.c sizebuf.c qendian.c qargs.c quakefs.c \ va.c quakeio.c link.c com.c \ zone.c $(common_ASM) diff --git a/source/gl_mesh.c b/source/gl_mesh.c index b54af12..9a189fc 100644 --- a/source/gl_mesh.c +++ b/source/gl_mesh.c @@ -109,7 +109,7 @@ int StripLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + for (j=starttri+1, check=&triangles[starttri+1] ; jmdl.numtris ; j++, check++) { if (check->facesfront != last->facesfront) continue; @@ -143,7 +143,7 @@ nexttri: done: // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) + for (j=starttri+1 ; jmdl.numtris ; j++) if (used[j] == 2) used[j] = 0; @@ -179,7 +179,7 @@ int FanLength (int starttri, int startv) // look for a matching triangle nexttri: - for (j=starttri+1, check=&triangles[starttri+1] ; jnumtris ; j++, check++) + for (j=starttri+1, check=&triangles[starttri+1] ; jmdl.numtris ; j++, check++) { if (check->facesfront != last->facesfront) continue; @@ -210,7 +210,7 @@ nexttri: done: // clear the temp used flags - for (j=starttri+1 ; jnumtris ; j++) + for (j=starttri+1 ; jmdl.numtris ; j++) if (used[j] == 2) used[j] = 0; @@ -242,7 +242,7 @@ void BuildTris (void) numorder = 0; numcommands = 0; memset (used, 0, sizeof(used)); - for (i=0 ; inumtris ; i++) + for (i=0 ; imdl.numtris ; i++) { // pick an unused triangle and start the trifan if (used[i]) @@ -289,9 +289,9 @@ void BuildTris (void) s = stverts[k].s; t = stverts[k].t; if (!triangles[besttris[0]].facesfront && stverts[k].onseam) - s += pheader->skinwidth / 2; // on back side - s = (s + 0.5) / pheader->skinwidth; - t = (t + 0.5) / pheader->skinheight; + s += pheader->mdl.skinwidth / 2; // on back side + s = (s + 0.5) / pheader->mdl.skinwidth; + t = (t + 0.5) / pheader->mdl.skinheight; *(float *)&commands[numcommands++] = s; *(float *)&commands[numcommands++] = t; @@ -300,10 +300,10 @@ void BuildTris (void) commands[numcommands++] = 0; // end of list marker - Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->numtris, numorder, numcommands); + Con_DPrintf ("%3i tri %3i vert %3i cmd\n", pheader->mdl.numtris, numorder, numcommands); allverts += numorder; - alltris += pheader->numtris; + alltris += pheader->mdl.numtris; } diff --git a/source/gl_model_alias.c b/source/gl_model_alias.c index 4187b3b..7476ee2 100644 --- a/source/gl_model_alias.c +++ b/source/gl_model_alias.c @@ -1,5 +1,5 @@ /* - gl_model.c + gl_model_alias.c model loading and caching @@ -51,100 +51,17 @@ ALIAS MODELS ============================================================================== */ -aliashdr_t *pheader; +extern aliashdr_t *pheader; -stvert_t stverts[MAXALIASVERTS]; -mtriangle_t triangles[MAXALIASTRIS]; +extern stvert_t stverts[MAXALIASVERTS]; +extern mtriangle_t triangles[MAXALIASTRIS]; // a pose is a single set of vertexes. a frame may be // an animating sequence of poses -trivertx_t *poseverts[MAXALIASFRAMES]; -int posenum; +extern trivertx_t *poseverts[MAXALIASFRAMES]; +extern int posenum; -byte player_8bit_texels[320*200]; - -/* -================= -Mod_LoadAliasFrame -================= -*/ -void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame) -{ - trivertx_t *pinframe; - int i; - daliasframe_t *pdaliasframe; - - pdaliasframe = (daliasframe_t *)pin; - - strcpy (frame->name, pdaliasframe->name); - frame->firstpose = posenum; - frame->numposes = 1; - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about - // endianness - frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i]; - frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i]; - } - - pinframe = (trivertx_t *)(pdaliasframe + 1); - - poseverts[posenum] = pinframe; - posenum++; - - pinframe += pheader->numverts; - - return (void *)pinframe; -} - - -/* -================= -Mod_LoadAliasGroup -================= -*/ -void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame) -{ - daliasgroup_t *pingroup; - int i, numframes; - daliasinterval_t *pin_intervals; - void *ptemp; - - pingroup = (daliasgroup_t *)pin; - - numframes = LittleLong (pingroup->numframes); - - frame->firstpose = posenum; - frame->numposes = numframes; - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about endianness - frame->bboxmin.v[i] = pingroup->bboxmin.v[i]; - frame->bboxmin.v[i] = pingroup->bboxmax.v[i]; - } - - pin_intervals = (daliasinterval_t *)(pingroup + 1); - - frame->interval = LittleFloat (pin_intervals->interval); - - pin_intervals += numframes; - - ptemp = (void *)pin_intervals; - - for (i=0 ; inumverts; - } - - return ptemp; -} - -//========================================================= +extern byte player_8bit_texels[320*200]; /* ================= @@ -222,92 +139,109 @@ void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight ) } } +void *Mod_LoadSkin (byte *skin, int skinsize, int snum, int gnum, qboolean group) +{ + int j; + char name[32]; + + Mod_FloodFillSkin( skin, pheader->mdl.skinwidth, pheader->mdl.skinheight ); + + // This block is GL fullbright support for objects... + { + int pixels; + byte *ptexel; + + // Check for fullbright pixels.. + pixels = pheader->mdl.skinwidth * pheader->mdl.skinheight; + ptexel = (byte *)(skin + 1); + + for (j=0 ; j= 256-32) { + loadmodel->hasfullbrights = true; + break; + } + } + + if (loadmodel->hasfullbrights) { + byte *ptexels; + + //ptexels = Hunk_Alloc(s); + ptexels = malloc(pixels); + + if (group) { + snprintf(name, sizeof(name), "fb_%s_%i_%i", loadmodel->name,snum,gnum); + } else { + snprintf(name, sizeof(name), "fb_%s_%i", loadmodel->name,snum); + } + Con_DPrintf("FB Model ID: '%s'\n", name); + for (j=0 ; j= 256-32) { + ptexels[j] = ptexel[j]; + } else { + ptexels[j] = 255; + } + } + pheader->gl_fb_texturenum[snum][gnum] = + GL_LoadTexture (name, pheader->mdl.skinwidth, + pheader->mdl.skinheight, ptexels, true, true, 1); + + free(ptexels); + } + } + + if (group) { + snprintf(name, sizeof(name), "%s_%i_%i", loadmodel->name,snum,gnum); + } else { + snprintf(name, sizeof(name), "%s_%i", loadmodel->name,snum); + } + pheader->gl_texturenum[snum][gnum] = + GL_LoadTexture (name, pheader->mdl.skinwidth, + pheader->mdl.skinheight, skin, true, false, 1); + // alpha param was true for non group skins + return skin + skinsize; +} + /* =============== Mod_LoadAllSkins =============== */ -void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype) +void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) { int i, j, k; - char name[32]; - int s; + int skinsize; byte *skin; daliasskingroup_t *pinskingroup; int groupskins; daliasskininterval_t *pinskinintervals; - skin = (byte *)(pskintype + 1); + skin = (byte *)pskintype; if (numskins < 1 || numskins > MAX_SKINS) Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); - s = pheader->skinwidth * pheader->skinheight; + skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; for (i=0 ; itype == ALIAS_SKIN_SINGLE) { - Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight ); + skin+=4; + skin = Mod_LoadSkin (skin, skinsize, i, 0, false); // save 8 bit texels for the player model to remap if (!strcmp(loadmodel->name,"progs/player.mdl")) { - if (s > sizeof(player_8bit_texels)) + if (skinsize > sizeof(player_8bit_texels)) Sys_Error ("Player skin too large"); - memcpy (player_8bit_texels, (byte *)(pskintype + 1), s); + memcpy (player_8bit_texels, skin, skinsize); } - // This block is GL fullbright support for objects... - { - int pixels; - byte *ptexel; - - // Check for fullbright pixels.. - pixels = pheader->skinwidth * pheader->skinheight; - ptexel = (byte *)(pskintype + 1); - - for (j=0 ; j= 256-32) { - loadmodel->hasfullbrights = true; - break; - } - } - - if (loadmodel->hasfullbrights) { - byte *ptexels; - - //ptexels = Hunk_Alloc(s); - ptexels = malloc(pixels); - - snprintf(name, sizeof(name), "fb_%s_%i", loadmodel->name,i); - Con_DPrintf("FB Model ID: '%s'\n", name); - for (j=0 ; j= 256-32) { - ptexels[j] = ptexel[j]; - } else { - ptexels[j] = 255; - } - } - pheader->gl_fb_texturenum[i][0] = - pheader->gl_fb_texturenum[i][1] = - pheader->gl_fb_texturenum[i][2] = - pheader->gl_fb_texturenum[i][3] = - GL_LoadTexture (name, pheader->skinwidth, - pheader->skinheight, ptexels, true, true, 1); - - free(ptexels); - } + for (j=1; j < 4; j++) { + pheader->gl_texturenum[i][j] = + pheader->gl_texturenum[i][j - 1]; + pheader->gl_fb_texturenum[i][j] = + pheader->gl_fb_texturenum[i][j - 1]; } - - - snprintf (name, sizeof(name), "%s_%i", loadmodel->name, i); - pheader->gl_texturenum[i][0] = - pheader->gl_texturenum[i][1] = - pheader->gl_texturenum[i][2] = - pheader->gl_texturenum[i][3] = - GL_LoadTexture (name, pheader->skinwidth, - pheader->skinheight, (byte *)(pskintype + 1), true, true, 1); - pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s); } else { // animating skin group. yuck. Con_Printf("Animating Skin Group, if you get this message please notify warp@debian.org\n"); @@ -317,189 +251,22 @@ void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype) pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); pskintype = (void *)(pinskinintervals + groupskins); + skin = (byte *)pskintype; for (j=0 ; jskinwidth, pheader->skinheight ); - snprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i,j); - pheader->gl_texturenum[i][j&3] = - GL_LoadTexture (name, pheader->skinwidth, - pheader->skinheight, (byte *)(pskintype), true, false, 1); - pskintype = (daliasskintype_t *)((byte *)(pskintype) + s); + skin+=4; + skin = Mod_LoadSkin (skin, skinsize, i, j, true); } k = j; - for (/* */; j < 4; j++) - pheader->gl_texturenum[i][j&3] = - pheader->gl_texturenum[i][j - k]; + for (/* */; j < 4; j++) { + pheader->gl_texturenum[i][j] = + pheader->gl_texturenum[i][j - k]; + pheader->gl_fb_texturenum[i][j] = + pheader->gl_fb_texturenum[i][j - k]; + } } } - return (void *)pskintype; -} - - -//========================================================================= - -/* -================= -Mod_LoadAliasModel -================= -*/ -void Mod_LoadAliasModel (model_t *mod, void *buffer) -{ - int i, j; - mdl_t *pinmodel; - stvert_t *pinstverts; - dtriangle_t *pintriangles; - int version, numframes; - int size; - daliasframetype_t *pframetype; - daliasskintype_t *pskintype; - int start, end, total; - - start = Hunk_LowMark (); - - pinmodel = (mdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - Sys_Error ("%s has wrong version number (%i should be %i)", - mod->name, version, ALIAS_VERSION); - -// -// allocate space for a working header, plus all the data except the frames, -// skin and group info -// - size = sizeof (aliashdr_t) - + (LittleLong (pinmodel->numframes) - 1) * - sizeof (pheader->frames[0]); - pheader = Hunk_AllocName (size, loadname); - - mod->flags = LittleLong (pinmodel->flags); - -// -// endian-adjust and copy the data, starting with the alias model header -// - pheader->boundingradius = LittleFloat (pinmodel->boundingradius); - pheader->numskins = LittleLong (pinmodel->numskins); - pheader->skinwidth = LittleLong (pinmodel->skinwidth); - pheader->skinheight = LittleLong (pinmodel->skinheight); - - if (pheader->skinheight > MAX_LBM_HEIGHT) - Sys_Error ("model %s has a skin taller than %d", mod->name, - MAX_LBM_HEIGHT); - - pheader->numverts = LittleLong (pinmodel->numverts); - - if (pheader->numverts <= 0) - Sys_Error ("model %s has no vertices", mod->name); - - if (pheader->numverts > MAXALIASVERTS) - Sys_Error ("model %s has too many vertices", mod->name); - - pheader->numtris = LittleLong (pinmodel->numtris); - - if (pheader->numtris <= 0) - Sys_Error ("model %s has no triangles", mod->name); - - pheader->numframes = LittleLong (pinmodel->numframes); - numframes = pheader->numframes; - if (numframes < 1) - Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); - - pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; - mod->synctype = LittleLong (pinmodel->synctype); - mod->numframes = pheader->numframes; - - for (i=0 ; i<3 ; i++) - { - pheader->scale[i] = LittleFloat (pinmodel->scale[i]); - pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); - pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); - } - - -// -// load the skins -// - pskintype = (daliasskintype_t *)&pinmodel[1]; - pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype); - -// -// load base s and t vertices -// - pinstverts = (stvert_t *)pskintype; - - for (i=0 ; inumverts ; i++) - { - stverts[i].onseam = LittleLong (pinstverts[i].onseam); - stverts[i].s = LittleLong (pinstverts[i].s); - stverts[i].t = LittleLong (pinstverts[i].t); - } - -// -// load triangle lists -// - pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts]; - - for (i=0 ; inumtris ; i++) - { - triangles[i].facesfront = LittleLong (pintriangles[i].facesfront); - - for (j=0 ; j<3 ; j++) - { - triangles[i].vertindex[j] = - LittleLong (pintriangles[i].vertindex[j]); - } - } - -// -// load the frames -// - posenum = 0; - pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris]; - - for (i=0 ; itype); - - if (frametype == ALIAS_SINGLE) - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]); - } - else - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]); - } - } - - pheader->numposes = posenum; - - mod->type = mod_alias; - -// FIXME: do this right - mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; - mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; - - // - // build the draw lists - // - GL_MakeAliasModelDisplayLists (mod, pheader); - -// -// move the complete, relocatable alias model to the cache -// - end = Hunk_LowMark (); - total = end - start; - - Cache_Alloc (&mod->cache, total, loadname); - if (!mod->cache.data) - return; - memcpy (mod->cache.data, pheader, total); - - Hunk_FreeToLowMark (start); + return (void *)skin; } diff --git a/source/gl_rmain.c b/source/gl_rmain.c index 00995ae..5764c49 100644 --- a/source/gl_rmain.c +++ b/source/gl_rmain.c @@ -469,9 +469,9 @@ static void GL_DrawAliasShadow (aliashdr_t *paliashdr, int posenum) order += 2; // normals and vertexes come from the frame list - point[0] = verts->v[0] * paliashdr->scale[0] + paliashdr->scale_origin[0]; - point[1] = verts->v[1] * paliashdr->scale[1] + paliashdr->scale_origin[1]; - point[2] = verts->v[2] * paliashdr->scale[2] + paliashdr->scale_origin[2]; + point[0] = verts->v[0] * paliashdr->mdl.scale[0] + paliashdr->mdl.scale_origin[0]; + point[1] = verts->v[1] * paliashdr->mdl.scale[1] + paliashdr->mdl.scale_origin[1]; + point[2] = verts->v[2] * paliashdr->mdl.scale[2] + paliashdr->mdl.scale_origin[2]; point[0] -= shadevector[0]*(point[2]+lheight); point[1] -= shadevector[1]*(point[2]+lheight); @@ -499,7 +499,7 @@ static void R_SetupAliasFrame (int frame, aliashdr_t *paliashdr, qboolean fb) int pose, numposes; float interval; - if ((frame >= paliashdr->numframes) || (frame < 0)) + if ((frame >= paliashdr->mdl.numframes) || (frame < 0)) { Con_DPrintf ("R_AliasSetupFrame: no such frame %d\n", frame); frame = 0; @@ -599,7 +599,7 @@ static void R_DrawAliasModel (entity_t *e) // paliashdr = (aliashdr_t *)Mod_Extradata (currententity->model); - c_alias_polys += paliashdr->numtris; + c_alias_polys += paliashdr->mdl.numtris; // // draw all the triangles @@ -613,14 +613,14 @@ static void R_DrawAliasModel (entity_t *e) if (!strcmp (clmodel->name, "progs/eyes.mdl") ) { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2] - (22 + 8)); + glTranslatef (paliashdr->mdl.scale_origin[0], paliashdr->mdl.scale_origin[1], paliashdr->mdl.scale_origin[2] - (22 + 8)); // double size of eyes, since they are really hard to see in gl - glScalef (paliashdr->scale[0]*2, paliashdr->scale[1]*2, paliashdr->scale[2]*2); + glScalef (paliashdr->mdl.scale[0]*2, paliashdr->mdl.scale[1]*2, paliashdr->mdl.scale[2]*2); } else { - glTranslatef (paliashdr->scale_origin[0], paliashdr->scale_origin[1], paliashdr->scale_origin[2]); - glScalef (paliashdr->scale[0], paliashdr->scale[1], paliashdr->scale[2]); + glTranslatef (paliashdr->mdl.scale_origin[0], paliashdr->mdl.scale_origin[1], paliashdr->mdl.scale_origin[2]); + glScalef (paliashdr->mdl.scale[0], paliashdr->mdl.scale[1], paliashdr->mdl.scale[2]); } anim = (int)(cl.time*10) & 3; diff --git a/source/gl_rmisc.c b/source/gl_rmisc.c index 0000e25..16c4ce5 100644 --- a/source/gl_rmisc.c +++ b/source/gl_rmisc.c @@ -340,8 +340,8 @@ void R_TranslatePlayerSkin (int playernum) return; // only translate skins on alias models paliashdr = (aliashdr_t *)Mod_Extradata (model); - s = paliashdr->skinwidth * paliashdr->skinheight; - if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->numskins) { + s = paliashdr->mdl.skinwidth * paliashdr->mdl.skinheight; + if (currententity->skinnum < 0 || currententity->skinnum >= paliashdr->mdl.numskins) { Con_Printf("(%d): Invalid player skin #%d\n", playernum, currententity->skinnum); original = (byte *)paliashdr + paliashdr->texels[0]; } else @@ -349,8 +349,8 @@ void R_TranslatePlayerSkin (int playernum) if (s & 3) Sys_Error ("R_TranslateSkin: s&3"); - inwidth = paliashdr->skinwidth; - inheight = paliashdr->skinheight; + inwidth = paliashdr->mdl.skinwidth; + inheight = paliashdr->mdl.skinheight; // because this happens during gameplay, do it fast // instead of sending it through gl_upload 8 diff --git a/source/model_alias.c b/source/model_alias.c new file mode 100644 index 0000000..c933f88 --- /dev/null +++ b/source/model_alias.c @@ -0,0 +1,314 @@ +/* + model_alias.c + + model loading and caching + + Copyright (C) 1996-1997 Id Software, Inc. + + This program is free software; you can redistribute it and/or + modify it under the terms of the GNU General Public License + as published by the Free Software Foundation; either version 2 + of the License, or (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + + See the GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to: + + Free Software Foundation, Inc. + 59 Temple Place - Suite 330 + Boston, MA 02111-1307, USA + + $Id$ +*/ + +// models are the only shared resource between a client and server running +// on the same machine. + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include "r_local.h" +#include "sys.h" +#include "console.h" +#include "qendian.h" +#include "checksum.h" +#include "glquake.h" + +extern char loadname[]; +extern model_t *loadmodel; + +void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex); + +/* +============================================================================== + +ALIAS MODELS + +============================================================================== +*/ + +aliashdr_t *pheader; + +stvert_t stverts[MAXALIASVERTS]; +mtriangle_t triangles[MAXALIASTRIS]; + +// a pose is a single set of vertexes. a frame may be +// an animating sequence of poses +trivertx_t *poseverts[MAXALIASFRAMES]; +int posenum; + +byte player_8bit_texels[320*200]; + +/* +================= +Mod_LoadAliasFrame +================= +*/ +void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame) +{ + trivertx_t *pinframe; + int i; + daliasframe_t *pdaliasframe; + + pdaliasframe = (daliasframe_t *)pin; + + strcpy (frame->name, pdaliasframe->name); + frame->firstpose = posenum; + frame->numposes = 1; + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about + // endianness + frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i]; + frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i]; + } + + pinframe = (trivertx_t *)(pdaliasframe + 1); + + poseverts[posenum] = pinframe; + posenum++; + + pinframe += pheader->mdl.numverts; + + return (void *)pinframe; +} + + +/* +================= +Mod_LoadAliasGroup +================= +*/ +void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame) +{ + daliasgroup_t *pingroup; + int i, numframes; + daliasinterval_t *pin_intervals; + void *ptemp; + + pingroup = (daliasgroup_t *)pin; + + numframes = LittleLong (pingroup->numframes); + + frame->firstpose = posenum; + frame->numposes = numframes; + + for (i=0 ; i<3 ; i++) + { + // these are byte values, so we don't have to worry about endianness + frame->bboxmin.v[i] = pingroup->bboxmin.v[i]; + frame->bboxmin.v[i] = pingroup->bboxmax.v[i]; + } + + pin_intervals = (daliasinterval_t *)(pingroup + 1); + + frame->interval = LittleFloat (pin_intervals->interval); + + pin_intervals += numframes; + + ptemp = (void *)pin_intervals; + + for (i=0 ; imdl.numverts; + } + + return ptemp; +} + +//========================================================================= + +/* +================= +Mod_LoadAliasModel +================= +*/ +void Mod_LoadAliasModel (model_t *mod, void *buffer) +{ + int i, j; + mdl_t *pinmodel, *pmodel; + stvert_t *pinstverts; + dtriangle_t *pintriangles; + int version, numframes; + int size; + daliasframetype_t *pframetype; + daliasskintype_t *pskintype; + int start, end, total; + + start = Hunk_LowMark (); + + pinmodel = (mdl_t *)buffer; + + version = LittleLong (pinmodel->version); + if (version != ALIAS_VERSION) + Sys_Error ("%s has wrong version number (%i should be %i)", + mod->name, version, ALIAS_VERSION); + +// +// allocate space for a working header, plus all the data except the frames, +// skin and group info +// + size = (int)&((aliashdr_t*)0)->frames[LittleLong (pinmodel->numframes)]; + pheader = Hunk_AllocName (size, loadname); + memset(pheader, 0, size); + pmodel = &pheader->mdl; + pheader->model = (byte*)pmodel - (byte*)pheader; + + mod->flags = LittleLong (pinmodel->flags); + +// +// endian-adjust and copy the data, starting with the alias model header +// + pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); + pmodel->numskins = LittleLong (pinmodel->numskins); + pmodel->skinwidth = LittleLong (pinmodel->skinwidth); + pmodel->skinheight = LittleLong (pinmodel->skinheight); + + if (pmodel->skinheight > MAX_LBM_HEIGHT) + Sys_Error ("model %s has a skin taller than %d", mod->name, + MAX_LBM_HEIGHT); + + pmodel->numverts = LittleLong (pinmodel->numverts); + + if (pmodel->numverts <= 0) + Sys_Error ("model %s has no vertices", mod->name); + + if (pmodel->numverts > MAXALIASVERTS) + Sys_Error ("model %s has too many vertices", mod->name); + + pmodel->numtris = LittleLong (pinmodel->numtris); + + if (pmodel->numtris <= 0) + Sys_Error ("model %s has no triangles", mod->name); + + pmodel->numframes = LittleLong (pinmodel->numframes); + numframes = pmodel->numframes; + if (numframes < 1) + Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); + + pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; + mod->synctype = LittleLong (pinmodel->synctype); + mod->numframes = pmodel->numframes; + + for (i=0 ; i<3 ; i++) + { + pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); + pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); + pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); + } + + +// +// load the skins +// + pskintype = (daliasskintype_t *)&pinmodel[1]; + pskintype = Mod_LoadAllSkins (pheader->mdl.numskins, pskintype, &pheader->skindesc); + +// +// load base s and t vertices +// + pinstverts = (stvert_t *)pskintype; + + for (i=0 ; imdl.numverts ; i++) + { + stverts[i].onseam = LittleLong (pinstverts[i].onseam); + stverts[i].s = LittleLong (pinstverts[i].s); + stverts[i].t = LittleLong (pinstverts[i].t); + } + +// +// load triangle lists +// + pintriangles = (dtriangle_t *)&pinstverts[pheader->mdl.numverts]; + + for (i=0 ; imdl.numtris ; i++) + { + triangles[i].facesfront = LittleLong (pintriangles[i].facesfront); + + for (j=0 ; j<3 ; j++) + { + triangles[i].vertindex[j] = + LittleLong (pintriangles[i].vertindex[j]); + } + } + +// +// load the frames +// + posenum = 0; + pframetype = (daliasframetype_t *)&pintriangles[pheader->mdl.numtris]; + + for (i=0 ; itype); + + if (frametype == ALIAS_SINGLE) + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]); + } + else + { + pframetype = (daliasframetype_t *) + Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]); + } + } + + pheader->numposes = posenum; + + mod->type = mod_alias; + +// FIXME: do this right + mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; + mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; + + // + // build the draw lists + // + GL_MakeAliasModelDisplayLists (mod, pheader); + +// +// move the complete, relocatable alias model to the cache +// + end = Hunk_LowMark (); + total = end - start; + + Cache_Alloc (&mod->cache, total, loadname); + if (!mod->cache.data) + return; + memcpy (mod->cache.data, pheader, total); + + Hunk_FreeToLowMark (start); +} diff --git a/source/sw_model_alias.c b/source/sw_model_alias.c index f2b54c0..e1a9876 100644 --- a/source/sw_model_alias.c +++ b/source/sw_model_alias.c @@ -1,5 +1,5 @@ /* - model.c + sw_model_alias.c model loading and caching @@ -26,6 +26,9 @@ $Id$ */ +// models are the only shared resource between a client and server running +// on the same machine. + #ifdef HAVE_CONFIG_H # include "config.h" #endif @@ -35,8 +38,10 @@ #include "console.h" #include "qendian.h" #include "checksum.h" +#include "glquake.h" extern char loadname[]; +extern model_t *loadmodel; /* ============================================================================== @@ -46,434 +51,115 @@ ALIAS MODELS ============================================================================== */ -/* -================= -Mod_LoadAliasFrame -================= -*/ -void * Mod_LoadAliasFrame (void * pin, int *pframeindex, int numv, - trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name) -{ - trivertx_t *pframe, *pinframe; - int i, j; - daliasframe_t *pdaliasframe; - - pdaliasframe = (daliasframe_t *)pin; - - strcpy (name, pdaliasframe->name); - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about - // endianness - pbboxmin->v[i] = pdaliasframe->bboxmin.v[i]; - pbboxmax->v[i] = pdaliasframe->bboxmax.v[i]; - } - - pinframe = (trivertx_t *)(pdaliasframe + 1); - pframe = Hunk_AllocName (numv * sizeof(*pframe), loadname); - - *pframeindex = (byte *)pframe - (byte *)pheader; - - for (j=0 ; jnumframes); - - paliasgroup = Hunk_AllocName (sizeof (maliasgroup_t) + - (numframes - 1) * sizeof (paliasgroup->frames[0]), loadname); - - paliasgroup->numframes = numframes; - - for (i=0 ; i<3 ; i++) - { - // these are byte values, so we don't have to worry about endianness - pbboxmin->v[i] = pingroup->bboxmin.v[i]; - pbboxmax->v[i] = pingroup->bboxmax.v[i]; - } - - *pframeindex = (byte *)paliasgroup - (byte *)pheader; - - pin_intervals = (daliasinterval_t *)(pingroup + 1); - - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); - - paliasgroup->intervals = (byte *)poutintervals - (byte *)pheader; - - for (i=0 ; iinterval); - if (*poutintervals <= 0.0) - Sys_Error ("Mod_LoadAliasGroup: interval<=0"); - - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - - for (i=0 ; iframes[i].frame, - numv, - &paliasgroup->frames[i].bboxmin, - &paliasgroup->frames[i].bboxmax, - pheader, name); - } - - return ptemp; -} - - -/* -================= -Mod_LoadAliasSkin -================= -*/ -void * Mod_LoadAliasSkin (void * pin, int *pskinindex, int skinsize, - aliashdr_t *pheader) +extern aliashdr_t *pheader; + +extern stvert_t stverts[MAXALIASVERTS]; +extern mtriangle_t triangles[MAXALIASTRIS]; + +// a pose is a single set of vertexes. a frame may be +// an animating sequence of poses +extern trivertx_t *poseverts[MAXALIASFRAMES]; +extern int posenum; + +extern byte player_8bit_texels[320*200]; + +void *Mod_LoadSkin (byte *skin, int skinsize, int *pskinindex, int snum, int gnum) { + byte *pskin; + ushort *pusskin; int i; - byte *pskin, *pinskin; - unsigned short *pusskin; pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); - pinskin = (byte *)pin; *pskinindex = (byte *)pskin - (byte *)pheader; - if (r_pixbytes == 1) - { - memcpy (pskin, pinskin, skinsize); - } - else if (r_pixbytes == 2) - { - pusskin = (unsigned short *)pskin; - - for (i=0 ; inumskins); - - paliasskingroup = Hunk_AllocName (sizeof (maliasskingroup_t) + - (numskins - 1) * sizeof (paliasskingroup->skindescs[0]), - loadname); - - paliasskingroup->numskins = numskins; - - *pskinindex = (byte *)paliasskingroup - (byte *)pheader; - - pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); - - poutskinintervals = Hunk_AllocName (numskins * sizeof (float),loadname); - - paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader; - - for (i=0 ; iinterval); - if (*poutskinintervals <= 0) - Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); - - poutskinintervals++; - pinskinintervals++; - } - - ptemp = (void *)pinskinintervals; - - for (i=0 ; iskindescs[i].skin, skinsize, pheader); - } - - return ptemp; -} - - -/* -================= -Mod_LoadAliasModel -================= -*/ -void Mod_LoadAliasModel (model_t *mod, void *buffer) -{ - int i; - mdl_t *pmodel, *pinmodel; - stvert_t *pstverts, *pinstverts; - aliashdr_t *pheader; - mtriangle_t *ptri; - dtriangle_t *pintriangles; - int version, numframes, numskins; - int size; - daliasframetype_t *pframetype; - daliasskintype_t *pskintype; - maliasskindesc_t *pskindesc; - int skinsize; - int start, end, total; - - start = Hunk_LowMark (); - - pinmodel = (mdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - Sys_Error ("%s has wrong version number (%i should be %i)", - mod->name, version, ALIAS_VERSION); - -// -// allocate space for a working header, plus all the data except the frames, -// skin and group info -// - size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) * - sizeof (pheader->frames[0]) + - sizeof (mdl_t) + - LittleLong (pinmodel->numverts) * sizeof (stvert_t) + - LittleLong (pinmodel->numtris) * sizeof (mtriangle_t); - - pheader = Hunk_AllocName (size, loadname); - pmodel = (mdl_t *) ((byte *)&pheader[1] + - (LittleLong (pinmodel->numframes) - 1) * - sizeof (pheader->frames[0])); - -// mod->cache.data = pheader; - mod->flags = LittleLong (pinmodel->flags); - -// -// endian-adjust and copy the data, starting with the alias model header -// - pmodel->boundingradius = LittleFloat (pinmodel->boundingradius); - pmodel->numskins = LittleLong (pinmodel->numskins); - pmodel->skinwidth = LittleLong (pinmodel->skinwidth); - pmodel->skinheight = LittleLong (pinmodel->skinheight); - - if (pmodel->skinheight > MAX_LBM_HEIGHT) - Sys_Error ("model %s has a skin taller than %d", mod->name, - MAX_LBM_HEIGHT); - - pmodel->numverts = LittleLong (pinmodel->numverts); - - if (pmodel->numverts <= 0) - Sys_Error ("model %s has no vertices", mod->name); - - if (pmodel->numverts > MAXALIASVERTS) - Sys_Error ("model %s has too many vertices", mod->name); - - pmodel->numtris = LittleLong (pinmodel->numtris); - - if (pmodel->numtris <= 0) - Sys_Error ("model %s has no triangles", mod->name); - - pmodel->numframes = LittleLong (pinmodel->numframes); - pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO; - mod->synctype = LittleLong (pinmodel->synctype); - mod->numframes = pmodel->numframes; - - for (i=0 ; i<3 ; i++) - { - pmodel->scale[i] = LittleFloat (pinmodel->scale[i]); - pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]); - pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]); - } - - numskins = pmodel->numskins; - numframes = pmodel->numframes; - - if (pmodel->skinwidth & 0x03) - Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4"); - - pheader->model = (byte *)pmodel - (byte *)pheader; - -// -// load the skins -// - skinsize = pmodel->skinheight * pmodel->skinwidth; - - if (numskins < 1) + if (numskins < 1 || numskins > MAX_SKINS) Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); - pskintype = (daliasskintype_t *)&pinmodel[1]; - + skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), loadname); - pheader->skindesc = (byte *)pskindesc - (byte *)pheader; for (i=0 ; itype == ALIAS_SKIN_SINGLE) { + skin+=4; + skin = Mod_LoadSkin (skin, skinsize, &pskindesc[i].skin, i, 0); + } else { + pskintype++; + pinskingroup = (daliasskingroup_t *)pskintype; + groupskins = LittleLong (pinskingroup->numskins); - skintype = LittleLong (pskintype->type); - pskindesc[i].type = skintype; + j = sizeof (maliasskingroup_t) + + (groupskins - 1) * sizeof (paliasskingroup->skindescs[0]); + j = (int)&((maliasskingroup_t*)0)->skindescs[groupskins]; + paliasskingroup = Hunk_AllocName (j, loadname); + paliasskingroup->numskins = groupskins; - if (skintype == ALIAS_SKIN_SINGLE) - { - pskintype = (daliasskintype_t *) - Mod_LoadAliasSkin (pskintype + 1, - &pskindesc[i].skin, - skinsize, pheader); - } - else - { - pskintype = (daliasskintype_t *) - Mod_LoadAliasSkinGroup (pskintype + 1, - &pskindesc[i].skin, - skinsize, pheader); + *pskinindex = (byte *)paliasskingroup - (byte *)pheader; + + pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); + poutskinintervals = Hunk_AllocName (groupskins * sizeof (float),loadname); + paliasskingroup->intervals = (byte *)poutskinintervals - (byte *)pheader; + for (i=0 ; iinterval); + if (*poutskinintervals <= 0) + Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0"); + + poutskinintervals++; + pinskinintervals++; + } + + pskintype = (void *)pinskinintervals; + skin = (byte *)pskintype; + + for (j=0 ; jskindescs[i].skin, i, j); + } } } -// -// set base s and t vertices -// - pstverts = (stvert_t *)&pmodel[1]; - pinstverts = (stvert_t *)pskintype; - - pheader->stverts = (byte *)pstverts - (byte *)pheader; - - for (i=0 ; inumverts ; i++) - { - pstverts[i].onseam = LittleLong (pinstverts[i].onseam); - // put s and t in 16.16 format - pstverts[i].s = LittleLong (pinstverts[i].s) << 16; - pstverts[i].t = LittleLong (pinstverts[i].t) << 16; - } - -// -// set up the triangles -// - ptri = (mtriangle_t *)&pstverts[pmodel->numverts]; - pintriangles = (dtriangle_t *)&pinstverts[pmodel->numverts]; - - pheader->triangles = (byte *)ptri - (byte *)pheader; - - for (i=0 ; inumtris ; i++) - { - int j; - - ptri[i].facesfront = LittleLong (pintriangles[i].facesfront); - - for (j=0 ; j<3 ; j++) - { - ptri[i].vertindex[j] = - LittleLong (pintriangles[i].vertindex[j]); - } - } - -// -// load the frames -// - if (numframes < 1) - Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); - - pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; - - for (i=0 ; itype); - pheader->frames[i].type = frametype; - - if (frametype == ALIAS_SINGLE) - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasFrame (pframetype + 1, - &pheader->frames[i].frame, - pmodel->numverts, - &pheader->frames[i].bboxmin, - &pheader->frames[i].bboxmax, - pheader, pheader->frames[i].name); - } - else - { - pframetype = (daliasframetype_t *) - Mod_LoadAliasGroup (pframetype + 1, - &pheader->frames[i].frame, - pmodel->numverts, - &pheader->frames[i].bboxmin, - &pheader->frames[i].bboxmax, - pheader, pheader->frames[i].name); - } - } - - mod->type = mod_alias; - -// FIXME: do this right - mod->mins[0] = mod->mins[1] = mod->mins[2] = -16; - mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16; - -// -// move the complete, relocatable alias model to the cache -// - end = Hunk_LowMark (); - total = end - start; - - Cache_Alloc (&mod->cache, total, loadname); - if (!mod->cache.data) - return; - memcpy (mod->cache.data, pheader, total); - - Hunk_FreeToLowMark (start); + return (void *)skin; +} + +void GL_MakeAliasModelDisplayLists (model_t *m, aliashdr_t *hdr) +{ }