fix many, many bugs in the alias skin loading, transforming and rendering

code. This fixes blather's `melted models' (sw), the nq alt player model
skins (gl), the arbitrary limits on skins and skin groups in gl, and the
incorrect timing of group skins (animated) in gl.
This commit is contained in:
Bill Currie 2001-11-21 08:14:05 +00:00
parent 3e34fc83e4
commit 7d14013041
6 changed files with 146 additions and 110 deletions

View file

@ -290,6 +290,8 @@ typedef struct
{ {
aliasskintype_t type; aliasskintype_t type;
int skin; int skin;
int texnum;
int fb_texnum;
} maliasskindesc_t; } maliasskindesc_t;
typedef struct typedef struct
@ -336,9 +338,6 @@ typedef struct {
unsigned short crc; unsigned short crc;
int gl_texturenum[MAX_SKINS][4];
int gl_fb_texturenum[MAX_SKINS][4];
int texels[MAX_SKINS]; // only for player skins
maliasframedesc_t frames[1]; maliasframedesc_t frames[1];
} aliashdr_t; } aliashdr_t;

View file

@ -136,43 +136,47 @@ Mod_FloodFillSkin (byte * skin, int skinwidth, int skinheight)
} }
void * void *
Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group) Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group,
maliasskindesc_t *skindesc)
{ {
char name[32]; char name[32];
int fbtexnum = 0; int fb_texnum = 0;
int texnum = 0;
byte *pskin;
Mod_FloodFillSkin (skin, pheader->mdl.skinwidth, pheader->mdl.skinheight); pskin = Hunk_AllocName (skinsize, loadname);
skindesc->skin = (byte *) pskin - (byte *) pheader;
memcpy (pskin, skin, skinsize);
Mod_FloodFillSkin (pskin, pheader->mdl.skinwidth, pheader->mdl.skinheight);
// save 8 bit texels for the player model to remap // save 8 bit texels for the player model to remap
if (!strcmp (loadmodel->name, "progs/player.mdl")) { if (strequal (loadmodel->name, "progs/player.mdl")) {
byte *texels;
if (skinsize > sizeof (player_8bit_texels)) if (skinsize > sizeof (player_8bit_texels))
Sys_Error ("Player skin too large"); Sys_Error ("Player skin too large");
texels = Hunk_AllocName (skinsize, loadname); memcpy (player_8bit_texels, pskin, skinsize);
pheader->texels[snum] = texels - (byte *) pheader;
memcpy (texels, skin, skinsize);
memcpy (player_8bit_texels, skin, skinsize);
} }
if (group) { if (!loadmodel->fullbright) {
snprintf (name, sizeof (name), "fb_%s_%i_%i", loadmodel->name, snum, if (group) {
gnum); snprintf (name, sizeof (name), "fb_%s_%i_%i", loadmodel->name,
} else { snum, gnum);
snprintf (name, sizeof (name), "fb_%s_%i", loadmodel->name, snum); } else {
} snprintf (name, sizeof (name), "fb_%s_%i", loadmodel->name, snum);
if (!loadmodel->fullbright) }
fbtexnum = Mod_Fullbright (skin + 1, pheader->mdl.skinwidth, fb_texnum = Mod_Fullbright (pskin, pheader->mdl.skinwidth,
pheader->mdl.skinheight, name); pheader->mdl.skinheight, name);
if ((loadmodel->hasfullbrights = (fbtexnum))) {
pheader->gl_fb_texturenum[snum][gnum] = fbtexnum;
} }
if (group) { if (group) {
snprintf (name, sizeof (name), "%s_%i_%i", loadmodel->name, snum, gnum); snprintf (name, sizeof (name), "%s_%i_%i", loadmodel->name, snum, gnum);
} else { } else {
snprintf (name, sizeof (name), "%s_%i", loadmodel->name, snum); snprintf (name, sizeof (name), "%s_%i", loadmodel->name, snum);
} }
pheader->gl_texturenum[snum][gnum] = texnum = GL_LoadTexture (name, pheader->mdl.skinwidth,
GL_LoadTexture (name, pheader->mdl.skinwidth, pheader->mdl.skinheight, pskin, true, false, 1);
pheader->mdl.skinheight, skin, true, false, 1); skindesc->texnum = texnum;
skindesc->fb_texnum = fb_texnum;
loadmodel->hasfullbrights = fb_texnum;
// alpha param was true for non group skins // alpha param was true for non group skins
return skin + skinsize; return skin + skinsize;
} }
@ -180,48 +184,63 @@ Mod_LoadSkin (byte * skin, int skinsize, int snum, int gnum, qboolean group)
void * void *
Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex) Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
{ {
int i, j, k; int snum, gnum, t;
int skinsize; int skinsize;
byte *skin; byte *skin;
daliasskingroup_t *pinskingroup;
int groupskins; int groupskins;
daliasskingroup_t *pinskingroup;
daliasskininterval_t *pinskinintervals; daliasskininterval_t *pinskinintervals;
maliasskindesc_t *pskindesc;
maliasskingroup_t *paliasskingroup;
float *poutskinintervals;
if (numskins < 1 || numskins > MAX_SKINS) if (numskins < 1 || numskins > MAX_SKINS)
Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins); Sys_Error ("Mod_LoadAliasModel: Invalid # of skins: %d\n", numskins);
skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight; skinsize = pheader->mdl.skinwidth * pheader->mdl.skinheight;
pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
loadname);
for (i = 0; i < numskins; i++) { *pskinindex = (byte *) pskindesc - (byte *) pheader;
for (snum = 0; snum < numskins; snum++) {
pskindesc[snum].type = pskintype->type;
if (pskintype->type == ALIAS_SKIN_SINGLE) { if (pskintype->type == ALIAS_SKIN_SINGLE) {
skin = (byte *) (pskintype + 1); skin = (byte *) (pskintype + 1);
skin = Mod_LoadSkin (skin, skinsize, i, 0, false); skin = Mod_LoadSkin (skin, skinsize, snum, 0, false,
&pskindesc[snum]);
for (j = 1; j < 4; j++) {
pheader->gl_texturenum[i][j] = pheader->gl_texturenum[i][j - 1];
pheader->gl_fb_texturenum[i][j] =
pheader->gl_fb_texturenum[i][j - 1];
}
} else { } else {
// animating skin group. yuck.
// Sys_Printf("Animating Skin Group, if you get this message
// please notify warp@debian.org\n");
pskintype++; pskintype++;
pinskingroup = (daliasskingroup_t *) pskintype; pinskingroup = (daliasskingroup_t *) pskintype;
groupskins = LittleLong (pinskingroup->numskins); groupskins = LittleLong (pinskingroup->numskins);
pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1);
pskintype = (void *) (pinskinintervals + groupskins); t = field_offset (maliasskingroup_t, skindescs[groupskins]);
paliasskingroup = Hunk_AllocName (t, loadname);
paliasskingroup->numskins = groupskins;
pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) pheader;
pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1);
poutskinintervals = Hunk_AllocName (groupskins * sizeof (float),
loadname);
paliasskingroup->intervals =
(byte *) poutskinintervals - (byte *) pheader;
for (gnum = 0; gnum < groupskins; gnum++) {
*poutskinintervals = LittleFloat (pinskinintervals->interval);
if (*poutskinintervals <= 0)
Sys_Error ("Mod_LoadAliasSkinGroup: interval<=0");
poutskinintervals++;
pinskinintervals++;
}
pskintype = (void *) pinskinintervals;
skin = (byte *) pskintype; skin = (byte *) pskintype;
for (j = 0; j < groupskins; j++) { for (gnum = 0; gnum < groupskins; gnum++) {
skin = Mod_LoadSkin (skin, skinsize, i, j & 3, true); paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
} skin = Mod_LoadSkin (skin, skinsize, snum, gnum, true,
k = j; &paliasskingroup->skindescs[gnum]);
for ( /* */ ; j < 4; j++) {
pheader->gl_texturenum[i][j] = pheader->gl_texturenum[i][j - k];
pheader->gl_fb_texturenum[i][j] =
pheader->gl_fb_texturenum[i][j - k];
} }
} }
pskintype = (daliasskintype_t *) skin; pskintype = (daliasskintype_t *) skin;

