From d6e0069c69ee43368cb6bc355a22d38acc0f2b7d Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Thu, 11 May 2000 23:06:57 +0000 Subject: [PATCH] almost done. only net_chan.c left to fix before client links, but still need to sort out two SERVERONLYs in model.c. All functions are split out, but two code snippets remain to be sorted. --- source/Makefile | 2 + source/cl_math.S | 102 +++++++ source/cl_model.c | 760 ++++++++++++++++++++++++++++++++++++++++++++++ source/model.c | 724 ------------------------------------------- 4 files changed, 864 insertions(+), 724 deletions(-) create mode 100644 source/cl_math.S create mode 100644 source/cl_model.c diff --git a/source/Makefile b/source/Makefile index 45fdcf9..c861139 100644 --- a/source/Makefile +++ b/source/Makefile @@ -76,7 +76,9 @@ CL_sources=\ cl_ents.c \ cl_input.c \ cl_main.c \ + cl_math.S \ cl_misc.c \ + cl_model.c \ cl_parse.c \ cl_pred.c \ cl_tent.c \ diff --git a/source/cl_math.S b/source/cl_math.S new file mode 100644 index 0000000..bb194bb --- /dev/null +++ b/source/cl_math.S @@ -0,0 +1,102 @@ +/* +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 the Free Software +Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. + +*/ +// +// math.s +// x86 assembly-language math routines. + +#include "asm_i386.h" +#include "quakeasm.h" + + +#if id386 + + .data + + .text + +// TODO: rounding needed? +// stack parameter offset +#define val 4 + +.globl C(Invert24To16) +C(Invert24To16): + + movl val(%esp),%ecx + movl $0x100,%edx // 0x10000000000 as dividend + cmpl %edx,%ecx + jle LOutOfRange + + subl %eax,%eax + divl %ecx + + ret + +LOutOfRange: + movl $0xFFFFFFFF,%eax + ret + +#define in 4 +#define out 8 + + .align 2 +.globl C(TransformVector) +C(TransformVector): + movl in(%esp),%eax + movl out(%esp),%edx + + flds (%eax) // in[0] + fmuls C(vright) // in[0]*vright[0] + flds (%eax) // in[0] | in[0]*vright[0] + fmuls C(vup) // in[0]*vup[0] | in[0]*vright[0] + flds (%eax) // in[0] | in[0]*vup[0] | in[0]*vright[0] + fmuls C(vpn) // in[0]*vpn[0] | in[0]*vup[0] | in[0]*vright[0] + + flds 4(%eax) // in[1] | ... + fmuls C(vright)+4 // in[1]*vright[1] | ... + flds 4(%eax) // in[1] | in[1]*vright[1] | ... + fmuls C(vup)+4 // in[1]*vup[1] | in[1]*vright[1] | ... + flds 4(%eax) // in[1] | in[1]*vup[1] | in[1]*vright[1] | ... + fmuls C(vpn)+4 // in[1]*vpn[1] | in[1]*vup[1] | in[1]*vright[1] | ... + fxch %st(2) // in[1]*vright[1] | in[1]*vup[1] | in[1]*vpn[1] | ... + + faddp %st(0),%st(5) // in[1]*vup[1] | in[1]*vpn[1] | ... + faddp %st(0),%st(3) // in[1]*vpn[1] | ... + faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + + flds 8(%eax) // in[2] | ... + fmuls C(vright)+8 // in[2]*vright[2] | ... + flds 8(%eax) // in[2] | in[2]*vright[2] | ... + fmuls C(vup)+8 // in[2]*vup[2] | in[2]*vright[2] | ... + flds 8(%eax) // in[2] | in[2]*vup[2] | in[2]*vright[2] | ... + fmuls C(vpn)+8 // in[2]*vpn[2] | in[2]*vup[2] | in[2]*vright[2] | ... + fxch %st(2) // in[2]*vright[2] | in[2]*vup[2] | in[2]*vpn[2] | ... + + faddp %st(0),%st(5) // in[2]*vup[2] | in[2]*vpn[2] | ... + faddp %st(0),%st(3) // in[2]*vpn[2] | ... + faddp %st(0),%st(1) // vpn_accum | vup_accum | vright_accum + + fstps 8(%edx) // out[2] + fstps 4(%edx) // out[1] + fstps (%edx) // out[0] + + ret + + +#endif // id386 diff --git a/source/cl_model.c b/source/cl_model.c new file mode 100644 index 0000000..ab31d50 --- /dev/null +++ b/source/cl_model.c @@ -0,0 +1,760 @@ +/* + model.c + + (description) + + 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.c -- model loading and caching + +// models are the only shared resource between a client and server running +// on the same machine. + +#include "quakedef.h" +#include "r_local.h" + +void SV_Error (char *error, ...); + +extern char loadname[]; // for hunk tags +extern model_t *loadmodel; +extern model_t mod_known[]; +extern int mod_numknown; + +void Mod_LoadSpriteModel (model_t *mod, void *buffer); +void Mod_LoadBrushModel (model_t *mod, void *buffer); +void Mod_LoadAliasModel (model_t *mod, void *buffer); +model_t *Mod_LoadModel (model_t *mod, qboolean crash); +model_t *Mod_FindName (char *name); + +/* +=============== +Mod_Init + +Caches the data if needed +=============== +*/ +void *Mod_Extradata (model_t *mod) +{ + void *r; + + r = Cache_Check (&mod->cache); + if (r) + return r; + + Mod_LoadModel (mod, true); + + if (!mod->cache.data) + SV_Error ("Mod_Extradata: caching failed"); + return mod->cache.data; +} + +/* +================== +Mod_TouchModel + +================== +*/ +void Mod_TouchModel (char *name) +{ + model_t *mod; + + mod = Mod_FindName (name); + + if (!mod->needload) + { + if (mod->type == mod_alias) + Cache_Check (&mod->cache); + } +} + +/* +============================================================================== + +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) + SV_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) +{ + 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) + { + Q_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) + SV_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; + + if (!strcmp(loadmodel->name, "progs/player.mdl") || + !strcmp(loadmodel->name, "progs/eyes.mdl")) { + unsigned short crc; + byte *p; + int len; + char st[40]; + + CRC_Init(&crc); + for (len = com_filesize, p = buffer; len; len--, p++) + CRC_ProcessByte(&crc, *p); + + sprintf(st, "%d", (int) crc); + Info_SetValueForKey (cls.userinfo, + !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, + st, MAX_INFO_STRING); + + if (cls.state >= ca_connected) { + MSG_WriteByte (&cls.netchan.message, clc_stringcmd); + sprintf(st, "setinfo %s %d", + !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, + (int)crc); + SZ_Print (&cls.netchan.message, st); + } + } + + start = Hunk_LowMark (); + + pinmodel = (mdl_t *)buffer; + + version = LittleLong (pinmodel->version); + if (version != ALIAS_VERSION) + SV_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) + SV_Error ("model %s has a skin taller than %d", mod->name, + MAX_LBM_HEIGHT); + + pmodel->numverts = LittleLong (pinmodel->numverts); + + if (pmodel->numverts <= 0) + SV_Error ("model %s has no vertices", mod->name); + + if (pmodel->numverts > MAXALIASVERTS) + SV_Error ("model %s has too many vertices", mod->name); + + pmodel->numtris = LittleLong (pinmodel->numtris); + + if (pmodel->numtris <= 0) + SV_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) + SV_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) + SV_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); + + pskintype = (daliasskintype_t *)&pinmodel[1]; + + pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), + loadname); + + pheader->skindesc = (byte *)pskindesc - (byte *)pheader; + + for (i=0 ; itype); + pskindesc[i].type = skintype; + + 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); + } + } + +// +// 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) + SV_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); +} + +//============================================================================= + +/* +================= +Mod_LoadSpriteFrame +================= +*/ +void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe) +{ + dspriteframe_t *pinframe; + mspriteframe_t *pspriteframe; + int i, width, height, size, origin[2]; + unsigned short *ppixout; + byte *ppixin; + + pinframe = (dspriteframe_t *)pin; + + width = LittleLong (pinframe->width); + height = LittleLong (pinframe->height); + size = width * height; + + pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes, + loadname); + + Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); + *ppframe = pspriteframe; + + pspriteframe->width = width; + pspriteframe->height = height; + origin[0] = LittleLong (pinframe->origin[0]); + origin[1] = LittleLong (pinframe->origin[1]); + + pspriteframe->up = origin[1]; + pspriteframe->down = origin[1] - height; + pspriteframe->left = origin[0]; + pspriteframe->right = width + origin[0]; + + if (r_pixbytes == 1) + { + Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size); + } + else if (r_pixbytes == 2) + { + ppixin = (byte *)(pinframe + 1); + ppixout = (unsigned short *)&pspriteframe->pixels[0]; + + for (i=0 ; inumframes); + + pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + + (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); + + pspritegroup->numframes = numframes; + + *ppframe = (mspriteframe_t *)pspritegroup; + + pin_intervals = (dspriteinterval_t *)(pingroup + 1); + + poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); + + pspritegroup->intervals = poutintervals; + + for (i=0 ; iinterval); + if (*poutintervals <= 0.0) + SV_Error ("Mod_LoadSpriteGroup: interval<=0"); + + poutintervals++; + pin_intervals++; + } + + ptemp = (void *)pin_intervals; + + for (i=0 ; iframes[i]); + } + + return ptemp; +} + + +/* +================= +Mod_LoadSpriteModel +================= +*/ +void Mod_LoadSpriteModel (model_t *mod, void *buffer) +{ + int i; + int version; + dsprite_t *pin; + msprite_t *psprite; + int numframes; + int size; + dspriteframetype_t *pframetype; + + pin = (dsprite_t *)buffer; + + version = LittleLong (pin->version); + if (version != SPRITE_VERSION) + SV_Error ("%s has wrong version number " + "(%i should be %i)", mod->name, version, SPRITE_VERSION); + + numframes = LittleLong (pin->numframes); + + size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); + + psprite = Hunk_AllocName (size, loadname); + + mod->cache.data = psprite; + + psprite->type = LittleLong (pin->type); + psprite->maxwidth = LittleLong (pin->width); + psprite->maxheight = LittleLong (pin->height); + psprite->beamlength = LittleFloat (pin->beamlength); + mod->synctype = LittleLong (pin->synctype); + psprite->numframes = numframes; + + mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; + mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; + mod->mins[2] = -psprite->maxheight/2; + mod->maxs[2] = psprite->maxheight/2; + +// +// load the frames +// + if (numframes < 1) + SV_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); + + mod->numframes = numframes; + + pframetype = (dspriteframetype_t *)(pin + 1); + + for (i=0 ; itype); + psprite->frames[i].type = frametype; + + if (frametype == SPR_SINGLE) + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteFrame (pframetype + 1, + &psprite->frames[i].frameptr); + } + else + { + pframetype = (dspriteframetype_t *) + Mod_LoadSpriteGroup (pframetype + 1, + &psprite->frames[i].frameptr); + } + } + + mod->type = mod_sprite; +} + +//============================================================================= + +/* +================ +Mod_Print +================ +*/ +void Mod_Print (void) +{ + int i; + model_t *mod; + + Con_Printf ("Cached models:\n"); + for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) + { + Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); + } +} diff --git a/source/model.c b/source/model.c index 51fa430..6e762e0 100644 --- a/source/model.c +++ b/source/model.c @@ -30,12 +30,7 @@ // models are the only shared resource between a client and server running // on the same machine. -#ifdef SERVERONLY #include "qwsvdef.h" -#else -#include "quakedef.h" -#include "r_local.h" -#endif model_t *loadmodel; char loadname[32]; // for hunk tags @@ -64,30 +59,6 @@ void Mod_Init (void) memset (mod_novis, 0xff, sizeof(mod_novis)); } -#ifndef SERVERONLY -/* -=============== -Mod_Init - -Caches the data if needed -=============== -*/ -void *Mod_Extradata (model_t *mod) -{ - void *r; - - r = Cache_Check (&mod->cache); - if (r) - return r; - - Mod_LoadModel (mod, true); - - if (!mod->cache.data) - SV_Error ("Mod_Extradata: caching failed"); - return mod->cache.data; -} -#endif - /* =============== Mod_PointInLeaf @@ -223,27 +194,6 @@ model_t *Mod_FindName (char *name) return mod; } -#ifndef SERVERONLY -/* -================== -Mod_TouchModel - -================== -*/ -void Mod_TouchModel (char *name) -{ - model_t *mod; - - mod = Mod_FindName (name); - - if (!mod->needload) - { - if (mod->type == mod_alias) - Cache_Check (&mod->cache); - } -} -#endif - /* ================== Mod_LoadModel @@ -1228,677 +1178,3 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer) } } } -#ifndef SERVERONLY - -/* -============================================================================== - -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) - SV_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) -{ - 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) - { - Q_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) - SV_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; - - if (!strcmp(loadmodel->name, "progs/player.mdl") || - !strcmp(loadmodel->name, "progs/eyes.mdl")) { - unsigned short crc; - byte *p; - int len; - char st[40]; - - CRC_Init(&crc); - for (len = com_filesize, p = buffer; len; len--, p++) - CRC_ProcessByte(&crc, *p); - - sprintf(st, "%d", (int) crc); - Info_SetValueForKey (cls.userinfo, - !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, - st, MAX_INFO_STRING); - - if (cls.state >= ca_connected) { - MSG_WriteByte (&cls.netchan.message, clc_stringcmd); - sprintf(st, "setinfo %s %d", - !strcmp(loadmodel->name, "progs/player.mdl") ? pmodel_name : emodel_name, - (int)crc); - SZ_Print (&cls.netchan.message, st); - } - } - - start = Hunk_LowMark (); - - pinmodel = (mdl_t *)buffer; - - version = LittleLong (pinmodel->version); - if (version != ALIAS_VERSION) - SV_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) - SV_Error ("model %s has a skin taller than %d", mod->name, - MAX_LBM_HEIGHT); - - pmodel->numverts = LittleLong (pinmodel->numverts); - - if (pmodel->numverts <= 0) - SV_Error ("model %s has no vertices", mod->name); - - if (pmodel->numverts > MAXALIASVERTS) - SV_Error ("model %s has too many vertices", mod->name); - - pmodel->numtris = LittleLong (pinmodel->numtris); - - if (pmodel->numtris <= 0) - SV_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) - SV_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) - SV_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); - - pskintype = (daliasskintype_t *)&pinmodel[1]; - - pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), - loadname); - - pheader->skindesc = (byte *)pskindesc - (byte *)pheader; - - for (i=0 ; itype); - pskindesc[i].type = skintype; - - 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); - } - } - -// -// 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) - SV_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); -} - -//============================================================================= - -/* -================= -Mod_LoadSpriteFrame -================= -*/ -void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe) -{ - dspriteframe_t *pinframe; - mspriteframe_t *pspriteframe; - int i, width, height, size, origin[2]; - unsigned short *ppixout; - byte *ppixin; - - pinframe = (dspriteframe_t *)pin; - - width = LittleLong (pinframe->width); - height = LittleLong (pinframe->height); - size = width * height; - - pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t) + size*r_pixbytes, - loadname); - - Q_memset (pspriteframe, 0, sizeof (mspriteframe_t) + size); - *ppframe = pspriteframe; - - pspriteframe->width = width; - pspriteframe->height = height; - origin[0] = LittleLong (pinframe->origin[0]); - origin[1] = LittleLong (pinframe->origin[1]); - - pspriteframe->up = origin[1]; - pspriteframe->down = origin[1] - height; - pspriteframe->left = origin[0]; - pspriteframe->right = width + origin[0]; - - if (r_pixbytes == 1) - { - Q_memcpy (&pspriteframe->pixels[0], (byte *)(pinframe + 1), size); - } - else if (r_pixbytes == 2) - { - ppixin = (byte *)(pinframe + 1); - ppixout = (unsigned short *)&pspriteframe->pixels[0]; - - for (i=0 ; inumframes); - - pspritegroup = Hunk_AllocName (sizeof (mspritegroup_t) + - (numframes - 1) * sizeof (pspritegroup->frames[0]), loadname); - - pspritegroup->numframes = numframes; - - *ppframe = (mspriteframe_t *)pspritegroup; - - pin_intervals = (dspriteinterval_t *)(pingroup + 1); - - poutintervals = Hunk_AllocName (numframes * sizeof (float), loadname); - - pspritegroup->intervals = poutintervals; - - for (i=0 ; iinterval); - if (*poutintervals <= 0.0) - SV_Error ("Mod_LoadSpriteGroup: interval<=0"); - - poutintervals++; - pin_intervals++; - } - - ptemp = (void *)pin_intervals; - - for (i=0 ; iframes[i]); - } - - return ptemp; -} - - -/* -================= -Mod_LoadSpriteModel -================= -*/ -void Mod_LoadSpriteModel (model_t *mod, void *buffer) -{ - int i; - int version; - dsprite_t *pin; - msprite_t *psprite; - int numframes; - int size; - dspriteframetype_t *pframetype; - - pin = (dsprite_t *)buffer; - - version = LittleLong (pin->version); - if (version != SPRITE_VERSION) - SV_Error ("%s has wrong version number " - "(%i should be %i)", mod->name, version, SPRITE_VERSION); - - numframes = LittleLong (pin->numframes); - - size = sizeof (msprite_t) + (numframes - 1) * sizeof (psprite->frames); - - psprite = Hunk_AllocName (size, loadname); - - mod->cache.data = psprite; - - psprite->type = LittleLong (pin->type); - psprite->maxwidth = LittleLong (pin->width); - psprite->maxheight = LittleLong (pin->height); - psprite->beamlength = LittleFloat (pin->beamlength); - mod->synctype = LittleLong (pin->synctype); - psprite->numframes = numframes; - - mod->mins[0] = mod->mins[1] = -psprite->maxwidth/2; - mod->maxs[0] = mod->maxs[1] = psprite->maxwidth/2; - mod->mins[2] = -psprite->maxheight/2; - mod->maxs[2] = psprite->maxheight/2; - -// -// load the frames -// - if (numframes < 1) - SV_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes); - - mod->numframes = numframes; - - pframetype = (dspriteframetype_t *)(pin + 1); - - for (i=0 ; itype); - psprite->frames[i].type = frametype; - - if (frametype == SPR_SINGLE) - { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteFrame (pframetype + 1, - &psprite->frames[i].frameptr); - } - else - { - pframetype = (dspriteframetype_t *) - Mod_LoadSpriteGroup (pframetype + 1, - &psprite->frames[i].frameptr); - } - } - - mod->type = mod_sprite; -} - -//============================================================================= - -/* -================ -Mod_Print -================ -*/ -void Mod_Print (void) -{ - int i; - model_t *mod; - - Con_Printf ("Cached models:\n"); - for (i=0, mod=mod_known ; i < mod_numknown ; i++, mod++) - { - Con_Printf ("%8p : %s\n",mod->cache.data, mod->name); - } -} -#endif