preliminary work on really cleaning up *model.c. atm, just split out the model

type specific code into the appropriate files (which will later be merged as
much as possible) and remove all model type specific code from model.c.
gl_model.c is no more as it ended up being an exact copy of model.c minus a
header include and a prototype, neither of which were needed.
This commit is contained in:
Bill Currie 2000-09-01 04:43:56 +00:00
parent 16101a8d0b
commit c7d8fb3773
7 changed files with 2428 additions and 2482 deletions

495
source/gl_model_alias.c Normal file
View file

@ -0,0 +1,495 @@
/*
gl_model.c
model loading and caching
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
// models are the only shared resource between a client and server running
// on the same machine.
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
/*
==============================================================================
ALIAS MODELS
==============================================================================
*/
aliashdr_t *pheader;
stvert_t stverts[MAXALIASVERTS];
mtriangle_t triangles[MAXALIASTRIS];
// a pose is a single set of vertexes. a frame may be
// an animating sequence of poses
trivertx_t *poseverts[MAXALIASFRAMES];
int posenum;
byte player_8bit_texels[320*200];
/*
=================
Mod_LoadAliasFrame
=================
*/
void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
{
trivertx_t *pinframe;
int i;
daliasframe_t *pdaliasframe;
pdaliasframe = (daliasframe_t *)pin;
strcpy (frame->name, pdaliasframe->name);
frame->firstpose = posenum;
frame->numposes = 1;
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about
// endianness
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
}
pinframe = (trivertx_t *)(pdaliasframe + 1);
poseverts[posenum] = pinframe;
posenum++;
pinframe += pheader->numverts;
return (void *)pinframe;
}
/*
=================
Mod_LoadAliasGroup
=================
*/
void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
{
daliasgroup_t *pingroup;
int i, numframes;
daliasinterval_t *pin_intervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
numframes = LittleLong (pingroup->numframes);
frame->firstpose = posenum;
frame->numposes = numframes;
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about endianness
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
}
pin_intervals = (daliasinterval_t *)(pingroup + 1);
frame->interval = LittleFloat (pin_intervals->interval);
pin_intervals += numframes;
ptemp = (void *)pin_intervals;
for (i=0 ; i<numframes ; i++)
{
poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
posenum++;
ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
}
return ptemp;
}
//=========================================================
/*
=================
Mod_FloodFillSkin
Fill background pixels so mipmapping doesn't have haloes - Ed
=================
*/
typedef struct
{
short x, y;
} floodfill_t;
extern unsigned d_8to24table[];
// must be a power of 2
#define FLOODFILL_FIFO_SIZE 0x1000
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
#define FLOODFILL_STEP( off, dx, dy ) \
{ \
if (pos[off] == fillcolor) \
{ \
pos[off] = 255; \
fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
} \
else if (pos[off] != 255) fdc = pos[off]; \
}
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
{
byte fillcolor = *skin; // assume this is the pixel to fill
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
int inpt = 0, outpt = 0;
int filledcolor = -1;
int i;
if (filledcolor == -1)
{
filledcolor = 0;
// attempt to find opaque black
for (i = 0; i < 256; ++i)
if (d_8to24table[i] == (255 << 0)) // alpha 1.0
{
filledcolor = i;
break;
}
}
// can't fill to filled color or to transparent color (used as visited marker)
if ((fillcolor == filledcolor) || (fillcolor == 255))
{
//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
return;
}
fifo[inpt].x = 0, fifo[inpt].y = 0;
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
while (outpt != inpt)
{
int x = fifo[outpt].x, y = fifo[outpt].y;
int fdc = filledcolor;
byte *pos = &skin[x + skinwidth * y];
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
skin[x + skinwidth * y] = fdc;
}
}
/*
===============
Mod_LoadAllSkins
===============
*/
void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
{
int i, j, k;
char name[32];
int s;
byte *skin;
daliasskingroup_t *pinskingroup;
int groupskins;
daliasskininterval_t *pinskinintervals;
skin = (byte *)(pskintype + 1);
if (numskins < 1 || numskins > MAX_SKINS)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
s = pheader->skinwidth * pheader->skinheight;
for (i=0 ; i<numskins ; i++)
{
if (pskintype->type == ALIAS_SKIN_SINGLE) {
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
// save 8 bit texels for the player model to remap
if (!strcmp(loadmodel->name,"progs/player.mdl"))
{
if (s > sizeof(player_8bit_texels))
Sys_Error ("Player skin too large");
memcpy (player_8bit_texels, (byte *)(pskintype + 1), s);
}
// This block is GL fullbright support for objects...
{
int pixels;
byte *ptexel;
// Check for fullbright pixels..
pixels = pheader->skinwidth * pheader->skinheight;
ptexel = (byte *)(pskintype + 1);
for (j=0 ; j<pixels ; j++) {
if (ptexel[j] >= 256-32) {
loadmodel->hasfullbrights = true;
break;
}
}
if (loadmodel->hasfullbrights) {
byte *ptexels;
//ptexels = Hunk_Alloc(s);
ptexels = malloc(pixels);
snprintf(name, sizeof(name), "fb_%s_%i", loadmodel->name,i);
Con_DPrintf("FB Model ID: '%s'\n", name);
for (j=0 ; j<pixels ; j++) {
if (ptexel[j] >= 256-32) {
ptexels[j] = ptexel[j];
} else {
ptexels[j] = 255;
}
}
pheader->gl_fb_texturenum[i][0] =
pheader->gl_fb_texturenum[i][1] =
pheader->gl_fb_texturenum[i][2] =
pheader->gl_fb_texturenum[i][3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, ptexels, true, true, 1);
free(ptexels);
}
}
snprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
pheader->gl_texturenum[i][0] =
pheader->gl_texturenum[i][1] =
pheader->gl_texturenum[i][2] =
pheader->gl_texturenum[i][3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype + 1), true, true, 1);
pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
} else {
// animating skin group. yuck.
Con_Printf("Animating Skin Group, if you get this message please notify warp@debian.org\n");
pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
groupskins = LittleLong (pinskingroup->numskins);
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
pskintype = (void *)(pinskinintervals + groupskins);
for (j=0 ; j<groupskins ; j++)
{
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
snprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i,j);
pheader->gl_texturenum[i][j&3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype), true, false, 1);
pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
}
k = j;
for (/* */; j < 4; j++)
pheader->gl_texturenum[i][j&3] =
pheader->gl_texturenum[i][j - k];
}
}
return (void *)pskintype;
}
//=========================================================================
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
int i, j;
mdl_t *pinmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
int version, numframes;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int start, end, total;
start = Hunk_LowMark ();
pinmodel = (mdl_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != ALIAS_VERSION)
Sys_Error ("%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
//
// allocate space for a working header, plus all the data except the frames,
// skin and group info
//
size = sizeof (aliashdr_t)
+ (LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]);
pheader = Hunk_AllocName (size, loadname);
mod->flags = LittleLong (pinmodel->flags);
//
// endian-adjust and copy the data, starting with the alias model header
//
pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
pheader->numskins = LittleLong (pinmodel->numskins);
pheader->skinwidth = LittleLong (pinmodel->skinwidth);
pheader->skinheight = LittleLong (pinmodel->skinheight);
if (pheader->skinheight > MAX_LBM_HEIGHT)
Sys_Error ("model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
pheader->numverts = LittleLong (pinmodel->numverts);
if (pheader->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
if (pheader->numverts > MAXALIASVERTS)
Sys_Error ("model %s has too many vertices", mod->name);
pheader->numtris = LittleLong (pinmodel->numtris);
if (pheader->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
pheader->numframes = LittleLong (pinmodel->numframes);
numframes = pheader->numframes;
if (numframes < 1)
Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
mod->synctype = LittleLong (pinmodel->synctype);
mod->numframes = pheader->numframes;
for (i=0 ; i<3 ; i++)
{
pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
}
//
// load the skins
//
pskintype = (daliasskintype_t *)&pinmodel[1];
pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
//
// load base s and t vertices
//
pinstverts = (stvert_t *)pskintype;
for (i=0 ; i<pheader->numverts ; i++)
{
stverts[i].onseam = LittleLong (pinstverts[i].onseam);
stverts[i].s = LittleLong (pinstverts[i].s);
stverts[i].t = LittleLong (pinstverts[i].t);
}
//
// load triangle lists
//
pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
for (i=0 ; i<pheader->numtris ; i++)
{
triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
for (j=0 ; j<3 ; j++)
{
triangles[i].vertindex[j] =
LittleLong (pintriangles[i].vertindex[j]);
}
}
//
// load the frames
//
posenum = 0;
pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
for (i=0 ; i<numframes ; i++)
{
aliasframetype_t frametype;
frametype = LittleLong (pframetype->type);
if (frametype == ALIAS_SINGLE)
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
}
else
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
}
}
pheader->numposes = posenum;
mod->type = mod_alias;
// FIXME: do this right
mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
//
// build the draw lists
//
GL_MakeAliasModelDisplayLists (mod, pheader);
//
// move the complete, relocatable alias model to the cache
//
end = Hunk_LowMark ();
total = end - start;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
memcpy (mod->cache.data, pheader, total);
Hunk_FreeToLowMark (start);
}

