2011-05-09 22:00:00 +02:00
|
|
|
/*
|
|
|
|
gl_rmisc.c - renderer misceallaneous
|
|
|
|
Copyright (C) 2010 Uncle Mike
|
|
|
|
|
|
|
|
This program is free software: you can redistribute it and/or modify
|
|
|
|
it under the terms of the GNU General Public License as published by
|
|
|
|
the Free Software Foundation, either version 3 of the License, or
|
|
|
|
(at your option) any later version.
|
|
|
|
|
|
|
|
This program is distributed in the hope that it will be useful,
|
|
|
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
|
|
GNU General Public License for more details.
|
|
|
|
*/
|
2010-12-03 22:00:00 +01:00
|
|
|
|
|
|
|
#include "common.h"
|
|
|
|
#include "client.h"
|
|
|
|
#include "gl_local.h"
|
2011-04-06 22:00:00 +02:00
|
|
|
#include "mod_local.h"
|
2010-12-03 22:00:00 +01:00
|
|
|
|
2011-07-07 22:00:00 +02:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
const char *texname;
|
|
|
|
const char *detail;
|
|
|
|
const char material;
|
|
|
|
int lMin;
|
|
|
|
int lMax;
|
|
|
|
} dmaterial_t;
|
|
|
|
|
2012-11-20 21:00:00 +01:00
|
|
|
typedef struct
|
|
|
|
{
|
|
|
|
char texname[64]; // shortname
|
|
|
|
imgfilter_t filter;
|
|
|
|
} dfilter_t;
|
|
|
|
|
|
|
|
dfilter_t *tex_filters[MAX_TEXTURES];
|
|
|
|
int num_texfilters;
|
|
|
|
|
2011-07-07 22:00:00 +02:00
|
|
|
// default rules for apply detail textures.
|
2011-08-14 22:00:00 +02:00
|
|
|
// maybe move this to external script?
|
2011-07-07 22:00:00 +02:00
|
|
|
static const dmaterial_t detail_table[] =
|
|
|
|
{
|
|
|
|
{ "crt", "dt_conc", 'C', 0, 0 }, // concrete
|
2011-10-14 22:00:00 +02:00
|
|
|
{ "rock", "dt_rock1", 'C', 0, 0 },
|
2011-07-07 22:00:00 +02:00
|
|
|
{ "conc", "dt_conc", 'C', 0, 0 },
|
|
|
|
{ "wall", "dt_brick", 'C', 0, 0 },
|
|
|
|
{ "crete", "dt_conc", 'C', 0, 0 },
|
|
|
|
{ "generic", "dt_brick", 'C', 0, 0 },
|
|
|
|
{ "metal", "dt_metal%i", 'M', 1, 2 }, // metal
|
|
|
|
{ "mtl", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "pipe", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "elev", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "sign", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "barrel", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "bath", "dt_ssteel1", 'M', 1, 2 },
|
|
|
|
{ "refbridge", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "panel", "dt_ssteel1", 'M', 0, 0 },
|
|
|
|
{ "brass", "dt_ssteel1", 'M', 0, 0 },
|
|
|
|
{ "car", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "circuit", "dt_metal%i", 'M', 1, 2 },
|
|
|
|
{ "steel", "dt_ssteel1", 'M', 0, 0 },
|
2011-10-06 22:00:00 +02:00
|
|
|
{ "reflect", "dt_ssteel1", 'G', 0, 0 },
|
2011-07-07 22:00:00 +02:00
|
|
|
{ "dirt", "dt_ground%i", 'D', 1, 5 }, // dirt
|
|
|
|
{ "drt", "dt_ground%i", 'D', 1, 5 },
|
|
|
|
{ "out", "dt_ground%i", 'D', 1, 5 },
|
|
|
|
{ "grass", "dt_grass1", 'D', 0, 0 },
|
2011-08-14 22:00:00 +02:00
|
|
|
{ "mud", "dt_carpet1", 'D', 0, 0 },
|
2011-07-07 22:00:00 +02:00
|
|
|
{ "vent", "dt_ssteel1", 'V', 1, 4 }, // vent
|
|
|
|
{ "duct", "dt_ssteel1", 'V', 1, 4 },
|
|
|
|
{ "tile", "dt_smooth%i", 'T', 1, 2 },
|
|
|
|
{ "labflr", "dt_smooth%i", 'T', 1, 2 },
|
|
|
|
{ "bath", "dt_smooth%i", 'T', 1, 2 },
|
|
|
|
{ "grate", "dt_stone%i", 'G', 1, 4 }, // vent
|
|
|
|
{ "stone", "dt_stone%i", 'G', 1, 4 },
|
|
|
|
{ "grt", "dt_stone%i", 'G', 1, 4 },
|
|
|
|
{ "wood", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "wd", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "table", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "board", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "chair", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "brd", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "carp", "dt_carpet1", 'W', 1, 3 },
|
|
|
|
{ "book", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "box", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "cab", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "couch", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "crate", "dt_wood%i", 'W', 1, 3 },
|
|
|
|
{ "poster", "dt_plaster%i", 'W', 1, 2 },
|
|
|
|
{ "sheet", "dt_plaster%i", 'W', 1, 2 },
|
|
|
|
{ "stucco", "dt_plaster%i", 'W', 1, 2 },
|
|
|
|
{ "comp", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "cmp", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "elec", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "vend", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "monitor", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "phone", "dt_smooth1", 'P', 0, 0 },
|
|
|
|
{ "glass", "dt_ssteel1", 'Y', 0, 0 },
|
|
|
|
{ "window", "dt_ssteel1", 'Y', 0, 0 },
|
|
|
|
{ "flesh", "dt_rough1", 'F', 0, 0 },
|
|
|
|
{ "meat", "dt_rough1", 'F', 0, 0 },
|
|
|
|
{ "fls", "dt_rough1", 'F', 0, 0 },
|
|
|
|
{ "ground", "dt_ground%i", 'D', 1, 5 },
|
|
|
|
{ "gnd", "dt_ground%i", 'D', 1, 5 },
|
|
|
|
{ "snow", "dt_snow%i", 'O', 1, 2 }, // snow
|
|
|
|
{ NULL, NULL, 0, 0, 0 }
|
|
|
|
};
|
|
|
|
|
|
|
|
static const char *R_DetailTextureForName( const char *name )
|
|
|
|
{
|
|
|
|
const dmaterial_t *table;
|
|
|
|
|
|
|
|
if( !name || !*name ) return NULL;
|
|
|
|
if( !Q_strnicmp( name, "sky", 3 ))
|
|
|
|
return NULL; // never details for sky
|
|
|
|
|
|
|
|
// never apply details for liquids
|
|
|
|
if( !Q_strnicmp( name + 1, "!lava", 5 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name + 1, "!slime", 6 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_90", 7 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_0", 6 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_270", 8 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_180", 8 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_up", 7 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "!cur_dwn", 8 ))
|
|
|
|
return NULL;
|
|
|
|
if( name[0] == '!' )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// never apply details to the special textures
|
|
|
|
if( !Q_strnicmp( name, "origin", 6 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "clip", 4 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "hint", 4 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "skip", 4 ))
|
|
|
|
return NULL;
|
|
|
|
if( !Q_strnicmp( name, "translucent", 11 ))
|
|
|
|
return NULL;
|
2011-08-14 22:00:00 +02:00
|
|
|
if( !Q_strnicmp( name, "3dsky", 5 )) // xash-mod support :-)
|
2011-07-07 22:00:00 +02:00
|
|
|
return NULL;
|
2011-10-14 22:00:00 +02:00
|
|
|
if( !Q_strnicmp( name, "scroll", 6 ))
|
|
|
|
return NULL;
|
2011-07-07 22:00:00 +02:00
|
|
|
if( name[0] == '@' )
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
// last check ...
|
|
|
|
if( !Q_strnicmp( name, "null", 4 ))
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
for( table = detail_table; table && table->texname; table++ )
|
|
|
|
{
|
|
|
|
if( Q_stristr( name, table->texname ))
|
|
|
|
{
|
|
|
|
if(( table->lMin + table->lMax ) > 0 )
|
|
|
|
return va( table->detail, Com_RandomLong( table->lMin, table->lMax ));
|
|
|
|
return table->detail;
|
|
|
|
}
|
|
|
|
}
|
2011-08-14 22:00:00 +02:00
|
|
|
|
|
|
|
return NULL;
|
2011-07-07 22:00:00 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
void R_CreateDetailTexturesList( const char *filename )
|
|
|
|
{
|
|
|
|
file_t *detail_txt = NULL;
|
2013-12-01 21:00:00 +01:00
|
|
|
float xScale, yScale;
|
|
|
|
const char *detail_name;
|
|
|
|
texture_t *tex;
|
|
|
|
rgbdata_t *pic;
|
2011-07-07 22:00:00 +02:00
|
|
|
int i;
|
|
|
|
|
|
|
|
for( i = 0; i < cl.worldmodel->numtextures; i++ )
|
|
|
|
{
|
2013-12-01 21:00:00 +01:00
|
|
|
tex = cl.worldmodel->textures[i];
|
|
|
|
detail_name = R_DetailTextureForName( tex->name );
|
2011-07-07 22:00:00 +02:00
|
|
|
if( !detail_name ) continue;
|
|
|
|
|
|
|
|
// detailtexture detected
|
|
|
|
if( detail_name )
|
|
|
|
{
|
2011-07-22 22:00:00 +02:00
|
|
|
if( !detail_txt ) detail_txt = FS_Open( filename, "w", false );
|
2011-07-07 22:00:00 +02:00
|
|
|
if( !detail_txt )
|
|
|
|
{
|
|
|
|
MsgDev( D_ERROR, "Can't write %s\n", filename );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
2013-12-01 21:00:00 +01:00
|
|
|
pic = FS_LoadImage( va( "gfx/detail/%s", detail_name ), NULL, 0 );
|
|
|
|
|
|
|
|
if( pic )
|
|
|
|
{
|
|
|
|
xScale = (pic->width / tex->width) * gl_detailscale->value;
|
|
|
|
yScale = (pic->height / tex->height) * gl_detailscale->value;
|
|
|
|
FS_FreeImage( pic );
|
|
|
|
}
|
|
|
|
else xScale = yScale = 10.0f;
|
|
|
|
|
2011-07-07 22:00:00 +02:00
|
|
|
// store detailtexture description
|
2013-12-01 21:00:00 +01:00
|
|
|
FS_Printf( detail_txt, "%s detail/%s %.2f %.2f\n", tex->name, detail_name, xScale, yScale );
|
2011-07-07 22:00:00 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( detail_txt ) FS_Close( detail_txt );
|
|
|
|
}
|
|
|
|
|
|
|
|
void R_ParseDetailTextures( const char *filename )
|
|
|
|
{
|
|
|
|
char *afile, *pfile;
|
|
|
|
string token, texname, detail_texname;
|
|
|
|
float xScale, yScale;
|
|
|
|
texture_t *tex;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if( r_detailtextures->integer >= 2 && !FS_FileExists( filename, false ))
|
|
|
|
{
|
|
|
|
// use built-in generator for detail textures
|
|
|
|
R_CreateDetailTexturesList( filename );
|
|
|
|
}
|
|
|
|
|
|
|
|
afile = FS_LoadFile( filename, NULL, false );
|
|
|
|
if( !afile ) return;
|
|
|
|
|
|
|
|
pfile = afile;
|
|
|
|
|
|
|
|
// format: 'texturename' 'detailtexture' 'xScale' 'yScale'
|
|
|
|
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
|
|
|
|
{
|
|
|
|
texname[0] = '\0';
|
|
|
|
|
|
|
|
// read texname
|
|
|
|
if( token[0] == '{' )
|
|
|
|
{
|
|
|
|
// NOTE: COM_ParseFile handled some symbols seperately
|
|
|
|
// this code will be fix it
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
Q_strncat( texname, "{", sizeof( texname ));
|
|
|
|
Q_strncat( texname, token, sizeof( texname ));
|
|
|
|
}
|
|
|
|
else Q_strncpy( texname, token, sizeof( texname ));
|
|
|
|
|
|
|
|
// read detailtexture name
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
2015-05-28 23:00:00 +02:00
|
|
|
Q_snprintf( detail_texname, sizeof( detail_texname ), "gfx/%s", token );
|
2011-07-07 22:00:00 +02:00
|
|
|
|
|
|
|
// read scales
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
xScale = Q_atof( token );
|
|
|
|
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
yScale = Q_atof( token );
|
|
|
|
|
|
|
|
if( xScale <= 0.0f || yScale <= 0.0f )
|
|
|
|
continue;
|
|
|
|
|
|
|
|
// search for existing texture and uploading detail texture
|
|
|
|
for( i = 0; i < cl.worldmodel->numtextures; i++ )
|
|
|
|
{
|
|
|
|
tex = cl.worldmodel->textures[i];
|
|
|
|
|
|
|
|
if( Q_stricmp( tex->name, texname ))
|
|
|
|
continue;
|
|
|
|
|
2012-11-20 21:00:00 +01:00
|
|
|
tex->dt_texturenum = GL_LoadTexture( detail_texname, NULL, 0, TF_FORCE_COLOR, NULL );
|
2011-07-07 22:00:00 +02:00
|
|
|
|
|
|
|
// texture is loaded
|
|
|
|
if( tex->dt_texturenum )
|
|
|
|
{
|
|
|
|
gltexture_t *glt;
|
|
|
|
|
|
|
|
GL_SetTextureType( tex->dt_texturenum, TEX_DETAIL );
|
2012-02-08 21:00:00 +01:00
|
|
|
glt = R_GetTexture( tex->gl_texturenum );
|
2011-07-07 22:00:00 +02:00
|
|
|
glt->xscale = xScale;
|
|
|
|
glt->yscale = yScale;
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
Mem_Free( afile );
|
|
|
|
}
|
|
|
|
|
2012-11-20 21:00:00 +01:00
|
|
|
void R_ParseTexFilters( const char *filename )
|
|
|
|
{
|
|
|
|
char *afile, *pfile;
|
|
|
|
string token, texname;
|
|
|
|
dfilter_t *tf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
afile = FS_LoadFile( filename, NULL, false );
|
|
|
|
if( !afile ) return;
|
|
|
|
|
|
|
|
pfile = afile;
|
|
|
|
|
|
|
|
// format: 'texturename' 'filtername' 'factor' 'bias' 'blendmode' 'grayscale'
|
|
|
|
while(( pfile = COM_ParseFile( pfile, token )) != NULL )
|
|
|
|
{
|
|
|
|
imgfilter_t filter;
|
|
|
|
|
|
|
|
Q_memset( &filter, 0, sizeof( filter ));
|
|
|
|
Q_strncpy( texname, token, sizeof( texname ));
|
|
|
|
|
|
|
|
// parse filter
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
if( !Q_stricmp( token, "blur" ))
|
|
|
|
filter.filter = BLUR_FILTER;
|
|
|
|
else if( !Q_stricmp( token, "blur2" ))
|
|
|
|
filter.filter = BLUR_FILTER2;
|
|
|
|
else if( !Q_stricmp( token, "edge" ))
|
|
|
|
filter.filter = EDGE_FILTER;
|
|
|
|
else if( !Q_stricmp( token, "emboss" ))
|
|
|
|
filter.filter = EMBOSS_FILTER;
|
|
|
|
|
|
|
|
// reading factor
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
filter.factor = Q_atof( token );
|
|
|
|
|
|
|
|
// reading bias
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
filter.bias = Q_atof( token );
|
|
|
|
|
|
|
|
// reading blendFunc
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
if( !Q_stricmp( token, "modulate" ) || !Q_stricmp( token, "GL_MODULATE" ))
|
|
|
|
filter.blendFunc = GL_MODULATE;
|
|
|
|
else if( !Q_stricmp( token, "replace" ) || !Q_stricmp( token, "GL_REPLACE" ))
|
|
|
|
filter.blendFunc = GL_REPLACE;
|
|
|
|
else if( !Q_stricmp( token, "add" ) || !Q_stricmp( token, "GL_ADD" ))
|
|
|
|
filter.blendFunc = GL_ADD;
|
|
|
|
else if( !Q_stricmp( token, "decal" ) || !Q_stricmp( token, "GL_DECAL" ))
|
|
|
|
filter.blendFunc = GL_DECAL;
|
|
|
|
else if( !Q_stricmp( token, "blend" ) || !Q_stricmp( token, "GL_BLEND" ))
|
|
|
|
filter.blendFunc = GL_BLEND;
|
|
|
|
else if( !Q_stricmp( token, "add_signed" ) || !Q_stricmp( token, "GL_ADD_SIGNED" ))
|
|
|
|
filter.blendFunc = GL_ADD_SIGNED;
|
|
|
|
else MsgDev( D_WARN, "unknown blendFunc '%s' specified for texture '%s'\n", texname, token );
|
|
|
|
|
|
|
|
// reading flags
|
|
|
|
pfile = COM_ParseFile( pfile, token );
|
|
|
|
filter.flags = Q_atoi( token );
|
|
|
|
|
|
|
|
// make sure what factor is not zeroed
|
|
|
|
if( filter.factor == 0.0f )
|
|
|
|
{
|
|
|
|
MsgDev( D_WARN, "texfilter for texture %s has factor 0! Ignored\n", texname );
|
|
|
|
continue;
|
|
|
|
}
|
|
|
|
|
|
|
|
// check if already existed
|
|
|
|
for( i = 0; i < num_texfilters; i++ )
|
|
|
|
{
|
|
|
|
tf = tex_filters[i];
|
|
|
|
|
|
|
|
if( !Q_stricmp( tf->texname, texname ))
|
|
|
|
{
|
|
|
|
MsgDev( D_WARN, "texture %s has specified multiple filters! Ignored\n", texname );
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if( i != num_texfilters )
|
|
|
|
continue; // already specified
|
|
|
|
|
|
|
|
// allocate new texfilter
|
|
|
|
tf = Z_Malloc( sizeof( dfilter_t ));
|
|
|
|
tex_filters[num_texfilters++] = tf;
|
|
|
|
|
|
|
|
Q_strncpy( tf->texname, texname, sizeof( tf->texname ));
|
|
|
|
tf->filter = filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
MsgDev( D_INFO, "%i texture filters parsed\n", num_texfilters );
|
|
|
|
|
|
|
|
Mem_Free( afile );
|
|
|
|
}
|
|
|
|
|
|
|
|
imgfilter_t *R_FindTexFilter( const char *texname )
|
|
|
|
{
|
|
|
|
dfilter_t *tf;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for( i = 0; i < num_texfilters; i++ )
|
|
|
|
{
|
|
|
|
tf = tex_filters[i];
|
|
|
|
|
|
|
|
if( !Q_stricmp( tf->texname, texname ))
|
|
|
|
return &tf->filter;
|
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2013-10-23 22:00:00 +02:00
|
|
|
/*
|
|
|
|
=======================
|
|
|
|
R_ClearStaticEntities
|
|
|
|
|
|
|
|
e.g. by demo request
|
|
|
|
=======================
|
|
|
|
*/
|
|
|
|
void R_ClearStaticEntities( void )
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
2014-04-01 22:00:00 +02:00
|
|
|
if( host.type == HOST_DEDICATED )
|
|
|
|
return;
|
|
|
|
|
2013-10-23 22:00:00 +02:00
|
|
|
// clear out efrags in case the level hasn't been reloaded
|
|
|
|
for( i = 0; i < cl.worldmodel->numleafs; i++ )
|
|
|
|
cl.worldmodel->leafs[i+1].efrags = NULL;
|
|
|
|
|
|
|
|
clgame.numStatics = 0;
|
|
|
|
|
|
|
|
CL_ClearEfrags ();
|
|
|
|
}
|
|
|
|
|
2010-12-03 22:00:00 +01:00
|
|
|
void R_NewMap( void )
|
|
|
|
{
|
2011-09-03 22:00:00 +02:00
|
|
|
texture_t *tx;
|
2010-12-06 22:00:00 +01:00
|
|
|
int i;
|
|
|
|
|
2010-12-23 22:00:00 +01:00
|
|
|
R_ClearDecals(); // clear all level decals
|
|
|
|
|
2013-12-19 21:00:00 +01:00
|
|
|
// upload detailtextures
|
|
|
|
if( r_detailtextures->integer )
|
|
|
|
{
|
|
|
|
string mapname, filepath;
|
|
|
|
|
|
|
|
Q_strncpy( mapname, cl.worldmodel->name, sizeof( mapname ));
|
|
|
|
FS_StripExtension( mapname );
|
|
|
|
Q_sprintf( filepath, "%s_detail.txt", mapname );
|
|
|
|
|
|
|
|
R_ParseDetailTextures( filepath );
|
|
|
|
}
|
2010-12-06 22:00:00 +01:00
|
|
|
|
|
|
|
// clear out efrags in case the level hasn't been reloaded
|
|
|
|
for( i = 0; i < cl.worldmodel->numleafs; i++ )
|
2012-05-15 22:00:00 +02:00
|
|
|
cl.worldmodel->leafs[i+1].efrags = NULL;
|
2010-12-06 22:00:00 +01:00
|
|
|
|
|
|
|
tr.skytexturenum = -1;
|
|
|
|
r_viewleaf = r_oldviewleaf = NULL;
|
|
|
|
|
|
|
|
// clearing texture chains
|
|
|
|
for( i = 0; i < cl.worldmodel->numtextures; i++ )
|
|
|
|
{
|
|
|
|
if( !cl.worldmodel->textures[i] )
|
|
|
|
continue;
|
|
|
|
|
2011-09-03 22:00:00 +02:00
|
|
|
tx = cl.worldmodel->textures[i];
|
|
|
|
|
|
|
|
if( !Q_strncmp( tx->name, "sky", 3 ) && tx->width == 256 && tx->height == 128)
|
2010-12-06 22:00:00 +01:00
|
|
|
tr.skytexturenum = i;
|
|
|
|
|
2011-09-03 22:00:00 +02:00
|
|
|
tx->texturechain = NULL;
|
2010-12-06 22:00:00 +01:00
|
|
|
}
|
2011-07-07 22:00:00 +02:00
|
|
|
|
2013-12-19 21:00:00 +01:00
|
|
|
R_SetupSky( cl.refdef.movevars->skyName );
|
2011-07-07 22:00:00 +02:00
|
|
|
|
2013-12-19 21:00:00 +01:00
|
|
|
GL_BuildLightmaps ();
|
2010-12-03 22:00:00 +01:00
|
|
|
}
|