From d39630580e9673e9e69ab9c40acd34d635fad0a3 Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 15 Jan 2024 14:12:59 +0900 Subject: [PATCH] [skin] Get team colors working for model skins This should actually get team colors working for all models, not just player.mdl. --- include/QF/image.h | 1 + include/mod_internal.h | 3 +- libs/models/alias/gl_model_alias.c | 56 +++------- libs/models/gl_skin.c | 32 +++--- libs/models/skin.c | 3 + libs/video/renderer/gl/gl_mod_alias.c | 141 +++++++++++++------------- 6 files changed, 110 insertions(+), 126 deletions(-) diff --git a/include/QF/image.h b/include/QF/image.h index d93f65cc3..fd1fc7365 100644 --- a/include/QF/image.h +++ b/include/QF/image.h @@ -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 }; diff --git a/include/mod_internal.h b/include/mod_internal.h index b703ee141..cc9338013 100644 --- a/include/mod_internal.h +++ b/include/mod_internal.h @@ -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 diff --git a/libs/models/alias/gl_model_alias.c b/libs/models/alias/gl_model_alias.c index 9e824177c..524b5e5fa 100644 --- a/libs/models/alias/gl_model_alias.c +++ b/libs/models/alias/gl_model_alias.c @@ -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); } } diff --git a/libs/models/gl_skin.c b/libs/models/gl_skin.c index 3b9bbad4e..2d2e3d2ac 100644 --- a/libs/models/gl_skin.c +++ b/libs/models/gl_skin.c @@ -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); diff --git a/libs/models/skin.c b/libs/models/skin.c index 312810115..e229870ab 100644 --- a/libs/models/skin.c +++ b/libs/models/skin.c @@ -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; } diff --git a/libs/video/renderer/gl/gl_mod_alias.c b/libs/video/renderer/gl/gl_mod_alias.c index da6b5d3c4..3eae26e40 100644 --- a/libs/video/renderer/gl/gl_mod_alias.c +++ b/libs/video/renderer/gl/gl_mod_alias.c @@ -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);