View file

@ -40,36 +40,6 @@
#include "checksum.h"
#include "glquake.h"
model_t *loadmodel;
char loadname[32]; // for hunk tags
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);
void Mod_LoadMMNearest(miptex_t *mx, texture_t *tx);
byte mod_novis[MAX_MAP_LEAFS/8];
#define MAX_MOD_KNOWN 512
model_t mod_known[MAX_MOD_KNOWN];
int mod_numknown;
unsigned *model_checksum;
texture_t *r_notexture_mip;
cvar_t *gl_subdivide_size;
/*
===============
Mod_Init
===============
*/
void Mod_Init (void)
{
gl_subdivide_size = Cvar_Get("gl_subdivide_size", "128", CVAR_ARCHIVE, "None");
memset (mod_novis, 0xff, sizeof(mod_novis));
}
/*
===============
Mod_PointInLeaf
@ -153,140 +123,6 @@ byte *Mod_LeafPVS (mleaf_t *leaf, model_t *model)
return Mod_DecompressVis (leaf->compressed_vis, model);
}
/*
===================
Mod_ClearAll
===================
*/
void Mod_ClearAll (void)
{
int i;
model_t *mod;
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
if (mod->type != mod_alias)
mod->needload = true;
}
/*
==================
Mod_FindName
==================
*/
model_t *Mod_FindName (char *name)
{
int i;
model_t *mod;
if (!name[0])
Sys_Error ("Mod_ForName: NULL name");
//
// search the currently loaded models
//
for (i=0 , mod=mod_known ; i<mod_numknown ; i++, mod++)
if (!strcmp (mod->name, name) )
break;
if (i == mod_numknown)
{
if (mod_numknown == MAX_MOD_KNOWN)
Sys_Error ("mod_numknown == MAX_MOD_KNOWN");
strcpy (mod->name, name);
mod->needload = true;
mod_numknown++;
}
return mod;
}
/*
==================
Mod_LoadModel
Loads a model into the cache
==================
*/
model_t *Mod_LoadModel (model_t *mod, qboolean crash)
{
void *d;
unsigned *buf;
byte stackbuf[1024]; // avoid dirtying the cache heap
if (!mod->needload)
{
if (mod->type == mod_alias)
{
d = Cache_Check (&mod->cache);
if (d)
return mod;
}
else
return mod; // not cached at all
}
//
// load the file
//
buf = (unsigned *)COM_LoadStackFile (mod->name, stackbuf, sizeof(stackbuf));
if (!buf)
{
if (crash)
Sys_Error ("Mod_NumForName: %s not found", mod->name);
return NULL;
}
//
// allocate a new model
//
COM_FileBase (mod->name, loadname);
loadmodel = mod;
//
// fill it in
//
// call the apropriate loader
mod->needload = false;
mod->hasfullbrights = false;
switch (LittleLong(*(unsigned *)buf))
{
case IDPOLYHEADER:
Mod_LoadAliasModel (mod, buf);
break;
case IDSPRITEHEADER:
Mod_LoadSpriteModel (mod, buf);
break;
default:
Mod_LoadBrushModel (mod, buf);
break;
}
return mod;
}
/*
==================
Mod_ForName
Loads in a model for the given name
==================
*/
model_t *Mod_ForName (char *name, qboolean crash)
{
model_t *mod;
mod = Mod_FindName (name);
return Mod_LoadModel (mod, crash);
}
/*
===============================================================================
@ -1229,57 +1065,6 @@ void Mod_LoadBrushModel (model_t *mod, void *buffer)
}
}
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_LoadAliasModel (model_t *mod, void *buffer);
model_t *Mod_LoadModel (model_t *mod, qboolean crash);
model_t *Mod_FindName (char *name);
/*
===============
Mod_Extradata
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)
Sys_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);
}
}
void
Mod_LoadMMNearest(miptex_t *mt, texture_t *tx)
{
@ -1287,656 +1072,3 @@ Mod_LoadMMNearest(miptex_t *mt, texture_t *tx)
tx->gl_texturenum = GL_LoadTexture (mt->name, tx->width, tx->height, (byte *)(tx+1), true, false, 1);
texture_mode = GL_LINEAR;
}
/*
==============================================================================
ALIAS MODELS
==============================================================================
*/
aliashdr_t *pheader;
stvert_t stverts[MAXALIASVERTS];
mtriangle_t triangles[MAXALIASTRIS];
// a pose is a single set of vertexes. a frame may be
// an animating sequence of poses
trivertx_t *poseverts[MAXALIASFRAMES];
int posenum;
byte player_8bit_texels[320*200];
/*
=================
Mod_LoadAliasFrame
=================
*/
void * Mod_LoadAliasFrame (void * pin, maliasframedesc_t *frame)
{
trivertx_t *pinframe;
int i;
daliasframe_t *pdaliasframe;
pdaliasframe = (daliasframe_t *)pin;
strcpy (frame->name, pdaliasframe->name);
frame->firstpose = posenum;
frame->numposes = 1;
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about
// endianness
frame->bboxmin.v[i] = pdaliasframe->bboxmin.v[i];
frame->bboxmin.v[i] = pdaliasframe->bboxmax.v[i];
}
pinframe = (trivertx_t *)(pdaliasframe + 1);
poseverts[posenum] = pinframe;
posenum++;
pinframe += pheader->numverts;
return (void *)pinframe;
}
/*
=================
Mod_LoadAliasGroup
=================
*/
void *Mod_LoadAliasGroup (void * pin, maliasframedesc_t *frame)
{
daliasgroup_t *pingroup;
int i, numframes;
daliasinterval_t *pin_intervals;
void *ptemp;
pingroup = (daliasgroup_t *)pin;
numframes = LittleLong (pingroup->numframes);
frame->firstpose = posenum;
frame->numposes = numframes;
for (i=0 ; i<3 ; i++)
{
// these are byte values, so we don't have to worry about endianness
frame->bboxmin.v[i] = pingroup->bboxmin.v[i];
frame->bboxmin.v[i] = pingroup->bboxmax.v[i];
}
pin_intervals = (daliasinterval_t *)(pingroup + 1);
frame->interval = LittleFloat (pin_intervals->interval);
pin_intervals += numframes;
ptemp = (void *)pin_intervals;
for (i=0 ; i<numframes ; i++)
{
poseverts[posenum] = (trivertx_t *)((daliasframe_t *)ptemp + 1);
posenum++;
ptemp = (trivertx_t *)((daliasframe_t *)ptemp + 1) + pheader->numverts;
}
return ptemp;
}
//=========================================================
/*
=================
Mod_FloodFillSkin
Fill background pixels so mipmapping doesn't have haloes - Ed
=================
*/
typedef struct
{
short x, y;
} floodfill_t;
extern unsigned d_8to24table[];
// must be a power of 2
#define FLOODFILL_FIFO_SIZE 0x1000
#define FLOODFILL_FIFO_MASK (FLOODFILL_FIFO_SIZE - 1)
#define FLOODFILL_STEP( off, dx, dy ) \
{ \
if (pos[off] == fillcolor) \
{ \
pos[off] = 255; \
fifo[inpt].x = x + (dx), fifo[inpt].y = y + (dy); \
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK; \
} \
else if (pos[off] != 255) fdc = pos[off]; \
}
void Mod_FloodFillSkin( byte *skin, int skinwidth, int skinheight )
{
byte fillcolor = *skin; // assume this is the pixel to fill
floodfill_t fifo[FLOODFILL_FIFO_SIZE];
int inpt = 0, outpt = 0;
int filledcolor = -1;
int i;
if (filledcolor == -1)
{
filledcolor = 0;
// attempt to find opaque black
for (i = 0; i < 256; ++i)
if (d_8to24table[i] == (255 << 0)) // alpha 1.0
{
filledcolor = i;
break;
}
}
// can't fill to filled color or to transparent color (used as visited marker)
if ((fillcolor == filledcolor) || (fillcolor == 255))
{
//printf( "not filling skin from %d to %d\n", fillcolor, filledcolor );
return;
}
fifo[inpt].x = 0, fifo[inpt].y = 0;
inpt = (inpt + 1) & FLOODFILL_FIFO_MASK;
while (outpt != inpt)
{
int x = fifo[outpt].x, y = fifo[outpt].y;
int fdc = filledcolor;
byte *pos = &skin[x + skinwidth * y];
outpt = (outpt + 1) & FLOODFILL_FIFO_MASK;
if (x > 0) FLOODFILL_STEP( -1, -1, 0 );
if (x < skinwidth - 1) FLOODFILL_STEP( 1, 1, 0 );
if (y > 0) FLOODFILL_STEP( -skinwidth, 0, -1 );
if (y < skinheight - 1) FLOODFILL_STEP( skinwidth, 0, 1 );
skin[x + skinwidth * y] = fdc;
}
}
/*
===============
Mod_LoadAllSkins
===============
*/
void *Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype)
{
int i, j, k;
char name[32];
int s;
byte *skin;
daliasskingroup_t *pinskingroup;
int groupskins;
daliasskininterval_t *pinskinintervals;
skin = (byte *)(pskintype + 1);
if (numskins < 1 || numskins > MAX_SKINS)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
s = pheader->skinwidth * pheader->skinheight;
for (i=0 ; i<numskins ; i++)
{
if (pskintype->type == ALIAS_SKIN_SINGLE) {
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
// save 8 bit texels for the player model to remap
if (!strcmp(loadmodel->name,"progs/player.mdl"))
{
if (s > sizeof(player_8bit_texels))
Sys_Error ("Player skin too large");
memcpy (player_8bit_texels, (byte *)(pskintype + 1), s);
}
// This block is GL fullbright support for objects...
{
int pixels;
byte *ptexel;
// Check for fullbright pixels..
pixels = pheader->skinwidth * pheader->skinheight;
ptexel = (byte *)(pskintype + 1);
for (j=0 ; j<pixels ; j++) {
if (ptexel[j] >= 256-32) {
loadmodel->hasfullbrights = true;
break;
}
}
if (loadmodel->hasfullbrights) {
byte *ptexels;
//ptexels = Hunk_Alloc(s);
ptexels = malloc(pixels);
snprintf(name, sizeof(name), "fb_%s_%i", loadmodel->name,i);
Con_DPrintf("FB Model ID: '%s'\n", name);
for (j=0 ; j<pixels ; j++) {
if (ptexel[j] >= 256-32) {
ptexels[j] = ptexel[j];
} else {
ptexels[j] = 255;
}
}
pheader->gl_fb_texturenum[i][0] =
pheader->gl_fb_texturenum[i][1] =
pheader->gl_fb_texturenum[i][2] =
pheader->gl_fb_texturenum[i][3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, ptexels, true, true, 1);
free(ptexels);
}
}
snprintf (name, sizeof(name), "%s_%i", loadmodel->name, i);
pheader->gl_texturenum[i][0] =
pheader->gl_texturenum[i][1] =
pheader->gl_texturenum[i][2] =
pheader->gl_texturenum[i][3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype + 1), true, true, 1);
pskintype = (daliasskintype_t *)((byte *)(pskintype+1) + s);
} else {
// animating skin group. yuck.
Con_Printf("Animating Skin Group, if you get this message please notify warp@debian.org\n");
pskintype++;
pinskingroup = (daliasskingroup_t *)pskintype;
groupskins = LittleLong (pinskingroup->numskins);
pinskinintervals = (daliasskininterval_t *)(pinskingroup + 1);
pskintype = (void *)(pinskinintervals + groupskins);
for (j=0 ; j<groupskins ; j++)
{
Mod_FloodFillSkin( skin, pheader->skinwidth, pheader->skinheight );
snprintf (name, sizeof(name), "%s_%i_%i", loadmodel->name, i,j);
pheader->gl_texturenum[i][j&3] =
GL_LoadTexture (name, pheader->skinwidth,
pheader->skinheight, (byte *)(pskintype), true, false, 1);
pskintype = (daliasskintype_t *)((byte *)(pskintype) + s);
}
k = j;
for (/* */; j < 4; j++)
pheader->gl_texturenum[i][j&3] =
pheader->gl_texturenum[i][j - k];
}
}
return (void *)pskintype;
}
//=========================================================================
/*
=================
Mod_LoadAliasModel
=================
*/
void Mod_LoadAliasModel (model_t *mod, void *buffer)
{
int i, j;
mdl_t *pinmodel;
stvert_t *pinstverts;
dtriangle_t *pintriangles;
int version, numframes;
int size;
daliasframetype_t *pframetype;
daliasskintype_t *pskintype;
int start, end, total;
start = Hunk_LowMark ();
pinmodel = (mdl_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != ALIAS_VERSION)
Sys_Error ("%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
//
// allocate space for a working header, plus all the data except the frames,
// skin and group info
//
size = sizeof (aliashdr_t)
+ (LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]);
pheader = Hunk_AllocName (size, loadname);
mod->flags = LittleLong (pinmodel->flags);
//
// endian-adjust and copy the data, starting with the alias model header
//
pheader->boundingradius = LittleFloat (pinmodel->boundingradius);
pheader->numskins = LittleLong (pinmodel->numskins);
pheader->skinwidth = LittleLong (pinmodel->skinwidth);
pheader->skinheight = LittleLong (pinmodel->skinheight);
if (pheader->skinheight > MAX_LBM_HEIGHT)
Sys_Error ("model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
pheader->numverts = LittleLong (pinmodel->numverts);
if (pheader->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
if (pheader->numverts > MAXALIASVERTS)
Sys_Error ("model %s has too many vertices", mod->name);
pheader->numtris = LittleLong (pinmodel->numtris);
if (pheader->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
pheader->numframes = LittleLong (pinmodel->numframes);
numframes = pheader->numframes;
if (numframes < 1)
Sys_Error ("Mod_LoadAliasModel: Invalid # of frames: %d\n", numframes);
pheader->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
mod->synctype = LittleLong (pinmodel->synctype);
mod->numframes = pheader->numframes;
for (i=0 ; i<3 ; i++)
{
pheader->scale[i] = LittleFloat (pinmodel->scale[i]);
pheader->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
pheader->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
}
//
// load the skins
//
pskintype = (daliasskintype_t *)&pinmodel[1];
pskintype = Mod_LoadAllSkins (pheader->numskins, pskintype);
//
// load base s and t vertices
//
pinstverts = (stvert_t *)pskintype;
for (i=0 ; i<pheader->numverts ; i++)
{
stverts[i].onseam = LittleLong (pinstverts[i].onseam);
stverts[i].s = LittleLong (pinstverts[i].s);
stverts[i].t = LittleLong (pinstverts[i].t);
}
//
// load triangle lists
//
pintriangles = (dtriangle_t *)&pinstverts[pheader->numverts];
for (i=0 ; i<pheader->numtris ; i++)
{
triangles[i].facesfront = LittleLong (pintriangles[i].facesfront);
for (j=0 ; j<3 ; j++)
{
triangles[i].vertindex[j] =
LittleLong (pintriangles[i].vertindex[j]);
}
}
//
// load the frames
//
posenum = 0;
pframetype = (daliasframetype_t *)&pintriangles[pheader->numtris];
for (i=0 ; i<numframes ; i++)
{
aliasframetype_t frametype;
frametype = LittleLong (pframetype->type);
if (frametype == ALIAS_SINGLE)
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasFrame (pframetype + 1, &pheader->frames[i]);
}
else
{
pframetype = (daliasframetype_t *)
Mod_LoadAliasGroup (pframetype + 1, &pheader->frames[i]);
}
}
pheader->numposes = posenum;
mod->type = mod_alias;
// FIXME: do this right
mod->mins[0] = mod->mins[1] = mod->mins[2] = -16;
mod->maxs[0] = mod->maxs[1] = mod->maxs[2] = 16;
//
// build the draw lists
//
GL_MakeAliasModelDisplayLists (mod, pheader);
//
// move the complete, relocatable alias model to the cache
//
end = Hunk_LowMark ();
total = end - start;
Cache_Alloc (&mod->cache, total, loadname);
if (!mod->cache.data)
return;
memcpy (mod->cache.data, pheader, total);
Hunk_FreeToLowMark (start);
}
//=============================================================================
/*
=================
Mod_LoadSpriteFrame
=================
*/
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
int width, height, size, origin[2];
char name[64];
pinframe = (dspriteframe_t *)pin;
width = LittleLong (pinframe->width);
height = LittleLong (pinframe->height);
size = width * height;
pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
memset (pspriteframe, 0, sizeof (mspriteframe_t));
*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];
snprintf (name, sizeof(name), "%s_%i", loadmodel->name, framenum);
pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, 1);
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
}
/*
=================
Mod_LoadSpriteGroup
=================
*/
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
{
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)
Sys_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], framenum * 100 + 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)
Sys_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)
Sys_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, i);
}
else
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteGroup (pframetype + 1,
&psprite->frames[i].frameptr, i);
}
}
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);
}
}

