[iortcw] 56/89: All: Allow more than 32 surfaces in skin files
Simon McVittie
smcv at debian.org
Fri Sep 8 10:44:27 UTC 2017
This is an automated email from the git hooks/post-receive script.
smcv pushed a commit to tag 1.51b
in repository iortcw.
commit f040cfb7f42ebb6a60f921f13f77c80c22187002
Author: MAN-AT-ARMS <M4N4T4RMS at gmail.com>
Date: Thu Jul 20 10:53:36 2017 -0400
All: Allow more than 32 surfaces in skin files
---
MP/code/rend2/tr_animation.c | 18 +++++++++++-------
MP/code/rend2/tr_image.c | 23 ++++++++++++++---------
MP/code/rend2/tr_local.h | 16 +++++++++++-----
MP/code/rend2/tr_mesh.c | 9 ++++-----
MP/code/rend2/tr_model_iqm.c | 9 +++++++--
MP/code/renderer/tr_animation.c | 18 +++++++++++-------
MP/code/renderer/tr_cmesh.c | 10 ++++------
MP/code/renderer/tr_image.c | 23 ++++++++++++++---------
MP/code/renderer/tr_local.h | 16 +++++++++++-----
MP/code/renderer/tr_mesh.c | 12 ++++--------
MP/code/renderer/tr_model_iqm.c | 9 +++++++--
SP/code/rend2/tr_animation.c | 14 +++++++++-----
SP/code/rend2/tr_image.c | 23 ++++++++++++++---------
SP/code/rend2/tr_local.h | 16 +++++++++++-----
SP/code/rend2/tr_mesh.c | 4 ++--
SP/code/rend2/tr_model_iqm.c | 9 +++++++--
SP/code/renderer/tr_animation.c | 14 +++++++++-----
SP/code/renderer/tr_cmesh.c | 25 +++++++++++--------------
SP/code/renderer/tr_image.c | 23 ++++++++++++++---------
SP/code/renderer/tr_local.h | 16 +++++++++++-----
SP/code/renderer/tr_mesh.c | 24 +++++++++++-------------
SP/code/renderer/tr_model_iqm.c | 9 +++++++--
22 files changed, 204 insertions(+), 136 deletions(-)
diff --git a/MP/code/rend2/tr_animation.c b/MP/code/rend2/tr_animation.c
index 80b7679..7cfd936 100644
--- a/MP/code/rend2/tr_animation.c
+++ b/MP/code/rend2/tr_animation.c
@@ -355,8 +355,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
if ( ent->e.renderfx & RF_BLINK ) {
const char *s = va( "%s_b", surface->name ); // append '_b' for 'blink'
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- if ( !strcmp( skin->surfaces[j]->name, s ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, s ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -366,8 +366,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1605,9 +1605,9 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1638,7 +1638,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
}
- if (!personalModel)
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 )
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
+
+ if ( !personalModel )
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse, cubemapIndex );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
diff --git a/MP/code/rend2/tr_image.c b/MP/code/rend2/tr_image.c
index dca835f..834dc2a 100644
--- a/MP/code/rend2/tr_image.c
+++ b/MP/code/rend2/tr_image.c
@@ -3223,6 +3223,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;
@@ -3279,8 +3280,8 @@ qhandle_t RE_RegisterSkin( const char *name ) {
skin->numSurfaces = 0;
skin->numModels = 0; //----(SA) added
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;
}
@@ -3350,12 +3351,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++;
@@ -3374,6 +3375,10 @@ qhandle_t RE_RegisterSkin( const char *name ) {
}
}
+ // 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;
}
@@ -3392,8 +3397,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;
}
/*
@@ -3422,10 +3427,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" );
diff --git a/MP/code/rend2/tr_local.h b/MP/code/rend2/tr_local.h
index 3895bfd..cc146d1 100644
--- a/MP/code/rend2/tr_local.h
+++ b/MP/code/rend2/tr_local.h
@@ -860,6 +860,12 @@ typedef struct {
//=================================================================================
+// max surfaces per-skin
+// This is an arbitry limit. Vanilla Q3 only supported 32 surfaces in skins but failed to
+// enforce the maximum limit when reading skin files. It was possile to use more than 32
+// surfaces which accessed out of bounds memory past end of skin->surfaces hunk block.
+#define MAX_SKIN_SURFACES 256
+
// skins allow models to be retextured without modifying the model file
typedef struct {
char name[MAX_QPATH];
@@ -870,17 +876,17 @@ typedef struct {
#define MAX_PART_MODELS 5
typedef struct {
- char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
- char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
+ char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
+ char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
} skinModel_t;
typedef struct skin_s {
- char name[MAX_QPATH]; // game path, including extension
+ char name[MAX_QPATH]; // game path, including extension
int numSurfaces;
int numModels;
- skinSurface_t *surfaces[MD3_MAX_SURFACES];
+ skinSurface_t *surfaces; // dynamically allocated array of surfaces
skinModel_t *models[MAX_PART_MODELS];
- vec3_t scale; //----(SA) added
+ vec3_t scale; //----(SA) added
} skin_t;
//----(SA) end
diff --git a/MP/code/rend2/tr_mesh.c b/MP/code/rend2/tr_mesh.c
index 695491f..538fe1e 100644
--- a/MP/code/rend2/tr_mesh.c
+++ b/MP/code/rend2/tr_mesh.c
@@ -382,8 +382,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
if ( ent->e.renderfx & RF_BLINK ) {
const char *s = va( "%s_b", surface->name ); // append '_b' for 'blink'
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- if ( !strcmp( skin->surfaces[j]->name, s ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, s ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -392,9 +392,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
if ( shader == tr.defaultShader ) { // blink reference in skin was not found
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
-
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
diff --git a/MP/code/rend2/tr_model_iqm.c b/MP/code/rend2/tr_model_iqm.c
index 5b528d0..507158c 100644
--- a/MP/code/rend2/tr_model_iqm.c
+++ b/MP/code/rend2/tr_model_iqm.c
@@ -907,9 +907,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -936,6 +936,11 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0, 0, 0 );
}
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0 );
+ }
+
if( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, 0, 0, cubemapIndex );
}
diff --git a/MP/code/renderer/tr_animation.c b/MP/code/renderer/tr_animation.c
index ce92d56..2dc73b8 100644
--- a/MP/code/renderer/tr_animation.c
+++ b/MP/code/renderer/tr_animation.c
@@ -353,8 +353,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
if ( ent->e.renderfx & RF_BLINK ) {
const char *s = va( "%s_b", surface->name ); // append '_b' for 'blink'
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- if ( !strcmp( skin->surfaces[j]->name, s ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, s ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -364,8 +364,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1603,9 +1603,9 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1636,7 +1636,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
}
- if (!personalModel)
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 )
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
+
+ if ( !personalModel )
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
diff --git a/MP/code/renderer/tr_cmesh.c b/MP/code/renderer/tr_cmesh.c
index aca1fea..365e461 100644
--- a/MP/code/renderer/tr_cmesh.c
+++ b/MP/code/renderer/tr_cmesh.c
@@ -376,8 +376,8 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
if ( ent->e.renderfx & RF_BLINK ) {
const char *s = va( "%s_b", surface->name ); // append '_b' for 'blink'
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- if ( !strcmp( skin->surfaces[j]->name, s ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, s ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -387,8 +387,8 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -426,7 +426,6 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
if ( r_shadows->integer == 4 ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
}
-
//----(SA) done testing
// don't add third_person objects if not viewing through a portal
@@ -436,6 +435,5 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
surface = ( mdcSurface_t * )( (byte *)surface + surface->ofsEnd );
}
-
}
diff --git a/MP/code/renderer/tr_image.c b/MP/code/renderer/tr_image.c
index 6b3ce45..402f117 100644
--- a/MP/code/renderer/tr_image.c
+++ b/MP/code/renderer/tr_image.c
@@ -1879,6 +1879,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;
@@ -1935,8 +1936,8 @@ qhandle_t RE_RegisterSkin( const char *name ) {
skin->numSurfaces = 0;
skin->numModels = 0; //----(SA) added
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;
}
@@ -2006,12 +2007,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++;
@@ -2030,6 +2031,10 @@ qhandle_t RE_RegisterSkin( const char *name ) {
}
}
+ // 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;
}
@@ -2048,8 +2053,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;
}
/*
@@ -2078,10 +2083,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" );
diff --git a/MP/code/renderer/tr_local.h b/MP/code/renderer/tr_local.h
index c036572..e0722f6 100644
--- a/MP/code/renderer/tr_local.h
+++ b/MP/code/renderer/tr_local.h
@@ -502,6 +502,12 @@ typedef struct {
//=================================================================================
+// max surfaces per-skin
+// This is an arbitry limit. Vanilla Q3 only supported 32 surfaces in skins but failed to
+// enforce the maximum limit when reading skin files. It was possile to use more than 32
+// surfaces which accessed out of bounds memory past end of skin->surfaces hunk block.
+#define MAX_SKIN_SURFACES 256
+
// skins allow models to be retextured without modifying the model file
typedef struct {
char name[MAX_QPATH];
@@ -512,17 +518,17 @@ typedef struct {
#define MAX_PART_MODELS 5
typedef struct {
- char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
- char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
+ char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
+ char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
} skinModel_t;
typedef struct skin_s {
- char name[MAX_QPATH]; // game path, including extension
+ char name[MAX_QPATH]; // game path, including extension
int numSurfaces;
int numModels;
- skinSurface_t *surfaces[MD3_MAX_SURFACES];
+ skinSurface_t *surfaces; // dynamically allocated array of surfaces
skinModel_t *models[MAX_PART_MODELS];
- vec3_t scale; //----(SA) added
+ vec3_t scale; //----(SA) added
} skin_t;
//----(SA) end
diff --git a/MP/code/renderer/tr_mesh.c b/MP/code/renderer/tr_mesh.c
index e3deb99..8cf262c 100644
--- a/MP/code/renderer/tr_mesh.c
+++ b/MP/code/renderer/tr_mesh.c
@@ -378,8 +378,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
if ( ent->e.renderfx & RF_BLINK ) {
const char *s = va( "%s_b", surface->name ); // append '_b' for 'blink'
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
- if ( !strcmp( skin->surfaces[j]->name, s ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, s ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -388,9 +388,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
if ( shader == tr.defaultShader ) { // blink reference in skin was not found
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
-
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -430,13 +429,11 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
}
-
// for testing polygon shadows (on /all/ models)
if ( r_shadows->integer == 4 ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
}
-
// don't add third_person objects if not viewing through a portal
if ( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse );
@@ -444,6 +441,5 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
surface = ( md3Surface_t * )( (byte *)surface + surface->ofsEnd );
}
-
}
diff --git a/MP/code/renderer/tr_model_iqm.c b/MP/code/renderer/tr_model_iqm.c
index b6f570e..370fc45 100644
--- a/MP/code/renderer/tr_model_iqm.c
+++ b/MP/code/renderer/tr_model_iqm.c
@@ -903,9 +903,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -932,6 +932,11 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0 );
}
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
+ }
+
if( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, 0 );
}
diff --git a/SP/code/rend2/tr_animation.c b/SP/code/rend2/tr_animation.c
index 5d24a33..d7c9d7c 100644
--- a/SP/code/rend2/tr_animation.c
+++ b/SP/code/rend2/tr_animation.c
@@ -387,8 +387,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1598,9 +1598,9 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1631,7 +1631,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0, ATI_TESS_TRUFORM );
}
- if (!personalModel)
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 )
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0, ATI_TESS_TRUFORM );
+
+ if ( !personalModel )
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, qfalse, cubemapIndex, ATI_TESS_TRUFORM );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
diff --git a/SP/code/rend2/tr_image.c b/SP/code/rend2/tr_image.c
index 56e8ab4..32b9c83 100644
--- a/SP/code/rend2/tr_image.c
+++ b/SP/code/rend2/tr_image.c
@@ -3228,6 +3228,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;
@@ -3284,8 +3285,8 @@ qhandle_t RE_RegisterSkin( const char *name ) {
skin->numSurfaces = 0;
skin->numModels = 0; //----(SA) added
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;
}
@@ -3355,12 +3356,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++;
@@ -3379,6 +3380,10 @@ qhandle_t RE_RegisterSkin( const char *name ) {
}
}
+ // 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;
}
@@ -3397,8 +3402,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;
}
/*
@@ -3427,10 +3432,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" );
diff --git a/SP/code/rend2/tr_local.h b/SP/code/rend2/tr_local.h
index 73b22c1..cf78ef2 100644
--- a/SP/code/rend2/tr_local.h
+++ b/SP/code/rend2/tr_local.h
@@ -864,6 +864,12 @@ typedef struct {
//=================================================================================
+// max surfaces per-skin
+// This is an arbitry limit. Vanilla Q3 only supported 32 surfaces in skins but failed to
+// enforce the maximum limit when reading skin files. It was possile to use more than 32
+// surfaces which accessed out of bounds memory past end of skin->surfaces hunk block.
+#define MAX_SKIN_SURFACES 256
+
// skins allow models to be retextured without modifying the model file
typedef struct {
char name[MAX_QPATH];
@@ -874,17 +880,17 @@ typedef struct {
#define MAX_PART_MODELS 5
typedef struct {
- char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
- char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
+ char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
+ char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
} skinModel_t;
typedef struct skin_s {
- char name[MAX_QPATH]; // game path, including extension
+ char name[MAX_QPATH]; // game path, including extension
int numSurfaces;
int numModels;
- skinSurface_t *surfaces[MD3_MAX_SURFACES];
+ skinSurface_t *surfaces; // dynamically allocated array of surfaces
skinModel_t *models[MAX_PART_MODELS];
- vec3_t scale; //----(SA) added
+ vec3_t scale; //----(SA) added
} skin_t;
//----(SA) end
diff --git a/SP/code/rend2/tr_mesh.c b/SP/code/rend2/tr_mesh.c
index 15902d6..bbfbc69 100644
--- a/SP/code/rend2/tr_mesh.c
+++ b/SP/code/rend2/tr_mesh.c
@@ -411,8 +411,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
diff --git a/SP/code/rend2/tr_model_iqm.c b/SP/code/rend2/tr_model_iqm.c
index deabf42..5274c0e 100644
--- a/SP/code/rend2/tr_model_iqm.c
+++ b/SP/code/rend2/tr_model_iqm.c
@@ -907,9 +907,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -936,6 +936,11 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0, 0, 0, ATI_TESS_TRUFORM );
}
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, qfalse, 0, ATI_TESS_TRUFORM );
+ }
+
if( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, 0, 0, cubemapIndex, ATI_TESS_TRUFORM );
}
diff --git a/SP/code/renderer/tr_animation.c b/SP/code/renderer/tr_animation.c
index e0f4bc6..8b31d55 100644
--- a/SP/code/renderer/tr_animation.c
+++ b/SP/code/renderer/tr_animation.c
@@ -385,8 +385,8 @@ void R_AddAnimSurfaces( trRefEntity_t *ent ) {
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1593,9 +1593,9 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -1626,7 +1626,11 @@ void R_MDRAddAnimSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, ATI_TESS_TRUFORM );
}
- if (!personalModel)
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 )
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, ATI_TESS_TRUFORM );
+
+ if ( !personalModel )
R_AddDrawSurf( (void *)surface, shader, fogNum, qfalse, ATI_TESS_TRUFORM );
surface = (mdrSurface_t *)( (byte *)surface + surface->ofsEnd );
diff --git a/SP/code/renderer/tr_cmesh.c b/SP/code/renderer/tr_cmesh.c
index 607251f..23550ad 100644
--- a/SP/code/renderer/tr_cmesh.c
+++ b/SP/code/renderer/tr_cmesh.c
@@ -407,8 +407,8 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -433,20 +433,18 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.shadowShader, 0, qfalse, tr.currentModel->ATI_tess );
}
-//----(SA)
-
// projection shadows work fine with personal models
-// if ( r_shadows->integer == 3
-// && fogNum == 0
-// && (ent->e.renderfx & RF_SHADOW_PLANE )
-// && shader->sort == SS_OPAQUE ) {
-// R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
-// }
+ if ( r_shadows->integer == 3
+ && fogNum == 0
+ && (ent->e.renderfx & RF_SHADOW_PLANE )
+ && shader->sort == SS_OPAQUE ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, tr.currentModel->ATI_tess );
+ }
//----(SA) for testing polygon shadows (on /all/ models)
-// if ( r_shadows->integer == 4)
-// R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
-
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, tr.currentModel->ATI_tess );
+ }
//----(SA) done testing
// don't add third_person objects if not viewing through a portal
@@ -457,6 +455,5 @@ void R_AddMDCSurfaces( trRefEntity_t *ent ) {
surface = ( mdcSurface_t * )( (byte *)surface + surface->ofsEnd );
}
-
}
diff --git a/SP/code/renderer/tr_image.c b/SP/code/renderer/tr_image.c
index 2893b58..2ce4d6d 100644
--- a/SP/code/renderer/tr_image.c
+++ b/SP/code/renderer/tr_image.c
@@ -1950,6 +1950,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;
@@ -2006,8 +2007,8 @@ qhandle_t RE_RegisterSkin( const char *name ) {
skin->numSurfaces = 0;
skin->numModels = 0; //----(SA) added
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;
}
@@ -2077,12 +2078,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++;
@@ -2101,6 +2102,10 @@ qhandle_t RE_RegisterSkin( const char *name ) {
}
}
+ // 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;
}
@@ -2119,8 +2124,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;
}
/*
@@ -2149,10 +2154,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" );
diff --git a/SP/code/renderer/tr_local.h b/SP/code/renderer/tr_local.h
index a23037d..a53ee2f 100644
--- a/SP/code/renderer/tr_local.h
+++ b/SP/code/renderer/tr_local.h
@@ -506,6 +506,12 @@ typedef struct {
//=================================================================================
+// max surfaces per-skin
+// This is an arbitry limit. Vanilla Q3 only supported 32 surfaces in skins but failed to
+// enforce the maximum limit when reading skin files. It was possile to use more than 32
+// surfaces which accessed out of bounds memory past end of skin->surfaces hunk block.
+#define MAX_SKIN_SURFACES 256
+
// skins allow models to be retextured without modifying the model file
typedef struct {
char name[MAX_QPATH];
@@ -516,17 +522,17 @@ typedef struct {
#define MAX_PART_MODELS 5
typedef struct {
- char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
- char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
+ char type[MAX_QPATH]; // md3_lower, md3_lbelt, md3_rbelt, etc.
+ char model[MAX_QPATH]; // lower.md3, belt1.md3, etc.
} skinModel_t;
typedef struct skin_s {
- char name[MAX_QPATH]; // game path, including extension
+ char name[MAX_QPATH]; // game path, including extension
int numSurfaces;
int numModels;
- skinSurface_t *surfaces[MD3_MAX_SURFACES];
+ skinSurface_t *surfaces; // dynamically allocated array of surfaces
skinModel_t *models[MAX_PART_MODELS];
- vec3_t scale; //----(SA) added
+ vec3_t scale; //----(SA) added
} skin_t;
//----(SA) end
diff --git a/SP/code/renderer/tr_mesh.c b/SP/code/renderer/tr_mesh.c
index 5f016a4..5390c57 100644
--- a/SP/code/renderer/tr_mesh.c
+++ b/SP/code/renderer/tr_mesh.c
@@ -406,8 +406,8 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
shader = tr.defaultShader;
for ( j = 0 ; j < skin->numSurfaces ; j++ ) {
// the names have both been lowercased
- if ( !strcmp( skin->surfaces[j]->name, surface->name ) ) {
- shader = skin->surfaces[j]->shader;
+ if ( !strcmp( skin->surfaces[j].name, surface->name ) ) {
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -439,18 +439,17 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
}
// projection shadows work fine with personal models
-// if ( r_shadows->integer == 3
-// && fogNum == 0
-// && (ent->e.renderfx & RF_SHADOW_PLANE )
-// && shader->sort == SS_OPAQUE ) {
-// R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
-// }
-
+ if ( r_shadows->integer == 3
+ && fogNum == 0
+ && (ent->e.renderfx & RF_SHADOW_PLANE )
+ && shader->sort == SS_OPAQUE ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, tr.currentModel->ATI_tess );
+ }
// for testing polygon shadows (on /all/ models)
-// if ( r_shadows->integer == 4)
-// R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse );
-
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, tr.currentModel->ATI_tess );
+ }
// don't add third_person objects if not viewing through a portal
if ( !personalModel ) {
@@ -460,6 +459,5 @@ void R_AddMD3Surfaces( trRefEntity_t *ent ) {
surface = ( md3Surface_t * )( (byte *)surface + surface->ofsEnd );
}
-
}
diff --git a/SP/code/renderer/tr_model_iqm.c b/SP/code/renderer/tr_model_iqm.c
index 5ab41c2..b1ab522 100644
--- a/SP/code/renderer/tr_model_iqm.c
+++ b/SP/code/renderer/tr_model_iqm.c
@@ -903,9 +903,9 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
for(j = 0; j < skin->numSurfaces; j++)
{
- if (!strcmp(skin->surfaces[j]->name, surface->name))
+ if (!strcmp(skin->surfaces[j].name, surface->name))
{
- shader = skin->surfaces[j]->shader;
+ shader = skin->surfaces[j].shader;
break;
}
}
@@ -932,6 +932,11 @@ void R_AddIQMSurfaces( trRefEntity_t *ent ) {
R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, 0, ATI_TESS_TRUFORM );
}
+ // for testing polygon shadows (on /all/ models)
+ if ( r_shadows->integer == 4 ) {
+ R_AddDrawSurf( (void *)surface, tr.projectionShadowShader, 0, qfalse, ATI_TESS_TRUFORM );
+ }
+
if( !personalModel ) {
R_AddDrawSurf( (void *)surface, shader, fogNum, 0, ATI_TESS_TRUFORM );
}
--
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/pkg-games/iortcw.git
More information about the Pkg-games-commits
mailing list