Allow more than 32 surfaces in skin files

Models don't have a surface limit; skins shouldn't either. Some player
models require more than 32 surfaces since vanilla Quake 3 did not
enforce the limit.

Skins are now limited to 256 surfaces because having no limit would
require parsing the skin file twice. The skin surfaces are dynamically
allocated so it doesn't increase memory usage when less surfaces
are used.
This commit is contained in:
Zack Middleton 2017-07-04 13:48:52 -05:00
parent 4dffc52c1d
commit 904bbc1a8f
10 changed files with 54 additions and 32 deletions

View file

@ -3060,6 +3060,7 @@ RE_RegisterSkin
===============
*/
qhandle_t RE_RegisterSkin( const char *name ) {
skinSurface_t parseSurfaces[MAX_SKIN_SURFACES];
qhandle_t hSkin;
skin_t *skin;
skinSurface_t *surf;
@ -3109,8 +3110,8 @@ qhandle_t RE_RegisterSkin( const char *name ) {
// If not a .skin file, load as a single shader
if ( strcmp( name + strlen( name ) - 5, ".skin" ) ) {
skin->numSurfaces = 1;
skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low );
skin->surfaces[0]->shader = R_FindShader( name, LIGHTMAP_NONE, qtrue );
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low );
skin->surfaces[0].shader = R_FindShader( name, LIGHTMAP_NONE, qtrue );
return hSkin;
}
@ -3143,12 +3144,12 @@ qhandle_t RE_RegisterSkin( const char *name ) {
// parse the shader name
token = CommaParse( &text_p );
if ( skin->numSurfaces >= MD3_MAX_SURFACES ) {
ri.Printf( PRINT_WARNING, "WARNING: Ignoring surfaces in '%s', the max is %d surfaces!\n", name, MD3_MAX_SURFACES );
if ( skin->numSurfaces >= MAX_SKIN_SURFACES ) {
ri.Printf( PRINT_WARNING, "WARNING: Ignoring surfaces in '%s', the max is %d surfaces!\n", name, MAX_SKIN_SURFACES );
break;
}
surf = skin->surfaces[ skin->numSurfaces ] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low );
surf = &parseSurfaces[skin->numSurfaces];
Q_strncpyz( surf->name, surfName, sizeof( surf->name ) );
surf->shader = R_FindShader( token, LIGHTMAP_NONE, qtrue );
skin->numSurfaces++;
@ -3162,6 +3163,10 @@ qhandle_t RE_RegisterSkin( const char *name ) {
return 0; // use default skin
}
// copy surfaces to skin
skin->surfaces = ri.Hunk_Alloc( skin->numSurfaces * sizeof( skinSurface_t ), h_low );
memcpy( skin->surfaces, parseSurfaces, skin->numSurfaces * sizeof( skinSurface_t ) );
return hSkin;
}
@ -3180,8 +3185,8 @@ void R_InitSkins( void ) {
skin = tr.skins[0] = ri.Hunk_Alloc( sizeof( skin_t ), h_low );
Q_strncpyz( skin->name, "<default skin>", sizeof( skin->name ) );
skin->numSurfaces = 1;
skin->surfaces[0] = ri.Hunk_Alloc( sizeof( *skin->surfaces[0] ), h_low );
skin->surfaces[0]->shader = tr.defaultShader;
skin->surfaces = ri.Hunk_Alloc( sizeof( skinSurface_t ), h_low );
skin->surfaces[0].shader = tr.defaultShader;
}
/*
@ -3210,10 +3215,10 @@ void R_SkinList_f( void ) {
for ( i = 0 ; i < tr.numSkins ; i++ ) {
skin = tr.skins[i];
ri.Printf( PRINT_ALL, "%3i:%s\n", i, skin->name );
ri.Printf( PRINT_ALL, "%3i:%s (%d surfaces)\n", i, skin->name, skin->numSurfaces );
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
ri.Printf( PRINT_ALL, " %s = %s\n",
skin->surfaces[j]->name, skin->surfaces[j]->shader->name );
skin->surfaces[j].name, skin->surfaces[j].shader->name );
}
}
ri.Printf (PRINT_ALL, "------------------\n");