210
source/gl_model_sprite.c Normal file
View file

@ -0,0 +1,210 @@
/*
gl_model.c
model loading and caching
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
// models are the only shared resource between a client and server running
// on the same machine.
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "r_local.h"
#include "sys.h"
#include "console.h"
#include "qendian.h"
#include "checksum.h"
#include "glquake.h"
/*
=================
Mod_LoadSpriteFrame
=================
*/
void * Mod_LoadSpriteFrame (void * pin, mspriteframe_t **ppframe, int framenum)
{
dspriteframe_t *pinframe;
mspriteframe_t *pspriteframe;
int width, height, size, origin[2];
char name[64];
pinframe = (dspriteframe_t *)pin;
width = LittleLong (pinframe->width);
height = LittleLong (pinframe->height);
size = width * height;
pspriteframe = Hunk_AllocName (sizeof (mspriteframe_t),loadname);
memset (pspriteframe, 0, sizeof (mspriteframe_t));
*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];
snprintf (name, sizeof(name), "%s_%i", loadmodel->name, framenum);
pspriteframe->gl_texturenum = GL_LoadTexture (name, width, height, (byte *)(pinframe + 1), true, true, 1);
return (void *)((byte *)pinframe + sizeof (dspriteframe_t) + size);
}
/*
=================
Mod_LoadSpriteGroup
=================
*/
void * Mod_LoadSpriteGroup (void * pin, mspriteframe_t **ppframe, int framenum)
{
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)
Sys_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], framenum * 100 + 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)
Sys_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)
Sys_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, i);
}
else
{
pframetype = (dspriteframetype_t *)
Mod_LoadSpriteGroup (pframetype + 1,
&psprite->frames[i].frameptr, i);
}
}
mod->type = mod_sprite;
}

