[skin] Get team colors working for model skins

This should actually get team colors working for all models, not just
player.mdl.
This commit is contained in:
Bill Currie 2024-01-15 14:12:59 +09:00
parent baa11cd710
commit d39630580e
6 changed files with 110 additions and 126 deletions

View file

@ -51,6 +51,7 @@ typedef struct tex_s {
int loaded:1; // 0 if size info only, otherwise data loaded
int flipped:1; // 1 if first pixel is bottom instead of top
int bgr:1; // 1 if image is bgr (for tex_rgb)
int relative:1; // 1 if data is an offset instead of a pointer
};
int flagbits; // for eazy zeroing
};

View file

@ -141,6 +141,7 @@ uint32_t glsl_Skin_Colormap (const colormap_t *colormap);
void gl_Skin_SetupSkin (skin_t *skin, int cmap);
void gl_Skin_Destroy (skin_t *skin);
glskin_t gl_Skin_Get (const skin_t *skin, const colormap_t *colormap);
glskin_t gl_Skin_Get (const tex_t *tex, const colormap_t *colormap,
const byte *texel_base);
#endif// __mod_internal_h

View file

@ -49,6 +49,7 @@
#include "QF/GL/qf_textures.h"
#include "mod_internal.h"
#include "r_internal.h"
#include "compat.h"
@ -60,60 +61,31 @@ gl_alias_clear (model_t *m, void *data)
Cache_Free (&m->cache);
}
static void
gl_Mod_LoadSkin (mod_alias_ctx_t *alias_ctx, byte *texels,
int snum, int gnum, maliasskindesc_t *skindesc)
{
aliashdr_t *header = alias_ctx->header;
char modname[MAX_QPATH + 4];
int fb_texnum = 0, texnum = 0;
dstring_t *name = dstring_new ();
Mod_FloodFillSkin (texels, header->mdl.skinwidth, header->mdl.skinheight);
QFS_StripExtension (alias_ctx->mod->path, modname);
if (!alias_ctx->mod->fullbright) {
if (gnum != -1) {
dsprintf (name, "fb_%s_%i_%i", modname, snum, gnum);
} else {
dsprintf (name, "fb_%s_%i", modname, snum);
}
fb_texnum = Mod_Fullbright (texels, header->mdl.skinwidth,
header->mdl.skinheight, name->str);
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, fb_texnum);
}
if (gnum != -1) {
dsprintf (name, "%s_%i_%i", modname, snum, gnum);
} else {
dsprintf (name, "%s_%i", modname, snum);
}
texnum = GL_LoadTexture (name->str, header->mdl.skinwidth,
header->mdl.skinheight, texels, true, false, 1);
Sys_MaskPrintf (SYS_glt, "%s %d\n", name->str, texnum);
skindesc->texnum = texnum;
skindesc->fb_texnum = fb_texnum;
dstring_delete (name);
// alpha param was true for non group skins
}
void
gl_Mod_LoadAllSkins (mod_alias_ctx_t *alias_ctx)
{
aliashdr_t *header = alias_ctx->header;
int skinsize = header->mdl.skinwidth * header->mdl.skinheight;
int num_skins = alias_ctx->skins.size;
tex_t *tex_block = Hunk_AllocName (0, sizeof (tex_t[num_skins]),
alias_ctx->mod->name);
byte *texel_block = Hunk_AllocName (0, skinsize * num_skins,
alias_ctx->mod->name);
for (int i = 0; i < num_skins; i++) {
__auto_type skin = alias_ctx->skins.a + i;
byte *texels = texel_block + i * skinsize;
auto skin = alias_ctx->skins.a + i;
byte *texels = texel_block + i * skinsize;
skin->skindesc->skin = texels - (byte *) header;
skin->skindesc->skin = (byte *)&tex_block[i] - (byte *) header;
tex_block[i] = (tex_t) {
.width = header->mdl.skinwidth,
.height = header->mdl.skinheight,
.format = tex_palette,
.relative = 1,
.palette = vid.palette,
.data = (byte *) (texels - (byte *) header),
};
memcpy (texels, skin->texels, skinsize);
gl_Mod_LoadSkin (alias_ctx, texels, skin->skin_num, skin->group_num,
skin->skindesc);
}
}