View file

@ -44,6 +44,7 @@ static const char rcsid[] =
#include "QF/qendian.h" #include "QF/qendian.h"
#include "QF/sys.h" #include "QF/sys.h"
#include "compat.h"
#include "d_iface.h" #include "d_iface.h"
@ -58,34 +59,16 @@ static const char rcsid[] =
void * void *
Mod_LoadSkin (byte * skin, int skinsize, int *pskinindex, int snum, int gnum) Mod_LoadSkin (byte * skin, int skinsize, maliasskindesc_t *skindesc)
{ {
byte *pskin; byte *pskin;
// unsigned short *pusskin;
// int i;
// LordHavoc: model rendering expects skin in 8bit always // LordHavoc: model rendering expects skin in 8bit always
pskin = Hunk_AllocName (skinsize, loadname); pskin = Hunk_AllocName (skinsize, loadname);
memcpy (pskin, skin, skinsize); skindesc->skin = (byte *) pskin - (byte *) pheader;
/*
pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); memcpy (pskin, skin, skinsize);
switch (r_pixbytes) {
case 1:
memcpy (pskin, skin, skinsize);
break;
case 2:
pusskin = (unsigned short *) skin;
for (i = 0; i < skinsize; i++)
pusskin[i] = d_8to16table[skin[i]];
break;
default:
Sys_Error ("Mod_LoadAliasSkin: driver set invalid r_pixbytes: "
"%d\n", r_pixbytes);
break;
}
*/
*pskinindex = (byte *) pskin - (byte *) pheader;
return skin + skinsize; return skin + skinsize;
} }
@ -109,28 +92,27 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
loadname); loadname);
pheader->skindesc = (byte *) pskindesc - (byte *) pheader; *pskinindex = (byte *) pskindesc - (byte *) pheader;
for (snum = 0; snum < numskins; snum++) { for (snum = 0; snum < numskins; snum++) {
pskindesc[snum].type = pskintype->type;
if (pskintype->type == ALIAS_SKIN_SINGLE) { if (pskintype->type == ALIAS_SKIN_SINGLE) {
skin = (byte *) (pskintype + 1); skin = (byte *) (pskintype + 1);
skin = skin = Mod_LoadSkin (skin, skinsize, &pskindesc[snum]);
Mod_LoadSkin (skin, skinsize, &pskindesc[snum].skin, snum, 0);
} else { } else {
pskintype++; pskintype++;
pinskingroup = (daliasskingroup_t *) pskintype; pinskingroup = (daliasskingroup_t *) pskintype;
groupskins = LittleLong (pinskingroup->numskins); groupskins = LittleLong (pinskingroup->numskins);
t = (int) &((maliasskingroup_t *) 0)->skindescs[groupskins]; t = field_offset (maliasskingroup_t, skindescs[groupskins]);
paliasskingroup = Hunk_AllocName (t, loadname); paliasskingroup = Hunk_AllocName (t, loadname);
paliasskingroup->numskins = groupskins; paliasskingroup->numskins = groupskins;
*pskinindex = (byte *) paliasskingroup - (byte *) pheader; pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) pheader;
pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1);
poutskinintervals = poutskinintervals = Hunk_AllocName (groupskins * sizeof (float),
loadname);
Hunk_AllocName (groupskins * sizeof (float), loadname);
paliasskingroup->intervals = paliasskingroup->intervals =
(byte *) poutskinintervals - (byte *) pheader; (byte *) poutskinintervals - (byte *) pheader;
for (gnum = 0; gnum < groupskins; gnum++) { for (gnum = 0; gnum < groupskins; gnum++) {
@ -146,10 +128,9 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
skin = (byte *) pskintype; skin = (byte *) pskintype;
for (gnum = 0; gnum < groupskins; gnum++) { for (gnum = 0; gnum < groupskins; gnum++) {
skin = paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
Mod_LoadSkin (skin, skinsize, skin = Mod_LoadSkin (skin, skinsize,
&paliasskingroup->skindescs[snum].skin, snum, &paliasskingroup->skindescs[gnum]);
gnum);
} }
} }
pskintype = (daliasskintype_t *) skin; pskintype = (daliasskintype_t *) skin;

View file

@ -60,14 +60,14 @@ static const char rcsid[] =
void * void *
Mod_LoadSkin (byte * skin, int skinsize, int *pskinindex, int snum, int gnum) Mod_LoadSkin (byte * skin, int skinsize, maliasskindesc_t *skindesc)
{ {
byte *pskin; byte *pskin;
unsigned short *pusskin; unsigned short *pusskin;
int i; int i;
pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname); pskin = Hunk_AllocName (skinsize * r_pixbytes, loadname);
*pskinindex = (byte *) pskin - (byte *) pheader; skindesc->skin = (byte *) pskin - (byte *) pheader;
switch (r_pixbytes) { switch (r_pixbytes) {
case 1: case 1:
@ -106,13 +106,13 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t), pskindesc = Hunk_AllocName (numskins * sizeof (maliasskindesc_t),
loadname); loadname);
pheader->skindesc = (byte *) pskindesc - (byte *) pheader; *pskinindex = (byte *) pskindesc - (byte *) pheader;
for (snum = 0; snum < numskins; snum++) { for (snum = 0; snum < numskins; snum++) {
pskindesc[snum].type = pskintype->type;
if (pskintype->type == ALIAS_SKIN_SINGLE) { if (pskintype->type == ALIAS_SKIN_SINGLE) {
skin = (byte *) (pskintype + 1); skin = (byte *) (pskintype + 1);
skin = skin = Mod_LoadSkin (skin, skinsize, &pskindesc[snum]);
Mod_LoadSkin (skin, skinsize, &pskindesc[snum].skin, snum, 0);
} else { } else {
pskintype++; pskintype++;
pinskingroup = (daliasskingroup_t *) pskintype; pinskingroup = (daliasskingroup_t *) pskintype;
@ -122,7 +122,7 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
paliasskingroup = Hunk_AllocName (t, loadname); paliasskingroup = Hunk_AllocName (t, loadname);
paliasskingroup->numskins = groupskins; paliasskingroup->numskins = groupskins;
*pskinindex = (byte *) paliasskingroup - (byte *) pheader; pskindesc[snum].skin = (byte *) paliasskingroup - (byte *) pheader;
pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1); pinskinintervals = (daliasskininterval_t *) (pinskingroup + 1);
poutskinintervals = Hunk_AllocName (groupskins * sizeof (float), poutskinintervals = Hunk_AllocName (groupskins * sizeof (float),
@ -142,10 +142,9 @@ Mod_LoadAllSkins (int numskins, daliasskintype_t *pskintype, int *pskinindex)
skin = (byte *) pskintype; skin = (byte *) pskintype;
for (gnum = 0; gnum < groupskins; gnum++) { for (gnum = 0; gnum < groupskins; gnum++) {
skin = paliasskingroup->skindescs[gnum].type = ALIAS_SKIN_SINGLE;
Mod_LoadSkin (skin, skinsize, skin = Mod_LoadSkin (skin, skinsize,
&paliasskingroup->skindescs[snum].skin, snum, &paliasskingroup->skindescs[gnum]);
gnum);
} }
} }
pskintype = (daliasskintype_t *) skin; pskintype = (daliasskintype_t *) skin;

View file

@ -379,11 +379,52 @@ GL_GetAliasFrameVerts (int frame, aliashdr_t *paliashdr, entity_t *e)
return vo; return vo;
} }
maliasskindesc_t *
R_AliasGetSkindesc (int skinnum, aliashdr_t *ahdr)
{
maliasskindesc_t *pskindesc;
maliasskingroup_t *paliasskingroup;
if ((skinnum >= ahdr->mdl.numskins) || (skinnum < 0)) {
Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
skinnum = 0;
}
pskindesc = ((maliasskindesc_t *)
((byte *) ahdr + ahdr->skindesc)) + skinnum;
if (pskindesc->type == ALIAS_SKIN_GROUP) {
float fullskininterval;
int i;
float skintargettime, skintime;
float *pskinintervals;
paliasskingroup = (maliasskingroup_t *) ((byte *) ahdr +
pskindesc->skin);
pskinintervals = (float *)
((byte *) ahdr + paliasskingroup->intervals);
numskins = paliasskingroup->numskins;
fullskininterval = pskinintervals[numskins - 1];
skintime = r_realtime + currententity->syncbase;
skintargettime = skintime -
((int) (skintime / fullskininterval)) * fullskininterval;
for (i = 0; i < (numskins - 1); i++) {
if (pskinintervals[i] > skintargettime)
break;
}
pskindesc = &paliasskingroup->skindescs[i];
}
return pskindesc;
}
void void
R_DrawAliasModel (entity_t *e, qboolean cull) R_DrawAliasModel (entity_t *e, qboolean cull)
{ {
float add, an; float add, an;
int anim, lnum, skinnum, texture; int lnum, texture;
int fb_texture = 0; int fb_texture = 0;
aliashdr_t *paliashdr; aliashdr_t *paliashdr;
model_t *clmodel; model_t *clmodel;
@ -461,18 +502,6 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
qfglScalef (paliashdr->mdl.scale[0], paliashdr->mdl.scale[1], qfglScalef (paliashdr->mdl.scale[0], paliashdr->mdl.scale[1],
paliashdr->mdl.scale[2]); paliashdr->mdl.scale[2]);
anim = (int) (r_realtime * 10) & 3;
skinnum = e->skinnum;
if ((skinnum >= paliashdr->mdl.numskins) || (skinnum < 0)) {
Con_DPrintf ("R_AliasSetupSkin: no such skin # %d\n", skinnum);
skinnum = 0;
}
texture = paliashdr->gl_texturenum[skinnum][anim];
if (gl_fb_models->int_val && !clmodel->fullbright)
fb_texture = paliashdr->gl_fb_texturenum[skinnum][anim];
// we can't dynamically colormap textures, so they are cached // we can't dynamically colormap textures, so they are cached
// seperately for the players. Heads are just uncolored. // seperately for the players. Heads are just uncolored.
if (e->skin && !gl_nocolors->int_val) { if (e->skin && !gl_nocolors->int_val) {
@ -482,6 +511,13 @@ R_DrawAliasModel (entity_t *e, qboolean cull)
if (gl_fb_models->int_val) { if (gl_fb_models->int_val) {
fb_texture = skin->fb_texture; fb_texture = skin->fb_texture;
} }
} else {
maliasskindesc_t *skindesc;
skindesc = R_AliasGetSkindesc (e->skinnum, paliashdr);
texture = skindesc->texnum;
if (gl_fb_models->int_val && !clmodel->fullbright)
fb_texture = skindesc->fb_texnum;
} }
qfglBindTexture (GL_TEXTURE_2D, texture); qfglBindTexture (GL_TEXTURE_2D, texture);

View file

@ -198,6 +198,7 @@ Skin_Do_Translation_Model (model_t *model, int skinnum, int slot, skin_t *skin)
int inwidth, inheight; int inwidth, inheight;
int texnum = skin->texture; int texnum = skin->texture;
aliashdr_t *paliashdr; aliashdr_t *paliashdr;
maliasskindesc_t *pskindesc;
if (!model) // player doesn't have a model yet if (!model) // player doesn't have a model yet
return; return;
@ -209,11 +210,12 @@ Skin_Do_Translation_Model (model_t *model, int skinnum, int slot, skin_t *skin)
|| skinnum >= paliashdr->mdl.numskins) { || skinnum >= paliashdr->mdl.numskins) {
Con_Printf ("(%d): Invalid player skin #%d\n", slot, Con_Printf ("(%d): Invalid player skin #%d\n", slot,
skinnum); skinnum);
original = (byte *) paliashdr + paliashdr->texels[0]; skinnum = 0;
} else {
original =
(byte *) paliashdr + paliashdr->texels[skinnum];
} }
pskindesc = ((maliasskindesc_t *)
((byte *) paliashdr + paliashdr->skindesc)) + skinnum;
//FIXME: broken for skin groups
original = (byte *) paliashdr + pskindesc->skin;
inwidth = paliashdr->mdl.skinwidth; inwidth = paliashdr->mdl.skinwidth;
inheight = paliashdr->mdl.skinheight; inheight = paliashdr->mdl.skinheight;