#include "quakedef.h" static void *Mod_LoadAliasFrame( void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name, int aliasbboxmin[3], int aliasbboxmax[3]){ 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]; aliasbboxmin[i] = min(aliasbboxmin[i], pbboxmin->v[i]); aliasbboxmax[i] = max(aliasbboxmax[i], pbboxmax->v[i]); } pinframe = (trivertx_t *)(pdaliasframe + 1); *pframeindex = Hunk_From(pheader); pframe = Hunk_Alloc(numv * sizeof(*pframe)); 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;} static void *Mod_LoadAliasGroup( void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax, aliashdr_t *pheader, char *name, int aliasbboxmin[3], int aliasbboxmax[3]){ 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); *pframeindex = Hunk_From(pheader); paliasgroup = Hunk_Alloc(sizeof(*paliasgroup) + (numframes - 1) * sizeof(paliasgroup->frames[0])); 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]; aliasbboxmin[i] = min(aliasbboxmin[i], pbboxmin->v[i]); aliasbboxmax[i] = max(aliasbboxmax[i], pbboxmax->v[i]); } pin_intervals = (daliasinterval_t *)(pingroup + 1); paliasgroup->intervals = Hunk_From(pheader); poutintervals = Hunk_Alloc(numframes * sizeof(*poutintervals)); for(i = 0; i < numframes; i++) { *poutintervals = LittleFloat(pin_intervals->interval); if(*poutintervals <= 0.0) Host_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, aliasbboxmin, aliasbboxmax ); } return ptemp;} static void *Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize, aliashdr_t *pheader){ byte *pinskin; pixel_t *pskin; *pskinindex = Hunk_From(pheader); pskin = Hunk_Alloc(skinsize * 4); pinskin = (byte *)pin; torgbx(pinskin, pskin, skinsize); pinskin += skinsize; return (void *)pinskin;} static 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); *pskinindex = Hunk_From(pheader); paliasskingroup = Hunk_Alloc( sizeof(*paliasskingroup) + (numskins - 1) * sizeof(paliasskingroup->skindescs[0]) ); paliasskingroup->numskins = numskins; pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1); paliasskingroup->intervals = Hunk_From(pheader); poutskinintervals = Hunk_Alloc(numskins * sizeof(*poutskinintervals)); for(i = 0; i < numskins; i++) { *poutskinintervals = LittleFloat(pinskinintervals->interval); if(*poutskinintervals <= 0) Host_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;} voidMod_LoadAliasModel(model_t *mod, void *buffer){ int i, version, numframes, numskins, size, skinsize, bboxmin[3], bboxmax[3]; mdl_t *pmodel, *pinmodel; stvert_t *pstverts, *pinstverts; aliashdr_t *pheader; mtriangle_t *ptri; dtriangle_t *pintriangles; daliasframetype_t *pframetype; daliasskintype_t *pskintype; maliasskindesc_t *pskindesc; pinmodel = (mdl_t *)buffer; version = LittleLong(pinmodel->version); if(version != ALIAS_VERSION) Host_Error( "%s has wrong version number (%d should be %d)", 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_Alloc(size); pmodel = (mdl_t *)((byte *)&pheader[1] + (LittleLong(pinmodel->numframes) - 1) * sizeof(pheader->frames[0])); pheader->model = (byte *)pmodel - (byte *)pheader; // 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) Host_Error("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT); pmodel->numverts = LittleLong(pinmodel->numverts); if(pmodel->numverts <= 0) Host_Error("model %s has no vertices", mod->name); if(pmodel->numverts > MAXALIASVERTS) Host_Error("model %s has too many vertices", mod->name); pmodel->numtris = LittleLong(pinmodel->numtris); if(pmodel->numtris <= 0) Host_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) Host_Error("Mod_LoadAliasModel: skinwidth not multiple of 4"); // load the skins skinsize = pmodel->skinheight * pmodel->skinwidth; if(numskins < 1) Host_Error("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); pskintype = (daliasskintype_t *)&pinmodel[1]; pheader->skindesc = Hunk_From(pheader); pskindesc = Hunk_Alloc(numskins * sizeof(*pskindesc)); 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) Host_Error("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes); pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris]; bboxmin[0] = bboxmin[1] = bboxmin[2] = 999999; bboxmax[0] = bboxmax[1] = bboxmax[2] = -999999; 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, bboxmin, bboxmax ); } 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, bboxmin, bboxmax ); } } mod->type = mod_alias; for(i = 0; i < 3; i++) { mod->mins[i] = bboxmin[i] * pmodel->scale[i] + pmodel->scale_origin[i]; mod->maxs[i] = bboxmax[i] * pmodel->scale[i] + pmodel->scale_origin[i]; } // move the complete, relocatable alias model to the cache Hunk_CacheFrom(&mod->cache, pheader);}
#include "quakedef.h"
static void *
Mod_LoadAliasFrame(
void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax,
aliashdr_t *pheader, char *name, int aliasbboxmin[3], int aliasbboxmax[3]
)
{
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];
aliasbboxmin[i] = min(aliasbboxmin[i], pbboxmin->v[i]);
aliasbboxmax[i] = max(aliasbboxmax[i], pbboxmax->v[i]);
}
pinframe = (trivertx_t *)(pdaliasframe + 1);
*pframeindex = Hunk_From(pheader);
pframe = Hunk_Alloc(numv * sizeof(*pframe));
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;
}
static void *
Mod_LoadAliasGroup(
void *pin, int *pframeindex, int numv, trivertx_t *pbboxmin, trivertx_t *pbboxmax,
aliashdr_t *pheader, char *name, int aliasbboxmin[3], int aliasbboxmax[3]
)
{
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);
*pframeindex = Hunk_From(pheader);
paliasgroup =
Hunk_Alloc(sizeof(*paliasgroup) + (numframes - 1) * sizeof(paliasgroup->frames[0]));
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];
aliasbboxmin[i] = min(aliasbboxmin[i], pbboxmin->v[i]);
aliasbboxmax[i] = max(aliasbboxmax[i], pbboxmax->v[i]);
}
pin_intervals = (daliasinterval_t *)(pingroup + 1);
paliasgroup->intervals = Hunk_From(pheader);
poutintervals = Hunk_Alloc(numframes * sizeof(*poutintervals));
for(i = 0; i < numframes; i++) {
*poutintervals = LittleFloat(pin_intervals->interval);
if(*poutintervals <= 0.0)
Host_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,
aliasbboxmin,
aliasbboxmax
);
}
return ptemp;
}
static void *
Mod_LoadAliasSkin(void *pin, int *pskinindex, int skinsize, aliashdr_t *pheader)
{
byte *pinskin;
pixel_t *pskin;
*pskinindex = Hunk_From(pheader);
pskin = Hunk_Alloc(skinsize * 4);
pinskin = (byte *)pin;
torgbx(pinskin, pskin, skinsize);
pinskin += skinsize;
return (void *)pinskin;
}
static 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);
*pskinindex = Hunk_From(pheader);
paliasskingroup = Hunk_Alloc(
sizeof(*paliasskingroup) + (numskins - 1) * sizeof(paliasskingroup->skindescs[0])
);
paliasskingroup->numskins = numskins;
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
paliasskingroup->intervals = Hunk_From(pheader);
poutskinintervals = Hunk_Alloc(numskins * sizeof(*poutskinintervals));
for(i = 0; i < numskins; i++) {
*poutskinintervals = LittleFloat(pinskinintervals->interval);
if(*poutskinintervals <= 0)
Host_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;
}
void
Mod_LoadAliasModel(model_t *mod, void *buffer)
{
int i, version, numframes, numskins, size, skinsize, bboxmin[3], bboxmax[3];
mdl_t *pmodel, *pinmodel;
stvert_t *pstverts, *pinstverts;
aliashdr_t *pheader;
mtriangle_t *ptri;
dtriangle_t *pintriangles;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
maliasskindesc_t *pskindesc;
pinmodel = (mdl_t *)buffer;
version = LittleLong(pinmodel->version);
if(version != ALIAS_VERSION)
Host_Error(
"%s has wrong version number (%d should be %d)", 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_Alloc(size);
pmodel = (mdl_t *)((byte *)&pheader[1] +
(LittleLong(pinmodel->numframes) - 1) * sizeof(pheader->frames[0]));
pheader->model = (byte *)pmodel - (byte *)pheader;
// 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)
Host_Error("model %s has a skin taller than %d", mod->name, MAX_LBM_HEIGHT);
pmodel->numverts = LittleLong(pinmodel->numverts);
if(pmodel->numverts <= 0)
Host_Error("model %s has no vertices", mod->name);
if(pmodel->numverts > MAXALIASVERTS)
Host_Error("model %s has too many vertices", mod->name);
pmodel->numtris = LittleLong(pinmodel->numtris);
if(pmodel->numtris <= 0)
Host_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)
Host_Error("Mod_LoadAliasModel: skinwidth not multiple of 4");
// load the skins
skinsize = pmodel->skinheight * pmodel->skinwidth;
if(numskins < 1)
Host_Error("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
pskintype = (daliasskintype_t *)&pinmodel[1];
pheader->skindesc = Hunk_From(pheader);
pskindesc = Hunk_Alloc(numskins * sizeof(*pskindesc));
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)
Host_Error("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
pframetype = (daliasframetype_t *)&pintriangles[pmodel->numtris];
bboxmin[0] = bboxmin[1] = bboxmin[2] = 999999;
bboxmax[0] = bboxmax[1] = bboxmax[2] = -999999;
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,
bboxmin,
bboxmax
);
} 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,
bboxmin,
bboxmax
);
}
}
mod->type = mod_alias;
for(i = 0; i < 3; i++) {
mod->mins[i] = bboxmin[i] * pmodel->scale[i] + pmodel->scale_origin[i];
mod->maxs[i] = bboxmax[i] * pmodel->scale[i] + pmodel->scale_origin[i];
}
// move the complete, relocatable alias model to the cache
Hunk_CacheFrom(&mod->cache, pheader);
}