View file

@ -142,18 +142,15 @@ skinpair_cmp (const void *_tex, const void *_skinpair)
}
glskin_t
gl_Skin_Get (const skin_t *skin, const colormap_t *colormap)
gl_Skin_Get (const tex_t *tex, const colormap_t *colormap,
const byte *texel_base)
{
if (!skin || !colormap) {
return (glskin_t) {};
}
byte top = colormap->top & 0x0f;
byte bot = colormap->bottom & 0x0f;
byte top = colormap ? colormap->top & 0x0f : TOP_COLOR;
byte bot = colormap ? colormap->bottom & 0x0f : BOTTOM_COLOR;
int ind = top | (bot << 4);
skinpair_t *sp = fbsearch (skin->tex, skin_table[ind], skin_counts[ind],
skinpair_t *sp = fbsearch (tex, skin_table[ind], skin_counts[ind],
sizeof (skinpair_t), skinpair_cmp);
if (sp && sp->tex == skin->tex) {
if (sp && sp->tex == tex) {
return sp->skin;
}
if (skin_counts[ind] == MAX_GLSKINS) {
@ -165,7 +162,7 @@ gl_Skin_Get (const skin_t *skin, const colormap_t *colormap)
sizeof (skinpair_t[skin_counts[ind] - insert]));
skin_counts[ind]++;
sp->tex = skin->tex;
sp->tex = tex;
auto build_skin = vid.is8bit ? build_skin_8 : build_skin_32;
@ -177,15 +174,22 @@ gl_Skin_Get (const skin_t *skin, const colormap_t *colormap)
swidth = max (swidth, 1);
sheight = max (sheight, 1);
tex_t wtex = *tex;
if (wtex.relative) {
wtex.relative = 0;
// discarding const :(
wtex.data = (byte *) (texel_base + (uintptr_t) wtex.data);
}
byte palette[256];
Skin_SetPalette (palette, top, bot);
qfglGenTextures (1, &sp->skin.id);
build_skin_32 (sp->tex, sp->skin.id, palette, swidth, sheight, false);
build_skin_32 (&wtex, sp->skin.id, palette, swidth, sheight, false);
int size = sp->tex->width * sp->tex->height;
int size = wtex.width * wtex.height;
byte fbskin[size];
if (Mod_CalcFullbright (fbskin, skin->tex->data, size)) {
tex_t fb_tex = *sp->tex;
if (Mod_CalcFullbright (fbskin, wtex.data, size)) {
tex_t fb_tex = wtex;
fb_tex.data = fbskin;
qfglGenTextures (1, &sp->skin.fb);
build_skin (&fb_tex, sp->skin.fb, palette, swidth, sheight, true);

View file

@ -123,6 +123,9 @@ Skin_SetColormap (byte *dest, int top, int bottom)
VISIBLE void
Skin_SetPalette (byte *dest, int top, int bottom)
{
top = bound (0, top, 13) * 16;
bottom = bound (0, bottom, 13) * 16;
for (int i = 0; i < 256; i++) {
dest[i] = i;
}

View file

@ -185,15 +185,15 @@ GL_DrawAliasFrameMulti (vert_order_t *vo)
Standard shadow drawing (triangles version)
*/
static void
GL_DrawAliasShadowTri (transform_t transform, const aliashdr_t *paliashdr,
GL_DrawAliasShadowTri (transform_t transform, const aliashdr_t *ahdr,
const vert_order_t *vo)
{
int count = vo->count;
const blended_vert_t *verts = vo->verts;
float height, lheight;
vec3_t point;
const vec_t *scale = paliashdr->mdl.scale;
const vec_t *scale_origin = paliashdr->mdl.scale_origin;
const vec_t *scale = ahdr->mdl.scale;
const vec_t *scale_origin = ahdr->mdl.scale_origin;
vec4f_t entorigin;
entorigin = Transform_GetWorldPosition (transform);
@ -225,7 +225,7 @@ GL_DrawAliasShadowTri (transform_t transform, const aliashdr_t *paliashdr,
Standard shadow drawing
*/
static void
GL_DrawAliasShadow (transform_t transform, const aliashdr_t *paliashdr,
GL_DrawAliasShadow (transform_t transform, const aliashdr_t *ahdr,
const vert_order_t *vo)
{
float height, lheight;
@ -251,14 +251,14 @@ GL_DrawAliasShadow (transform_t transform, const aliashdr_t *paliashdr,
do {
// normals and vertices come from the frame list
point[0] =
verts->vert[0] * paliashdr->mdl.scale[0] +
paliashdr->mdl.scale_origin[0];
verts->vert[0] * ahdr->mdl.scale[0] +
ahdr->mdl.scale_origin[0];
point[1] =
verts->vert[1] * paliashdr->mdl.scale[1] +
paliashdr->mdl.scale_origin[1];
verts->vert[1] * ahdr->mdl.scale[1] +
ahdr->mdl.scale_origin[1];
point[2] =
verts->vert[2] * paliashdr->mdl.scale[2] +
paliashdr->mdl.scale_origin[2] + lheight;
verts->vert[2] * ahdr->mdl.scale[2] +
ahdr->mdl.scale_origin[2] + lheight;
point[0] -= shadevector[0] * point[2];
point[1] -= shadevector[1] * point[2];
@ -273,25 +273,24 @@ GL_DrawAliasShadow (transform_t transform, const aliashdr_t *paliashdr,
}
static inline vert_order_t *
GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t e)
GL_GetAliasFrameVerts16 (aliashdr_t *ahdr, entity_t e)
{
animation_t *animation = Ent_GetComponent (e.id, e.base + scene_animation, e.reg);
float blend = R_AliasGetLerpedFrames (animation, paliashdr);
float blend = R_AliasGetLerpedFrames (animation, ahdr);
int count, i;
trivertx16_t *verts;
vert_order_t *vo;
blended_vert_t *vo_v;
verts = (trivertx16_t *) ((byte *) paliashdr + paliashdr->posedata);
verts = (trivertx16_t *) ((byte *) ahdr + ahdr->posedata);
count = paliashdr->poseverts;
count = ahdr->poseverts;
vo = Hunk_TempAlloc (0, sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->order = (int *) ((byte *) ahdr + ahdr->commands);
vo->verts = (blended_vert_t *) &vo[1];
if (paliashdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) paliashdr
+ paliashdr->tex_coord);
if (ahdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) ahdr + ahdr->tex_coord);
} else {
vo->tex_coord = NULL;
}
@ -338,24 +337,24 @@ GL_GetAliasFrameVerts16 (aliashdr_t *paliashdr, entity_t e)
}
static inline vert_order_t *
GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t e)
GL_GetAliasFrameVerts (aliashdr_t *ahdr, entity_t e)
{
animation_t *animation = Ent_GetComponent (e.id, e.base + scene_animation, e.reg);
float blend = R_AliasGetLerpedFrames (animation, paliashdr);
float blend = R_AliasGetLerpedFrames (animation, ahdr);
int count, i;
trivertx_t *verts;
vert_order_t *vo;
blended_vert_t *vo_v;
verts = (trivertx_t *) ((byte *) paliashdr + paliashdr->posedata);
verts = (trivertx_t *) ((byte *) ahdr + ahdr->posedata);
count = paliashdr->poseverts;
count = ahdr->poseverts;
vo = Hunk_TempAlloc (0, sizeof (*vo) + count * sizeof (blended_vert_t));
vo->order = (int *) ((byte *) paliashdr + paliashdr->commands);
vo->order = (int *) ((byte *) ahdr + ahdr->commands);
vo->verts = (blended_vert_t *) &vo[1];
if (paliashdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) paliashdr + paliashdr->tex_coord);
if (ahdr->tex_coord) {
vo->tex_coord = (tex_coord_t *) ((byte *) ahdr + ahdr->tex_coord);
} else {
vo->tex_coord = NULL;
}
@ -400,6 +399,27 @@ GL_GetAliasFrameVerts (aliashdr_t *paliashdr, entity_t e)
return vo;
}
static glskin_t
gl_get_skin (entity_t e, renderer_t *renderer, aliashdr_t *ahdr)
{
auto colormap = Entity_GetColormap (e);
if (!gl_nocolors) {
skin_t *skin = renderer->skin ? Skin_Get (renderer->skin) : nullptr;
if (skin) {
return gl_Skin_Get (skin->tex, colormap, (byte *) ahdr);
}
}
maliasskindesc_t *skindesc;
animation_t *animation = Ent_GetComponent (e.id, e.base + scene_animation,
e.reg);
skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, ahdr);
if (!skindesc->texnum) {
auto tex = (tex_t *) ((byte *) ahdr + skindesc->skin);
return gl_Skin_Get (tex, colormap, (byte *) ahdr);
}
return (glskin_t) { .id = skindesc->texnum, .fb = skindesc->fb_texnum };
}
void
gl_R_DrawAliasModel (entity_t e)
{
@ -408,10 +428,10 @@ gl_R_DrawAliasModel (entity_t e)
color[4] = {0.0, 0.0, 0.0, 1.0},
dark[4] = {0.0, 0.0, 0.0, 1.0},
emission[4] = {0.0, 0.0, 0.0, 1.0};
int gl_light, texture = 0;
int fb_texture = 0, used_lights = 0;
int gl_light;
int used_lights = 0;
bool is_fullbright = false;
aliashdr_t *paliashdr;
aliashdr_t *ahdr;
vec3_t dist, scale;
vec4f_t origin;
vert_order_t *vo;
@ -551,54 +571,37 @@ gl_R_DrawAliasModel (entity_t e)
}
// locate the proper data
if (!(paliashdr = renderer->model->aliashdr)) {
paliashdr = Cache_Get (&renderer->model->cache);
if (!(ahdr = renderer->model->aliashdr)) {
ahdr = Cache_Get (&renderer->model->cache);
}
gl_ctx->alias_polys += paliashdr->mdl.numtris;
gl_ctx->alias_polys += ahdr->mdl.numtris;
// if the model has a colorised/external skin, use it, otherwise use
// the skin embedded in the model data
if (!gl_nocolors) {
skin_t *skin = renderer->skin ? Skin_Get (renderer->skin) : nullptr;
auto colormap = Entity_GetColormap (e);
auto glskin = gl_Skin_Get (skin, colormap);
if (glskin.id) {
texture = glskin.id;
fb_texture = glskin.fb;
}
}
if (!texture) {
maliasskindesc_t *skindesc;
animation_t *animation = Ent_GetComponent (e.id, e.base + scene_animation,
e.reg);
skindesc = R_AliasGetSkindesc (animation, renderer->skinnum, paliashdr);
texture = skindesc->texnum;
fb_texture = skindesc->fb_texnum;
}
auto glskin = gl_get_skin (e, renderer, ahdr);
if (!gl_fb_models || is_fullbright) {
fb_texture = 0;
glskin.fb = 0;
}
if (paliashdr->mdl.ident == HEADER_MDL16) {
if (ahdr->mdl.ident == HEADER_MDL16) {
// because we multipled by 256 when we loaded the verts, we have to
// scale by 1/256 when drawing.
//FIXME see scaling above
VectorScale (paliashdr->mdl.scale, 1 / 256.0, scale);
vo = GL_GetAliasFrameVerts16 (paliashdr, e);
VectorScale (ahdr->mdl.scale, 1 / 256.0, scale);
vo = GL_GetAliasFrameVerts16 (ahdr, e);
} else {
//FIXME see scaling above
VectorScale (paliashdr->mdl.scale, 1, scale);
vo = GL_GetAliasFrameVerts (paliashdr, e);
VectorScale (ahdr->mdl.scale, 1, scale);
vo = GL_GetAliasFrameVerts (ahdr, e);
}
// setup the transform
qfglPushMatrix ();
gl_R_RotateForEntity (Transform_GetWorldMatrixPtr (transform));
qfglTranslatef (paliashdr->mdl.scale_origin[0],
paliashdr->mdl.scale_origin[1],
paliashdr->mdl.scale_origin[2]);
qfglTranslatef (ahdr->mdl.scale_origin[0],
ahdr->mdl.scale_origin[1],
ahdr->mdl.scale_origin[2]);
qfglScalef (scale[0], scale[1], scale[2]);
if (gl_modelalpha < 1.0)
@ -606,7 +609,7 @@ gl_R_DrawAliasModel (entity_t e)
// draw all the triangles
if (is_fullbright) {
qfglBindTexture (GL_TEXTURE_2D, texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.id);
if (gl_vector_light) {
qfglDisable (GL_LIGHTING);
@ -624,9 +627,9 @@ gl_R_DrawAliasModel (entity_t e)
qfglEnable (GL_NORMALIZE);
qfglEnable (GL_LIGHTING);
}
} else if (!fb_texture) {
} else if (!glskin.fb) {
// Model has no fullbrights, don't bother with multi
qfglBindTexture (GL_TEXTURE_2D, texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.id);
if (vo->tex_coord)
GL_DrawAliasFrameTri (vo);
else
@ -634,11 +637,11 @@ gl_R_DrawAliasModel (entity_t e)
} else { // try multitexture
if (gl_mtex_active_tmus >= 2) { // set up the textures
qglActiveTexture (gl_mtex_enum + 0);
qfglBindTexture (GL_TEXTURE_2D, texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.id);
qglActiveTexture (gl_mtex_enum + 1);
qfglEnable (GL_TEXTURE_2D);
qfglBindTexture (GL_TEXTURE_2D, fb_texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.fb);
// do the heavy lifting
if (vo->tex_coord)
@ -651,7 +654,7 @@ gl_R_DrawAliasModel (entity_t e)
qglActiveTexture (gl_mtex_enum + 0);
} else {
if (vo->tex_coord) {
qfglBindTexture (GL_TEXTURE_2D, texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.id);
GL_DrawAliasFrameTri (vo);
if (gl_vector_light) {
@ -662,7 +665,7 @@ gl_R_DrawAliasModel (entity_t e)
qfglColor4fv (renderer->colormod);
qfglBindTexture (GL_TEXTURE_2D, fb_texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.fb);
GL_DrawAliasFrameTri (vo);
if (gl_vector_light) {
@ -671,7 +674,7 @@ gl_R_DrawAliasModel (entity_t e)
qfglEnable (GL_NORMALIZE);
}
} else {
qfglBindTexture (GL_TEXTURE_2D, texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.id);
GL_DrawAliasFrame (vo);
if (gl_vector_light) {
@ -682,7 +685,7 @@ gl_R_DrawAliasModel (entity_t e)
qfglColor4fv (renderer->colormod);
qfglBindTexture (GL_TEXTURE_2D, fb_texture);
qfglBindTexture (GL_TEXTURE_2D, glskin.fb);
GL_DrawAliasFrame (vo);
if (gl_vector_light) {
@ -724,9 +727,9 @@ gl_R_DrawAliasModel (entity_t e)
vec = m3vmulf (shadow_mat, vec);
VectorCopy (vec, shadevector);
if (vo->tex_coord)
GL_DrawAliasShadowTri (transform, paliashdr, vo);
GL_DrawAliasShadowTri (transform, ahdr, vo);
else
GL_DrawAliasShadow (transform, paliashdr, vo);
GL_DrawAliasShadow (transform, ahdr, vo);
qfglDepthMask (GL_TRUE);
qfglEnable (GL_TEXTURE_2D);