File diff suppressed because it is too large Load diff

477
source/sw_model_alias.c Normal file
View file

@ -0,0 +1,477 @@
/*
model.c
model loading and caching
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "r_local.h"
#include "sys.h"
#include "console.h"
#include "qendian.h"
#include "checksum.h"
/*
==============================================================================
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)
Sys_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)
{
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
{
Sys_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)
Sys_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;
start = Hunk_LowMark ();
pinmodel = (mdl_t *)buffer;
version = LittleLong (pinmodel->version);
if (version != ALIAS_VERSION)
Sys_Error ("%s has wrong version number (%i should be %i)",
mod->name, version, ALIAS_VERSION);
//
// allocate space for a working header, plus all the data except the frames,
// skin and group info
//
size = sizeof (aliashdr_t) + (LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]) +
sizeof (mdl_t) +
LittleLong (pinmodel->numverts) * sizeof (stvert_t) +
LittleLong (pinmodel->numtris) * sizeof (mtriangle_t);
pheader = Hunk_AllocName (size, loadname);
pmodel = (mdl_t *) ((byte *)&pheader[1] +
(LittleLong (pinmodel->numframes) - 1) *
sizeof (pheader->frames[0]));
// mod->cache.data = pheader;
mod->flags = LittleLong (pinmodel->flags);
//
// endian-adjust and copy the data, starting with the alias model header
//
pmodel->boundingradius = LittleFloat (pinmodel->boundingradius);
pmodel->numskins = LittleLong (pinmodel->numskins);
pmodel->skinwidth = LittleLong (pinmodel->skinwidth);
pmodel->skinheight = LittleLong (pinmodel->skinheight);
if (pmodel->skinheight > MAX_LBM_HEIGHT)
Sys_Error ("model %s has a skin taller than %d", mod->name,
MAX_LBM_HEIGHT);
pmodel->numverts = LittleLong (pinmodel->numverts);
if (pmodel->numverts <= 0)
Sys_Error ("model %s has no vertices", mod->name);
if (pmodel->numverts > MAXALIASVERTS)
Sys_Error ("model %s has too many vertices", mod->name);
pmodel->numtris = LittleLong (pinmodel->numtris);
if (pmodel->numtris <= 0)
Sys_Error ("model %s has no triangles", mod->name);
pmodel->numframes = LittleLong (pinmodel->numframes);
pmodel->size = LittleFloat (pinmodel->size) * ALIAS_BASE_SIZE_RATIO;
mod->synctype = LittleLong (pinmodel->synctype);
mod->numframes = pmodel->numframes;
for (i=0 ; i<3 ; i++)
{
pmodel->scale[i] = LittleFloat (pinmodel->scale[i]);
pmodel->scale_origin[i] = LittleFloat (pinmodel->scale_origin[i]);
pmodel->eyeposition[i] = LittleFloat (pinmodel->eyeposition[i]);
}
numskins = pmodel->numskins;
numframes = pmodel->numframes;
if (pmodel->skinwidth & 0x03)
Sys_Error ("Mod_LoadAliasModel: skinwidth not multiple of 4");
pheader->model = (byte *)pmodel - (byte *)pheader;
//
// load the skins
//
skinsize = pmodel->skinheight * pmodel->skinwidth;
if (numskins < 1)
Sys_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)
Sys_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);
}

1019
source/sw_model_brush.c Normal file

File diff suppressed because it is too large Load diff

223
source/sw_model_sprite.c Normal file
View file

@ -0,0 +1,223 @@
/*
model.c
model loading and caching
Copyright (C) 1996-1997 Id Software, Inc.
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
$Id$
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#include "r_local.h"
#include "sys.h"
#include "console.h"
#include "qendian.h"
#include "checksum.h"
/*
=================
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);
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)
{
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
{
Sys_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)
Sys_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)
Sys_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)
Sys_Error ("Mod_LoadSpriteModel: Invalid # of frames: %d\n", numframes);
mod->numframes = numframes;
mod->flags = 0;
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;
}