mirror of
https://git.code.sf.net/p/quake/newtree
synced 2024-11-22 04:01:17 +00:00
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.
This commit is contained in:
parent
ace849a9be
commit
d6e0069c69
4 changed files with 864 additions and 724 deletions
|
@ -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 \
|
||||
|
|
102
source/cl_math.S
Normal file
102
source/cl_math.S
Normal file
|
@ -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
|
760
source/cl_model.c
Normal file
760
source/cl_model.c
Normal file
|
@ -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 ; j<numv ; j++)
|
||||
{
|
||||
int k;
|
||||
|
||||
// these are all byte values, so no need to deal with endianness
|
||||
pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
|
||||
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
pframe[j].v[k] = pinframe[j].v[k];
|
||||
}
|
||||
}
|
||||
|
||||
pinframe += numv;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
|
||||
trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
|
||||
{
|
||||
daliasgroup_t *pingroup;
|
||||
maliasgroup_t *paliasgroup;
|
||||
int i, numframes;
|
||||
daliasinterval_t *pin_intervals;
|
||||
float *poutintervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (daliasgroup_t *)pin;
|
||||
|
||||
numframes = LittleLong (pingroup->numframes);
|
||||
|
||||
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 ; i<numframes ; i++)
|
||||
{
|
||||
*poutintervals = LittleFloat (pin_intervals->interval);
|
||||
if (*poutintervals <= 0.0)
|
||||
SV_Error ("Mod_LoadAliasGroup: interval<=0");
|
||||
|
||||
poutintervals++;
|
||||
pin_intervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadAliasFrame (ptemp,
|
||||
&paliasgroup->frames[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 ; i<skinsize ; i++)
|
||||
pusskin[i] = d_8to16table[pinskin[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
|
||||
r_pixbytes);
|
||||
}
|
||||
|
||||
pinskin += skinsize;
|
||||
|
||||
return ((void *)pinskin);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasSkinGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
|
||||
aliashdr_t *pheader)
|
||||
{
|
||||
daliasskingroup_t *pinskingroup;
|
||||
maliasskingroup_t *paliasskingroup;
|
||||
int i, numskins;
|
||||
daliasskininterval_t *pinskinintervals;
|
||||
float *poutskinintervals;
|
||||
void *ptemp;
|
||||
|
||||
pinskingroup = (daliasskingroup_t *)pin;
|
||||
|
||||
numskins = LittleLong (pinskingroup->numskins);
|
||||
|
||||
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 ; i<numskins ; i++)
|
||||
{
|
||||
*poutskinintervals = LittleFloat (pinskinintervals->interval);
|
||||
if (*poutskinintervals <= 0)
|
||||
SV_Error ("Mod_LoadAliasSkinGroup: interval<=0");
|
||||
|
||||
poutskinintervals++;
|
||||
pinskinintervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pinskinintervals;
|
||||
|
||||
for (i=0 ; i<numskins ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadAliasSkin (ptemp,
|
||||
&paliasskingroup->skindescs[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 ; i<numskins ; i++)
|
||||
{
|
||||
aliasskintype_t skintype;
|
||||
|
||||
skintype = LittleLong (pskintype->type);
|
||||
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 ; i<pmodel->numverts ; 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 ; i<pmodel->numtris ; 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 ; i<numframes ; i++)
|
||||
{
|
||||
aliasframetype_t frametype;
|
||||
|
||||
frametype = LittleLong (pframetype->type);
|
||||
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 ; i<size ; i++)
|
||||
ppixout[i] = d_8to16table[ppixin[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
|
||||
r_pixbytes);
|
||||
}
|
||||
|
||||
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadSpriteGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
|
||||
{
|
||||
dspritegroup_t *pingroup;
|
||||
mspritegroup_t *pspritegroup;
|
||||
int i, numframes;
|
||||
dspriteinterval_t *pin_intervals;
|
||||
float *poutintervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (dspritegroup_t *)pin;
|
||||
|
||||
numframes = LittleLong (pingroup->numframes);
|
||||
|
||||
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 ; i<numframes ; i++)
|
||||
{
|
||||
*poutintervals = LittleFloat (pin_intervals->interval);
|
||||
if (*poutintervals <= 0.0)
|
||||
SV_Error ("Mod_LoadSpriteGroup: interval<=0");
|
||||
|
||||
poutintervals++;
|
||||
pin_intervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[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 ; i<numframes ; i++)
|
||||
{
|
||||
spriteframetype_t frametype;
|
||||
|
||||
frametype = LittleLong (pframetype->type);
|
||||
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);
|
||||
}
|
||||
}
|
724
source/model.c
724
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 ; j<numv ; j++)
|
||||
{
|
||||
int k;
|
||||
|
||||
// these are all byte values, so no need to deal with endianness
|
||||
pframe[j].lightnormalindex = pinframe[j].lightnormalindex;
|
||||
|
||||
for (k=0 ; k<3 ; k++)
|
||||
{
|
||||
pframe[j].v[k] = pinframe[j].v[k];
|
||||
}
|
||||
}
|
||||
|
||||
pinframe += numv;
|
||||
|
||||
return (void *)pinframe;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadAliasGroup (void * pin, int *pframeindex, int numv,
|
||||
trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name)
|
||||
{
|
||||
daliasgroup_t *pingroup;
|
||||
maliasgroup_t *paliasgroup;
|
||||
int i, numframes;
|
||||
daliasinterval_t *pin_intervals;
|
||||
float *poutintervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (daliasgroup_t *)pin;
|
||||
|
||||
numframes = LittleLong (pingroup->numframes);
|
||||
|
||||
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 ; i<numframes ; i++)
|
||||
{
|
||||
*poutintervals = LittleFloat (pin_intervals->interval);
|
||||
if (*poutintervals <= 0.0)
|
||||
SV_Error ("Mod_LoadAliasGroup: interval<=0");
|
||||
|
||||
poutintervals++;
|
||||
pin_intervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadAliasFrame (ptemp,
|
||||
&paliasgroup->frames[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 ; i<skinsize ; i++)
|
||||
pusskin[i] = d_8to16table[pinskin[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: %d\n",
|
||||
r_pixbytes);
|
||||
}
|
||||
|
||||
pinskin += skinsize;
|
||||
|
||||
return ((void *)pinskin);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadAliasSkinGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadAliasSkinGroup (void * pin, int *pskinindex, int skinsize,
|
||||
aliashdr_t *pheader)
|
||||
{
|
||||
daliasskingroup_t *pinskingroup;
|
||||
maliasskingroup_t *paliasskingroup;
|
||||
int i, numskins;
|
||||
daliasskininterval_t *pinskinintervals;
|
||||
float *poutskinintervals;
|
||||
void *ptemp;
|
||||
|
||||
pinskingroup = (daliasskingroup_t *)pin;
|
||||
|
||||
numskins = LittleLong (pinskingroup->numskins);
|
||||
|
||||
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 ; i<numskins ; i++)
|
||||
{
|
||||
*poutskinintervals = LittleFloat (pinskinintervals->interval);
|
||||
if (*poutskinintervals <= 0)
|
||||
SV_Error ("Mod_LoadAliasSkinGroup: interval<=0");
|
||||
|
||||
poutskinintervals++;
|
||||
pinskinintervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pinskinintervals;
|
||||
|
||||
for (i=0 ; i<numskins ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadAliasSkin (ptemp,
|
||||
&paliasskingroup->skindescs[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 ; i<numskins ; i++)
|
||||
{
|
||||
aliasskintype_t skintype;
|
||||
|
||||
skintype = LittleLong (pskintype->type);
|
||||
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 ; i<pmodel->numverts ; 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 ; i<pmodel->numtris ; 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 ; i<numframes ; i++)
|
||||
{
|
||||
aliasframetype_t frametype;
|
||||
|
||||
frametype = LittleLong (pframetype->type);
|
||||
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 ; i<size ; i++)
|
||||
ppixout[i] = d_8to16table[ppixin[i]];
|
||||
}
|
||||
else
|
||||
{
|
||||
SV_Error ("Mod_LoadSpriteFrame: driver set invalid r_pixbytes: %d\n",
|
||||
r_pixbytes);
|
||||
}
|
||||
|
||||
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
=================
|
||||
Mod_LoadSpriteGroup
|
||||
=================
|
||||
*/
|
||||
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe)
|
||||
{
|
||||
dspritegroup_t *pingroup;
|
||||
mspritegroup_t *pspritegroup;
|
||||
int i, numframes;
|
||||
dspriteinterval_t *pin_intervals;
|
||||
float *poutintervals;
|
||||
void *ptemp;
|
||||
|
||||
pingroup = (dspritegroup_t *)pin;
|
||||
|
||||
numframes = LittleLong (pingroup->numframes);
|
||||
|
||||
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 ; i<numframes ; i++)
|
||||
{
|
||||
*poutintervals = LittleFloat (pin_intervals->interval);
|
||||
if (*poutintervals <= 0.0)
|
||||
SV_Error ("Mod_LoadSpriteGroup: interval<=0");
|
||||
|
||||
poutintervals++;
|
||||
pin_intervals++;
|
||||
}
|
||||
|
||||
ptemp = (void *)pin_intervals;
|
||||
|
||||
for (i=0 ; i<numframes ; i++)
|
||||
{
|
||||
ptemp = Mod_LoadSpriteFrame (ptemp, &pspritegroup->frames[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 ; i<numframes ; i++)
|
||||
{
|
||||
spriteframetype_t frametype;
|
||||
|
||||
frametype = LittleLong (pframetype->type);
|
||||
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
|
||||
|
|
Loading…
Reference in a new issue