2
0
mirror of https://github.com/FWGS/xash3d-fwgs synced 2024-11-25 11:19:59 +01:00

engine: client: reimplement Mod_LoadMapSprite on engine side

This commit is contained in:
Alibek Omarov 2024-11-03 02:58:31 +03:00
parent addd50467e
commit 4cb11861e4

View File

@ -1165,6 +1165,126 @@ void CL_ClearSpriteTextures( void )
clgame.sprites[i].needload = NL_UNREFERENCED;
}
// it's a Valve default value for LoadMapSprite (probably must be power of two)
#define MAPSPRITE_SIZE 128
/*
====================
Mod_LoadMapSprite
Loading a bitmap image as sprite with multiple frames
as pieces of input image
====================
*/
static void Mod_LoadMapSprite( model_t *mod, const void *buffer, size_t size, qboolean *loaded )
{
rgbdata_t *pix, temp = { 0 };
char texname[128];
int i, w, h;
int xl, yl;
int numframes;
msprite_t *psprite;
char poolname[MAX_VA_STRING];
if( loaded ) *loaded = false;
Q_snprintf( texname, sizeof( texname ), "#%s", mod->name );
Image_SetForceFlags( IL_OVERVIEW );
pix = FS_LoadImage( texname, buffer, size );
Image_ClearForceFlags();
if( !pix ) return; // bad image or something else
mod->type = mod_sprite;
if( pix->width % MAPSPRITE_SIZE )
w = pix->width - ( pix->width % MAPSPRITE_SIZE );
else w = pix->width;
if( pix->height % MAPSPRITE_SIZE )
h = pix->height - ( pix->height % MAPSPRITE_SIZE );
else h = pix->height;
if( w < MAPSPRITE_SIZE ) w = MAPSPRITE_SIZE;
if( h < MAPSPRITE_SIZE ) h = MAPSPRITE_SIZE;
// resample image if needed
Image_Process( &pix, w, h, IMAGE_FORCE_RGBA|IMAGE_RESAMPLE, 0.0f );
w = h = MAPSPRITE_SIZE;
// check range
if( w > pix->width ) w = pix->width;
if( h > pix->height ) h = pix->height;
// determine how many frames we needs
numframes = (pix->width * pix->height) / (w * h);
Q_snprintf( poolname, sizeof( poolname ), "^2%s^7", mod->name );
mod->mempool = Mem_AllocPool( poolname );
psprite = Mem_Calloc( mod->mempool, sizeof( msprite_t ) + ( numframes - 1 ) * sizeof( psprite->frames ));
mod->cache.data = psprite; // make link to extradata
psprite->type = SPR_FWD_PARALLEL_ORIENTED;
psprite->texFormat = SPR_ALPHTEST;
psprite->numframes = mod->numframes = numframes;
psprite->radius = sqrt(((w >> 1) * (w >> 1)) + ((h >> 1) * (h >> 1)));
mod->mins[0] = mod->mins[1] = -w / 2;
mod->maxs[0] = mod->maxs[1] = w / 2;
mod->mins[2] = -h / 2;
mod->maxs[2] = h / 2;
// create a temporary pic
temp.width = w;
temp.height = h;
temp.type = pix->type;
temp.flags = pix->flags;
temp.size = w * h * PFDesc[temp.type].bpp;
temp.buffer = Mem_Malloc( mod->mempool, temp.size );
temp.palette = NULL;
// chop the image and upload into video memory
for( i = xl = yl = 0; i < numframes; i++ )
{
mspriteframe_t *pspriteframe;
int xh = xl + w, yh = yl + h, x, y, j;
int linedelta = ( pix->width - w ) * 4;
byte *src = pix->buffer + ( yl * pix->width + xl ) * 4;
byte *dst = temp.buffer;
// cut block from source
for( y = yl; y < yh; y++ )
{
for( x = xl; x < xh; x++ )
for( j = 0; j < 4; j++ )
*dst++ = *src++;
src += linedelta;
}
// build uinque frame name
Q_snprintf( texname, sizeof( texname ), "#MAP/%s_%i%i.spr", mod->name, i / 10, i % 10 );
psprite->frames[i].frameptr = Mem_Calloc( mod->mempool, sizeof( mspriteframe_t ));
pspriteframe = psprite->frames[i].frameptr;
pspriteframe->width = w;
pspriteframe->height = h;
pspriteframe->up = ( h >> 1 );
pspriteframe->left = -( w >> 1 );
pspriteframe->down = ( h >> 1 ) - h;
pspriteframe->right = w + -( w >> 1 );
pspriteframe->gl_texturenum = GL_LoadTextureInternal( texname, &temp, TF_IMAGE );
xl += w;
if( xl >= pix->width )
{
xl = 0;
yl += h;
}
}
FS_FreeImage( pix );
Mem_Free( temp.buffer );
if( loaded ) *loaded = true;
}
/*
=============
CL_LoadHudSprite
@ -1210,7 +1330,7 @@ static qboolean CL_LoadHudSprite( const char *szSpriteName, model_t *m_pSprite,
return false;
if( type == SPR_MAPSPRITE )
ref.dllFuncs.Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
Mod_LoadMapSprite( m_pSprite, buf, size, &loaded );
else
{
Mod_LoadSpriteModel( m_pSprite, buf, &loaded );