mirror of
https://git.code.sf.net/p/quake/nuq
synced 2024-11-22 04:01:11 +00:00
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:
parent
16101a8d0b
commit
c7d8fb3773
7 changed files with 2428 additions and 2482 deletions
495
source/gl_model_alias.c
Normal file
495
source/gl_model_alias.c
Normal 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);
|
||||
}
|
|
@ -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
210
source/gl_model_sprite.c
Normal 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;
|
||||
}
|
1616
source/model.c
1616
source/model.c
File diff suppressed because it is too large
Load diff
477
source/sw_model_alias.c
Normal file
477
source/sw_model_alias.c
Normal 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
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
223
source/sw_model_sprite.c
Normal 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;
|
||||
}
|
Loading…
Reference in a new issue