Merge 4483 update

This commit is contained in:
Alibek Omarov 2019-05-25 02:44:24 +03:00
commit b797e0af1a
49 changed files with 671 additions and 383 deletions

View File

@ -134,6 +134,8 @@ BRUSH MODELS
#define TEX_EXTRA_LIGHTMAP BIT( 3 ) // bsp31 legacy - using 8 texels per luxel instead of 16 texels per luxel
#define TEX_SCROLL BIT( 6 ) // Doom special FX
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
// ambient sound types
enum
{

View File

@ -8,7 +8,7 @@ typically expanded to rgba buffer
NOTE: number at end of pixelformat name it's a total bitscount e.g. PF_RGB_24 == PF_RGB_888
========================================================================
*/
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24)
#define ImageRAW( type ) (type == PF_RGBA_32 || type == PF_BGRA_32 || type == PF_RGB_24 || type == PF_BGR_24 || type == PF_LUMINANCE)
#define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2)
typedef enum
@ -20,6 +20,7 @@ typedef enum
PF_BGRA_32, // big endian RGBA (MacOS)
PF_RGB_24, // uncompressed dds or another 24-bit image
PF_BGR_24, // big-endian RGB (MacOS)
PF_LUMINANCE,
PF_DXT1, // s3tc DXT1 format
PF_DXT3, // s3tc DXT3 format
PF_DXT5, // s3tc DXT5 format

View File

@ -109,6 +109,15 @@ typedef struct
int reserved[32]; // just for future expansions or mod-makers
} mfaceinfo_t;
typedef struct
{
mplane_t *edges;
int numedges;
vec3_t origin;
vec_t radius; // for culling tests
int contents; // sky or solid
} mfacebevel_t;
typedef struct
{
float vecs[2][4]; // [s/t] unit vectors in world space.
@ -208,7 +217,7 @@ typedef struct mextrasurf_s
// begin userdata
struct msurface_s *lightmapchain; // lightmapped polys
struct mextrasurf_s *detailchain; // for detail textures drawing
struct mextrasurf_s *mirrorchain; // for gl_texsort drawing
mfacebevel_t *bevel; // for exact face traceline
struct mextrasurf_s *lumachain; // draw fullbrights
struct cl_entity_s *parent; // upcast to owner entity

View File

@ -23,7 +23,7 @@ GNU General Public License for more details.
#define ENGINE_PHYSICS_PUSHER_EXT (1<<3) // enable sets of improvements for MOVETYPE_PUSH physics
#define ENGINE_LARGE_LIGHTMAPS (1<<4) // change lightmap sizes from 128x128 to 1024x1024
#define ENGINE_COMPENSATE_QUAKE_BUG (1<<5) // compensate stupid quake bug (inverse pitch) for mods where this bug is fixed
// reserved
#define ENGINE_IMPROVED_LINETRACE (1<<6) // new traceline that tracing through alphatextures
#define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#endif//FEATURES_H

View File

@ -60,6 +60,7 @@ GNU General Public License for more details.
#define PARM_GLES_WRAPPER 35 //
#define PARM_STENCIL_ACTIVE 36
#define PARM_WATER_ALPHA 37
#define PARM_TEX_MEMORY 38 // returns total memory of uploaded texture in bytes
// skybox ordering
enum

View File

@ -405,7 +405,7 @@ int AVI_GetAudioChunk( movie_state_t *Avi, char *audiodata, int offset, int leng
for( i = 0; i < length; i++ )
audiodata[i] = 0;
return length;
// return length;
}
}

View File

@ -257,7 +257,7 @@ Return contents for point
*/
int CL_PointContents( const vec3_t p )
{
int cont = CL_TruePointContents( p );
int cont = PM_PointContents( clgame.pmove, p );
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
cont = CONTENTS_WATER;
@ -2201,7 +2201,7 @@ static int pfnPointContents( const float *p, int *truecontents )
{
int cont, truecont;
truecont = cont = CL_TruePointContents( p );
truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )

View File

@ -380,7 +380,7 @@ static HIMAGE pfnPIC_Load( const char *szPicName, const byte *image_buf, int ima
{
HIMAGE tx;
if( !szPicName || !*szPicName )
if( !COM_CheckString( szPicName ))
{
Con_Reportf( S_ERROR "CL_LoadImage: refusing to load image with empty name\n" );
return 0;
@ -932,7 +932,7 @@ pfnHostEndGame
static void pfnHostEndGame( const char *szFinalMessage )
{
if( !szFinalMessage ) szFinalMessage = "";
Host_EndGame( true, "%s", szFinalMessage );
Host_EndGame( false, "%s", szFinalMessage );
}
/*

View File

@ -2224,6 +2224,7 @@ void CL_ReadPackets( void )
// check resource for downloading and precache
CL_EstimateNeededResources();
CL_BatchResourceRequest( false );
cls.dl.doneregistering = false;
cls.dl.custom = true;
}

View File

@ -1532,7 +1532,7 @@ void CL_RegisterResources( sizebuf_t *msg )
ASSERT( clgame.entities != NULL );
clgame.entities->model = cl.worldmodel;
if( cls.state != ca_disconnected )
if( !cl.video_prepped && !cl.audio_prepped )
{
Con_Printf( "Setting up renderer...\n" );

View File

@ -472,7 +472,7 @@ void CL_AddLinksToPmove( frame_t *frame )
if( VectorIsNull( state->mins ) && VectorIsNull( state->maxs ))
continue;
if( state->solid == SOLID_NOT && state->skin < CONTENTS_EMPTY )
if( state->solid == SOLID_NOT && state->skin == CONTENTS_LADDER )
{
if( clgame.pmove->nummoveent >= MAX_MOVEENTS )
continue;
@ -588,67 +588,6 @@ void CL_SetSolidPlayers( int playernum )
}
}
/*
=============
CL_TruePointContents
=============
*/
int CL_TruePointContents( const vec3_t p )
{
int i, contents;
int oldhull;
hull_t *hull;
vec3_t test, offset;
physent_t *pe;
// sanity check
if( !p ) return CONTENTS_NONE;
oldhull = clgame.pmove->usehull;
// get base contents from world
contents = PM_HullPointContents( &cl.worldmodel->hulls[0], 0, p );
for( i = 0; i < clgame.pmove->nummoveent; i++ )
{
pe = &clgame.pmove->moveents[i];
if( pe->solid != SOLID_NOT ) // disabled ?
continue;
// only brushes can have special contents
if( !pe->model || pe->model->type != mod_brush )
continue;
// check water brushes accuracy
clgame.pmove->usehull = 2;
hull = PM_HullForBsp( pe, clgame.pmove, offset );
clgame.pmove->usehull = oldhull;
// offset the test point appropriately for this hull.
VectorSubtract( p, offset, test );
if( FBitSet( pe->model->flags, MODEL_HAS_ORIGIN ) && !VectorIsNull( pe->angles ))
{
matrix4x4 matrix;
Matrix4x4_CreateFromEntity( matrix, pe->angles, offset, 1.0f );
Matrix4x4_VectorITransform( matrix, p, test );
}
// test hull for intersection with this model
if( PM_HullPointContents( hull, hull->firstclipnode, test ) == CONTENTS_EMPTY )
continue;
// compare contents ranking
if( RankForContents( pe->skin ) > RankForContents( contents ))
contents = pe->skin; // new content has more priority
}
return contents;
}
/*
=============
CL_WaterEntity
@ -666,9 +605,9 @@ int CL_WaterEntity( const float *rgflPos )
oldhull = clgame.pmove->usehull;
for( i = 0; i < clgame.pmove->nummoveent; i++ )
for( i = 0; i < clgame.pmove->numphysent; i++ )
{
pe = &clgame.pmove->moveents[i];
pe = &clgame.pmove->physents[i];
if( pe->solid != SOLID_NOT ) // disabled ?
continue;
@ -793,7 +732,7 @@ static int pfnPointContents( float *p, int *truecontents )
{
int cont, truecont;
truecont = cont = CL_TruePointContents( p );
truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
@ -803,7 +742,7 @@ static int pfnPointContents( float *p, int *truecontents )
static int pfnTruePointContents( float *p )
{
return CL_TruePointContents( p );
return PM_TruePointContents( clgame.pmove, p );
}
static int pfnHullPointContents( struct hull_s *hull, int num, float *p )

View File

@ -144,7 +144,7 @@ void Con_SetColor_f( void )
{
vec3_t color;
switch( Cmd_Argc() )
switch( Cmd_Argc( ))
{
case 1:
Con_Printf( "\"con_color\" is %i %i %i\n", g_color_table[7][0], g_color_table[7][1], g_color_table[7][2] );

View File

@ -335,6 +335,9 @@ void Key_Unbindall_f( void )
if( keys[i].binding )
Key_SetBinding( i, "" );
}
// set some defaults
Key_SetBinding( K_ESCAPE, "cancelselect" );
}
/*

View File

@ -1006,9 +1006,8 @@ void Cmd_ExecuteString( char *text )
}
else
#endif // XASH_DEDICATED
if( text[0] != '@' && Cvar_VariableInteger( "host_gameloaded" ))
if( Cvar_VariableInteger( "host_gameloaded" ))
{
// commands with leading '@' are hidden system commands
Con_Printf( S_WARN "Unknown command \"%s\"\n", text );
}
}

View File

@ -885,7 +885,6 @@ void SV_StartSound( edict_t *ent, int chan, const char *sample, float vol, float
void SV_StartMusic( const char *curtrack, const char *looptrack, int position );
void SV_CreateDecal( sizebuf_t *msg, const float *origin, int decalIndex, int entityIndex, int modelIndex, int flags, float scale );
void Log_Printf( const char *fmt, ... ) _format( 1 );
struct sizebuf_s *SV_GetReliableDatagram( void );
void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 );
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... ) _format( 2 );

View File

@ -229,7 +229,7 @@ qboolean CRC32_File( dword *crcvalue, const char *filename )
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer )
{
char headbuf[256], buffer[1024];
char headbuf[1024], buffer[1024];
int i, num_bytes, lumplen;
int version, hdr_size;
dheader_t *header;

View File

@ -49,6 +49,8 @@ sysinfo_t SI;
CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
convar_t *host_serverstate;
convar_t *host_gameloaded;
convar_t *host_clientloaded;
convar_t *host_limitlocal;
@ -460,6 +462,7 @@ double Host_CalcFPS( void )
else
{
fps = host_maxfps->value;
if( fps == 0.0 ) fps = MAX_FPS;
fps = bound( MIN_FPS, fps, MAX_FPS );
}
@ -943,6 +946,7 @@ int EXPORT Host_Main( int argc, char **argv, const char *progname, int bChangeGa
Cmd_AddCommand ( "crash", Host_Crash_f, "a way to force a bus error for development reasons");
}
host_serverstate = Cvar_Get( "host_serverstate", "0", FCVAR_READ_ONLY, "displays current server state" );
host_maxfps = Cvar_Get( "fps_max", "72", FCVAR_ARCHIVE, "host fps upper limit" );
host_framerate = Cvar_Get( "host_framerate", "0", 0, "locks frame timing to this value in seconds" );
host_sleeptime = Cvar_Get( "sleeptime", "1", FCVAR_ARCHIVE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );

View File

@ -18,7 +18,6 @@ GNU General Public License for more details.
qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin )
{
uint bitmask;
word sAlpha;
byte *alpha;
int x, y, i, j;
@ -27,10 +26,8 @@ qboolean Image_CheckDXT3Alpha( dds_t *hdr, byte *fin )
{
for( x = 0; x < hdr->dwWidth; x += 4 )
{
alpha = fin;
fin += 8;
bitmask = ((uint *)fin)[1];
fin += 8;
alpha = fin + 8;
fin += 16;
for( j = 0; j < 4; j++ )
{
@ -138,11 +135,21 @@ void Image_DXTGetPixelFormat( dds_t *hdr )
}
else
{
if( bits == 32 )
switch( bits )
{
case 32:
image.type = PF_BGRA_32;
else if( bits == 24 )
break;
case 24:
image.type = PF_BGR_24;
else image.type = PF_UNKNOWN; // assume error;
break;
case 8:
image.type = PF_LUMINANCE;
break;
default:
image.type = PF_UNKNOWN;
break;
}
}
}
@ -162,6 +169,7 @@ size_t Image_DXTGetLinearSize( int type, int width, int height, int depth )
case PF_DXT3:
case PF_DXT5:
case PF_ATI2: return ((( width + 3 ) / 4 ) * (( height + 3 ) / 4 ) * depth * 16 );
case PF_LUMINANCE: return (width * height * depth);
case PF_BGR_24:
case PF_RGB_24: return (width * height * depth * 3);
case PF_BGRA_32:
@ -314,6 +322,9 @@ qboolean Image_LoadDDS( const char *name, const byte *buffer, fs_offset_t filesi
break;
}
if( image.type == PF_LUMINANCE )
ClearBits( image.flags, IMAGE_HAS_COLOR|IMAGE_HAS_ALPHA );
if( header.dwReserved1[1] != 0 )
{
// store texture reflectivity

View File

@ -72,17 +72,18 @@ static const cubepack_t load_cubemap[] =
// soul of ImageLib - table of image format constants
const bpc_desc_t PFDesc[] =
{
{PF_UNKNOWN, "raw", 0x1908, 0 },
{PF_INDEXED_24, "pal 24", 0x1908, 1 },
{PF_INDEXED_32, "pal 32", 0x1908, 1 },
{PF_RGBA_32, "RGBA 32",0x1908, 4 },
{PF_BGRA_32, "BGRA 32",0x80E1, 4 },
{PF_RGB_24, "RGB 24", 0x1908, 3 },
{PF_BGR_24, "BGR 24", 0x80E0, 3 },
{PF_DXT1, "DXT 1", 0x83F1, 4 },
{PF_DXT3, "DXT 3", 0x83F2, 4 },
{PF_DXT5, "DXT 5", 0x83F3, 4 },
{PF_ATI2, "ATI 2", 0x8837, 4 },
{ PF_UNKNOWN, "raw", 0x1908, 0 },
{ PF_INDEXED_24, "pal 24", 0x1908, 1 },
{ PF_INDEXED_32, "pal 32", 0x1908, 1 },
{ PF_RGBA_32, "RGBA 32",0x1908, 4 },
{ PF_BGRA_32, "BGRA 32",0x80E1, 4 },
{ PF_RGB_24, "RGB 24", 0x1908, 3 },
{ PF_BGR_24, "BGR 24", 0x80E0, 3 },
{ PF_LUMINANCE, "LUM 8", 0x1909, 1 },
{ PF_DXT1, "DXT 1", 0x83F1, 4 },
{ PF_DXT3, "DXT 3", 0x83F2, 4 },
{ PF_DXT5, "DXT 5", 0x83F3, 4 },
{ PF_ATI2, "ATI 2", 0x8837, 4 },
};
void Image_Reset( void )

View File

@ -150,11 +150,16 @@ void Image_Init( void )
image.loadformats = load_game;
image.saveformats = save_game;
break;
default: // all other instances not using imagelib
image.cmd_flags = 0;
case HOST_DEDICATED:
image.cmd_flags = 0;
image.loadformats = load_game;
image.saveformats = save_null;
break;
default: // all other instances not using imagelib
image.cmd_flags = 0;
image.loadformats = load_null;
image.saveformats = save_null;
break;
}
image.tempbuffer = NULL;

View File

@ -36,7 +36,7 @@ typedef struct leaflist_s
int count;
int maxcount;
qboolean overflowed;
short *list;
int *list;
vec3_t mins, maxs;
int topnode; // for overflows where each leaf can't be stored individually
} leaflist_t;
@ -668,7 +668,7 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
Mod_BoxLeafnums
==================
*/
static int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, short *list, int listsize, int *topnode )
static int Mod_BoxLeafnums( const vec3_t mins, const vec3_t maxs, int *list, int listsize, int *topnode )
{
leaflist_t ll;
@ -699,7 +699,7 @@ is potentially visible
*/
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits )
{
short leafList[MAX_BOX_LEAFS];
int leafList[MAX_BOX_LEAFS];
int i, count;
if( !visbits || !mins || !maxs )
@ -884,6 +884,59 @@ int Mod_SampleSizeForFace( msurface_t *surf )
return LM_SAMPLE_SIZE;
}
/*
==================
Mod_GetFaceContents
determine face contents by name
==================
*/
static int Mod_GetFaceContents( const char *name )
{
if( !Q_strnicmp( name, "SKY", 3 ))
return CONTENTS_SKY;
if( name[0] == '!' || name[0] == '*' )
{
if( !Q_strnicmp( name + 1, "lava", 4 ))
return CONTENTS_LAVA;
else if( !Q_strnicmp( name + 1, "slime", 5 ))
return CONTENTS_SLIME;
return CONTENTS_WATER; // otherwise it's water
}
if( !Q_strnicmp( name, "water", 5 ))
return CONTENTS_WATER;
return CONTENTS_SOLID;
}
/*
==================
Mod_GetFaceContents
determine face contents by name
==================
*/
static mvertex_t *Mod_GetVertexByNumber( model_t *mod, int surfedge )
{
int lindex;
medge_t *edge;
lindex = mod->surfedges[surfedge];
if( lindex > 0 )
{
edge = &mod->edges[lindex];
return &mod->vertexes[edge->v[0]];
}
else
{
edge = &mod->edges[-lindex];
return &mod->vertexes[edge->v[1]];
}
}
/*
==================
Mod_MakeNormalAxial
@ -1068,6 +1121,66 @@ static void Mod_CalcSurfaceBounds( msurface_t *surf )
VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin );
}
/*
=================
Mod_CreateFaceBevels
=================
*/
static void Mod_CreateFaceBevels( msurface_t *surf )
{
vec3_t delta, edgevec;
byte *facebevel;
vec3_t faceNormal;
mvertex_t *v0, *v1;
int contents;
int i, size;
vec_t radius;
mfacebevel_t *fb;
if( surf->texinfo && surf->texinfo->texture )
contents = Mod_GetFaceContents( surf->texinfo->texture->name );
else contents = CONTENTS_SOLID;
size = sizeof( mfacebevel_t ) + surf->numedges * sizeof( mplane_t );
facebevel = (byte *)Mem_Calloc( loadmodel->mempool, size );
fb = (mfacebevel_t *)facebevel;
facebevel += sizeof( mfacebevel_t );
fb->edges = (mplane_t *)facebevel;
fb->numedges = surf->numedges;
fb->contents = contents;
surf->info->bevel = fb;
if( FBitSet( surf->flags, SURF_PLANEBACK ))
VectorNegate( surf->plane->normal, faceNormal );
else VectorCopy( surf->plane->normal, faceNormal );
// compute face origin and plane edges
for( i = 0; i < surf->numedges; i++ )
{
mplane_t *dest = &fb->edges[i];
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
v1 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + (i + 1) % surf->numedges );
VectorSubtract( v1->position, v0->position, edgevec );
CrossProduct( faceNormal, edgevec, dest->normal );
VectorNormalize( dest->normal );
dest->dist = DotProduct( dest->normal, v0->position );
dest->type = PlaneTypeForNormal( dest->normal );
VectorAdd( fb->origin, v0->position, fb->origin );
}
VectorScale( fb->origin, 1.0f / surf->numedges, fb->origin );
// compute face radius
for( i = 0; i < surf->numedges; i++ )
{
v0 = Mod_GetVertexByNumber( loadmodel, surf->firstedge + i );
VectorSubtract( v0->position, fb->origin, delta );
radius = DotProduct( delta, delta );
fb->radius = Q_max( radius, fb->radius );
}
}
/*
=================
Mod_SetParent
@ -1520,7 +1633,7 @@ static void Mod_LoadEntities( dbspmodel_t *bmod )
{
byte *entpatch = NULL;
char token[MAX_TOKEN];
char wadstring[2048];
char wadstring[MAX_TOKEN];
string keyname;
char *pfile;
@ -1822,6 +1935,8 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
for( i = 0; i < loadmodel->numtextures; i++ )
{
int txFlags = 0;
if( in->dataofs[i] == -1 )
{
// create default texture (some mods requires this)
@ -1853,6 +1968,10 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
tx->width = mt->width;
tx->height = mt->height;
if( FBitSet( host.features, ENGINE_IMPROVED_LINETRACE ) && mt->name[0] == '{' )
SetBits( txFlags, TF_KEEP_SOURCE ); // Paranoia2 texture alpha-tracing
if( mt->offsets[0] > 0 )
{
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6);
@ -1904,7 +2023,7 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( FS_FileExists( texpath, false ))
{
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS );
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texpath, NULL, 0, TF_ALLOW_EMBOSS|txFlags );
bmod->wadlist.wadusage[j]++; // this wad are really used
break;
}
@ -1920,14 +2039,13 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( custom_palette ) size += sizeof( short ) + 768;
Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name );
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS );
tx->gl_texturenum = ref.dllFuncs.GL_LoadTexture( texname, (byte *)mt, size, TF_ALLOW_EMBOSS|txFlags );
}
// if texture is completely missed
if( !tx->gl_texturenum )
{
if( host.type != HOST_DEDICATED )
Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name );
Con_DPrintf( S_ERROR "unable to find %s.mip\n", mt->name );
tx->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
}
@ -2225,6 +2343,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
Mod_CalcSurfaceBounds( out );
Mod_CalcSurfaceExtents( out );
Mod_CreateFaceBevels( out );
// grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 )
@ -2816,7 +2935,7 @@ check lump for existing
*/
int Mod_CheckLump( const char *filename, const int lump, int *lumpsize )
{
file_t *f = FS_Open( filename, "rb", true );
file_t *f = FS_Open( filename, "rb", false );
byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr;
@ -2875,7 +2994,7 @@ reading random lump by user request
*/
int Mod_ReadLump( const char *filename, const int lump, void **lumpdata, int *lumpsize )
{
file_t *f = FS_Open( filename, "rb", true );
file_t *f = FS_Open( filename, "rb", false );
byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr;

View File

@ -749,6 +749,8 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAtt, float *origin, float *
{
mstudioattachment_t *pAtt;
vec3_t angles2;
matrix3x4 localPose;
matrix3x4 worldPose;
model_t *mod;
mod = SV_ModelHandle( e->v.modelindex );
@ -776,19 +778,15 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAtt, float *origin, float *
pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, angles2, e->v.origin, e->v.controller, e->v.blending, pAtt->bone, e );
// compute pos and angles
if( origin != NULL )
Matrix3x4_VectorTransform( studio_bones[pAtt->bone], pAtt->org, origin );
Matrix3x4_LoadIdentity( localPose );
Matrix3x4_SetOrigin( localPose, pAtt->org[0], pAtt->org[1], pAtt->org[2] );
Matrix3x4_ConcatTransforms( worldPose, studio_bones[pAtt->bone], localPose );
if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && origin != NULL && angles != NULL )
{
vec3_t forward, bonepos;
if( origin != NULL ) // origin is used always
Matrix3x4_OriginFromMatrix( worldPose, origin );
Matrix3x4_OriginFromMatrix( studio_bones[pAtt->bone], bonepos );
VectorSubtract( origin, bonepos, forward ); // make forward
VectorNormalizeFast( forward );
VectorAngles( forward, angles );
}
if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && angles != NULL )
Matrix3x4_AnglesFromMatrix( worldPose, angles );
}
/*
@ -807,7 +805,7 @@ void Mod_GetBonePosition( const edict_t *e, int iBone, float *origin, float *ang
pBlendAPI->SV_StudioSetupBones( mod, e->v.frame, e->v.sequence, e->v.angles, e->v.origin, e->v.controller, e->v.blending, iBone, e );
if( origin ) Matrix3x4_OriginFromMatrix( studio_bones[iBone], origin );
if( angles ) VectorAngles( studio_bones[iBone][0], angles ); // bone forward to angles
if( angles ) Matrix3x4_AnglesFromMatrix( studio_bones[iBone], angles );
}
/*

View File

@ -120,6 +120,11 @@ void Mod_FreeModel( model_t *mod )
===============================================================================
*/
/*
================
Mod_Init
================
*/
void Mod_Init( void )
{
com_studiocache = Mem_AllocPool( "Studio Cache" );

View File

@ -214,11 +214,11 @@ void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits )
}
}
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned )
void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned )
{
if( bSigned )
MSG_WriteSBitLong( sb, (int)data, numbits );
else MSG_WriteUBitLong( sb, data, numbits );
MSG_WriteSBitLong( sb, data, numbits );
else MSG_WriteUBitLong( sb, (uint)data, numbits );
}
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits )
@ -616,7 +616,6 @@ void MSG_ReadVec3Angles( sizebuf_t *sb, vec3_t fa )
fa[2] = MSG_ReadBitAngle( sb, 16 );
}
int MSG_ReadLong( sizebuf_t *sb )
{
return MSG_ReadSBitLong( sb, sizeof( int ) << 3 );

View File

@ -73,7 +73,7 @@ void MSG_Clear( sizebuf_t *sb );
void MSG_WriteOneBit( sizebuf_t *sb, int nValue );
void MSG_WriteUBitLong( sizebuf_t *sb, uint curData, int numbits );
void MSG_WriteSBitLong( sizebuf_t *sb, int data, int numbits );
void MSG_WriteBitLong( sizebuf_t *sb, uint data, int numbits, qboolean bSigned );
void MSG_WriteBitLong( sizebuf_t *sb, int data, int numbits, qboolean bSigned );
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits );
void MSG_WriteBitAngle( sizebuf_t *sb, float fAngle, int numbits );
void MSG_WriteBitFloat( sizebuf_t *sb, float val );

View File

@ -312,7 +312,7 @@ delta_info_t *Delta_FindStruct( const char *name )
{
int i;
if( !name || !name[0] )
if( !COM_CheckString( name ))
return NULL;
for( i = 0; i < NUM_FIELDS( dt_info ); i++ )
@ -431,8 +431,12 @@ qboolean Delta_AddField( const char *pStructName, const char *pName, int flags,
{
if( !Q_strcmp( pField->name, pName ))
{
Con_Reportf( "Delta_Add: %s->%s already existing\n", pStructName, pName );
return false; // field already exist
// update existed field
pField->flags = flags;
pField->bits = bits;
pField->multiplier = mul;
pField->post_multiplier = post_mul;
return true;
}
}
@ -474,7 +478,7 @@ void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pFiel
Assert( pField != NULL );
if( !pField->name || !*pField->name )
if( !COM_CheckString( pField->name ))
return; // not initialized ?
dt = Delta_FindStructByIndex( tableIndex );
@ -484,7 +488,7 @@ void Delta_WriteTableField( sizebuf_t *msg, int tableIndex, const delta_t *pFiel
Assert( nameIndex >= 0 && nameIndex < dt->maxFields );
MSG_BeginServerCmd( msg, svc_deltatable );
MSG_WriteUBitLong( msg, tableIndex, 4 ); // assume we support 16 network tables
MSG_WriteUBitLong( msg, tableIndex, 4 ); // assume we support 16 network tables
MSG_WriteUBitLong( msg, nameIndex, 8 ); // 255 fields by struct should be enough
MSG_WriteUBitLong( msg, pField->flags, 10 ); // flags are indicated various input types
MSG_WriteUBitLong( msg, pField->bits - 1, 5 ); // max received value is 32 (32 bit)
@ -626,7 +630,6 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt
}
// read delta-bits
if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL )
{
Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name );
@ -781,13 +784,8 @@ void Delta_InitFields( void )
Delta_ParseTable( &pfile, dt, encodeDll, encodeFunc );
}
Mem_Free( afile );
#if 0
// adding some required fields that user may forget or don't know how to specified
Delta_AddField( "event_t", "velocity[0]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[1]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
Delta_AddField( "event_t", "velocity[2]", DT_SIGNED | DT_FLOAT, 16, 8.0f, 1.0f );
#endif
}
void Delta_Init( void )
@ -894,73 +892,18 @@ Delta_ClampIntegerField
prevent data to out of range
=====================
*/
int Delta_ClampIntegerField( int iValue, qboolean bSigned, int bits )
int Delta_ClampIntegerField( delta_t *pField, int iValue, qboolean bSigned, int numbits )
{
switch( bits )
#ifdef _DEBUG
if( numbits < 32 && abs( iValue ) >= (uint)BIT( numbits ))
Msg( "%s %d overflow %d\n", pField->name, abs( iValue ), (uint)BIT( numbits ));
#endif
if( numbits < 32 )
{
case 1:
iValue = bound( 0, (byte)iValue, 1 );
break;
case 2:
if( bSigned ) iValue = bound( -2, (short)iValue, 1 );
else iValue = bound( 0, (word)iValue, 3 );
break;
case 3:
if( bSigned ) iValue = bound( -4, (short)iValue, 3 );
else iValue = bound( 0, (word)iValue, 7 );
break;
case 4:
if( bSigned ) iValue = bound( -8, (short)iValue, 7 );
else iValue = bound( 0, (word)iValue, 15 );
break;
case 5:
if( bSigned ) iValue = bound( -16, (short)iValue, 15 );
else iValue = bound( 0, (word)iValue, 31 );
break;
case 6:
if( bSigned ) iValue = bound( -32, (short)iValue, 31 );
else iValue = bound( 0, (word)iValue, 63 );
break;
case 7:
if( bSigned ) iValue = bound( -64, (short)iValue, 63 );
else iValue = bound( 0, (word)iValue, 127 );
break;
case 8:
if( bSigned ) iValue = bound( -128, (short)iValue, 127 );
else iValue = bound( 0, (word)iValue, 255 );
break;
case 9:
if( bSigned ) iValue = bound( -256, (short)iValue, 255 );
else iValue = bound( 0, (word)iValue, 511 );
break;
case 10:
if( bSigned ) iValue = bound( -512, (short)iValue, 511 );
else iValue = bound( 0, (word)iValue, 1023 );
break;
case 11:
if( bSigned ) iValue = bound( -1024, (short)iValue, 1023 );
else iValue = bound( 0, (word)iValue, 2047 );
break;
case 12:
if( bSigned ) iValue = bound( -2048, (short)iValue, 2047 );
else iValue = bound( 0, (word)iValue, 4095 );
break;
case 13:
if( bSigned ) iValue = bound( -4096, (short)iValue, 4095 );
else iValue = bound( 0, (word)iValue, 8191 );
break;
case 14:
if( bSigned ) iValue = bound( -8192, (short)iValue, 8191 );
else iValue = bound( 0, (word)iValue, 16383 );
break;
case 15:
if( bSigned ) iValue = bound( -16384, (short)iValue, 16383 );
else iValue = bound( 0, (word)iValue, 32767 );
break;
case 16:
if( bSigned ) iValue = bound( -32768, (short)iValue, 32767 );
else iValue = bound( 0, (word)iValue, 65535 );
break;
int signbits = bSigned ? (numbits - 1) : numbits;
int maxnum = BIT( signbits ) - 1;
int minnum = bSigned ? -maxnum : 0;
iValue = bound( minnum, iValue, maxnum );
}
return iValue; // clamped;
@ -1002,8 +945,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(byte *)((byte *)to + pField->offset );
}
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
@ -1020,8 +963,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(word *)((byte *)to + pField->offset );
}
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
@ -1038,8 +981,8 @@ qboolean Delta_CompareField( delta_t *pField, void *from, void *to, float timeba
toF = *(uint *)((byte *)to + pField->offset );
}
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits );
fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= pField->multiplier;
}
@ -1175,21 +1118,21 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
if( pField->flags & DT_BYTE )
{
iValue = *(byte *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_SHORT )
{
iValue = *(word *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_INTEGER )
{
iValue = *(uint *)((byte *)to + pField->offset );
iValue = Delta_ClampIntegerField( iValue, bSigned, pField->bits );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
@ -1197,6 +1140,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
{
flValue = *(float *)((byte *)to + pField->offset );
iValue = (int)(flValue * pField->multiplier);
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_ANGLE )
@ -1210,9 +1154,9 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
else if( pField->flags & DT_TIMEWINDOW_8 )
{
flValue = *(float *)((byte *)to + pField->offset );
flTime = Q_rint( timebase * 100.0f ) - Q_rint(flValue * 100.0f);
flTime = Q_rint( timebase * 100.0f ) - Q_rint( flValue * 100.0f );
iValue = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_TIMEWINDOW_BIG )
@ -1220,7 +1164,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
flValue = *(float *)((byte *)to + pField->offset );
flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier );
iValue = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
}
else if( pField->flags & DT_STRING )

View File

@ -36,6 +36,8 @@ qboolean PM_RecursiveHullCheck( hull_t *hull, int num, float p1f, float p2f, vec
pmtrace_t PM_PlayerTraceExt( playermove_t *pm, vec3_t p1, vec3_t p2, int flags, int numents, physent_t *ents, int ignore_pe, pfnIgnore pmFilter );
int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, pfnIgnore pmFilter );
int PM_HullPointContents( hull_t *hull, int num, const vec3_t p );
int PM_TruePointContents( playermove_t *pmove, const vec3_t p );
int PM_PointContents( playermove_t *pmove, const vec3_t p );
void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent );
//

View File

@ -16,84 +16,160 @@ GNU General Public License for more details.
#include "common.h"
#include "mathlib.h"
#include "pm_local.h"
#include "ref_common.h"
#define FRAC_EPSILON (1.0f / 32.0f)
typedef struct
{
float fraction;
int contents;
float fraction;
int contents;
msurface_t *surface;
} linetrace_t;
/*
==============
fix_coord
converts the reletive tex coords to absolute
==============
*/
static uint fix_coord( vec_t in, uint width )
{
if( in > 0 ) return (uint)in % width;
return width - ((uint)fabs( in ) % width);
}
/*
=============
SampleMiptex
fence texture testing
=============
*/
int PM_SampleMiptex( const msurface_t *surf, const vec3_t point )
{
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int contents;
vec_t ds, dt;
int x, y;
mtexinfo_t *tx;
texture_t *mt;
// fill the default contents
if( fb ) contents = fb->contents;
else contents = CONTENTS_SOLID;
if( !surf->texinfo || !surf->texinfo->texture )
return contents;
tx = surf->texinfo;
mt = tx->texture;
if( mt->name[0] != '{' )
return contents;
// TODO: this won't work under dedicated
// should we bring up imagelib and keep original buffers?
if( !Host_IsDedicated() )
{
const byte *data;
data = ref.dllFuncs.R_GetTextureOriginalBuffer( mt->gl_texturenum );
if( !data ) return contents; // original doesn't kept
ds = DotProduct( point, tx->vecs[0] ) + tx->vecs[0][3];
dt = DotProduct( point, tx->vecs[1] ) + tx->vecs[1][3];
// convert ST to real pixels position
x = fix_coord( ds, mt->width - 1 );
y = fix_coord( dt, mt->height - 1 );
ASSERT( x >= 0 && y >= 0 );
if( data[(mt->width * y) + x] == 255 )
return CONTENTS_EMPTY;
return CONTENTS_SOLID;
}
return contents;
}
/*
==================
PM_RecursiveSurfCheck
==================
*/
msurface_t *PM_RecursiveSurfCheck( model_t *model, mnode_t *node, vec3_t p1, vec3_t p2 )
msurface_t *PM_RecursiveSurfCheck( model_t *mod, mnode_t *node, vec3_t p1, vec3_t p2 )
{
float t1, t2, frac;
int side, ds, dt;
mplane_t *plane;
int i, side;
msurface_t *surf;
vec3_t mid;
int i;
loc0:
if( node->contents < 0 )
return NULL;
plane = node->plane;
t1 = PlaneDiff( p1, node->plane );
t2 = PlaneDiff( p2, node->plane );
if( plane->type < 3 )
if( t1 >= -FRAC_EPSILON && t2 >= -FRAC_EPSILON )
{
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
}
else
{
t1 = DotProduct( plane->normal, p1 ) - plane->dist;
t2 = DotProduct( plane->normal, p2 ) - plane->dist;
node = node->children[0];
goto loc0;
}
if( t1 >= 0.0f && t2 >= 0.0f )
return PM_RecursiveSurfCheck( model, node->children[0], p1, p2 );
if( t1 < 0.0f && t2 < 0.0f )
return PM_RecursiveSurfCheck( model, node->children[1], p1, p2 );
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{
node = node->children[1];
goto loc0;
}
side = (t1 < 0.0f);
frac = t1 / ( t1 - t2 );
if( frac < 0.0f ) frac = 0.0f;
if( frac > 1.0f ) frac = 1.0f;
frac = bound( 0.0f, frac, 1.0f );
VectorLerp( p1, frac, p2, mid );
side = (t1 < 0.0f);
// now this is weird.
surf = PM_RecursiveSurfCheck( model, node->children[side], p1, mid );
if( surf != NULL || ( t1 >= 0.0f && t2 >= 0.0f ) || ( t1 < 0.0f && t2 < 0.0f ))
{
if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
return surf;
}
surf = model->surfaces + node->firstsurface;
for( i = 0; i < node->numsurfaces; i++, surf++ )
// walk through real faces
for( i = 0; i < node->numsurfaces; i++ )
{
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] );
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
vec3_t delta;
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] )
if( !fb ) continue; // ???
VectorSubtract( mid, fb->origin, delta );
if( DotProduct( delta, delta ) >= fb->radius )
continue; // no intersection
for( j = 0; j < fb->numedges; j++ )
{
int s = ds - surf->texturemins[0];
int t = dt - surf->texturemins[1];
if( s <= surf->extents[0] && t <= surf->extents[1] )
return surf;
if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
break; // outside the bounds
}
if( j != fb->numedges )
continue; // we are outside the bounds of the facet
// hit the surface
contents = PM_SampleMiptex( surf, mid );
if( contents != CONTENTS_EMPTY )
return surf;
return NULL; // through the fence
}
return PM_RecursiveSurfCheck( model, node->children[side^1], mid, p2 );
return PM_RecursiveSurfCheck( mod, node->children[side^1], mid, p2 );
}
/*
@ -160,32 +236,34 @@ PM_TestLine_r
optimized trace for light gathering
==================
*/
int PM_TestLine_r( mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace )
int PM_TestLine_r( model_t *mod, mnode_t *node, vec_t p1f, vec_t p2f, const vec3_t start, const vec3_t stop, linetrace_t *trace )
{
float front, back;
float frac, midf;
int r, side;
int i, r, side;
vec3_t mid;
loc0:
if( node->contents < 0 )
trace->contents = node->contents;
if( node->contents == CONTENTS_SOLID )
return CONTENTS_SOLID;
if( node->contents == CONTENTS_SKY )
return CONTENTS_SKY;
if( node->contents < 0 )
{
// water, slime or lava interpret as empty
if( node->contents == CONTENTS_SOLID )
return CONTENTS_SOLID;
if( node->contents == CONTENTS_SKY )
return CONTENTS_SKY;
trace->fraction = 1.0f;
return CONTENTS_EMPTY;
}
front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, node->plane );
if( front >= -ON_EPSILON && back >= -ON_EPSILON )
if( front >= -FRAC_EPSILON && back >= -FRAC_EPSILON )
{
node = node->children[0];
goto loc0;
}
if( front < ON_EPSILON && back < ON_EPSILON )
if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{
node = node->children[1];
goto loc0;
@ -198,15 +276,54 @@ loc0:
VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac;
r = PM_TestLine_r( node->children[side], p1f, midf, start, mid, trace );
r = PM_TestLine_r( mod, node->children[side], p1f, midf, start, mid, trace );
if( r != CONTENTS_EMPTY )
{
trace->fraction = midf;
if( trace->surface == NULL )
trace->fraction = midf;
trace->contents = r;
return r;
}
return PM_TestLine_r( node->children[!side], midf, p2f, mid, stop, trace );
// walk through real faces
for( i = 0; i < node->numsurfaces; i++ )
{
msurface_t *surf = &mod->surfaces[node->firstsurface + i];
mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
vec3_t delta;
if( !fb ) continue;
VectorSubtract( mid, fb->origin, delta );
if( DotProduct( delta, delta ) >= fb->radius )
continue; // no intersection
for( j = 0; j < fb->numedges; j++ )
{
if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
break; // outside the bounds
}
if( j != fb->numedges )
continue; // we are outside the bounds of the facet
// hit the surface
contents = PM_SampleMiptex( surf, mid );
// fill the trace and out
trace->contents = contents;
trace->fraction = midf;
if( contents != CONTENTS_EMPTY )
trace->surface = surf;
return contents;
}
return PM_TestLine_r( mod, node->children[!side], midf, p2f, mid, stop, trace );
}
int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec3_t start, const vec3_t end, int flags )
@ -221,18 +338,19 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
trace.contents = CONTENTS_EMPTY;
trace.fraction = 1.0f;
trace.surface = NULL;
for( i = 0; i < numents; i++ )
{
pe = &ents[i];
if( i != 0 && ( flags & PM_WORLD_ONLY ))
if( i != 0 && FBitSet( flags, PM_WORLD_ONLY ))
break;
if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP )
continue;
if( pe->rendermode != kRenderNormal )
if( FBitSet( flags, PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal )
continue;
hull = &pe->model->hulls[0];
@ -257,8 +375,9 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
trace_bbox.contents = CONTENTS_EMPTY;
trace_bbox.fraction = 1.0f;
trace_bbox.surface = NULL;
PM_TestLine_r( &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox );
PM_TestLine_r( pe->model, &pe->model->nodes[hull->firstclipnode], 0.0f, 1.0f, start_l, end_l, &trace_bbox );
if( trace_bbox.contents != CONTENTS_EMPTY || trace_bbox.fraction < trace.fraction )
{
@ -267,4 +386,4 @@ int PM_TestLineExt( playermove_t *pmove, physent_t *ents, int numents, const vec
}
return trace.contents;
}
}

View File

@ -654,4 +654,82 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
}
return -1; // didn't hit anything
}
/*
=============
PM_TruePointContents
=============
*/
int PM_TruePointContents( playermove_t *pmove, const vec3_t p )
{
hull_t *hull = &pmove->physents[0].model->hulls[0];
if( hull )
{
return PM_HullPointContents( hull, hull->firstclipnode, p );
}
else
{
return CONTENTS_EMPTY;
}
}
/*
=============
PM_PointContents
=============
*/
int PM_PointContents( playermove_t *pmove, const vec3_t p )
{
int i, contents;
hull_t *hull;
vec3_t test;
physent_t *pe;
// sanity check
if( !p || !pmove->physents[0].model )
return CONTENTS_NONE;
// get base contents from world
contents = PM_HullPointContents( &pmove->physents[0].model->hulls[0], 0, p );
for( i = 1; i < pmove->numphysent; i++ )
{
pe = &pmove->physents[i];
if( pe->solid != SOLID_NOT ) // disabled ?
continue;
// only brushes can have special contents
if( !pe->model ) continue;
// check water brushes accuracy
hull = &pe->model->hulls[0];
if( FBitSet( pe->model->flags, MODEL_HAS_ORIGIN ) && !VectorIsNull( pe->angles ))
{
matrix4x4 matrix;
Matrix4x4_CreateFromEntity( matrix, pe->angles, pe->origin, 1.0f );
Matrix4x4_VectorITransform( matrix, p, test );
}
else
{
// offset the test point appropriately for this hull.
VectorSubtract( p, pe->origin, test );
}
// test hull for intersection with this model
if( PM_HullPointContents( hull, hull->firstclipnode, test ) == CONTENTS_EMPTY )
continue;
// compare contents ranking
if( RankForContents( pe->skin ) > RankForContents( contents ))
contents = pe->skin; // new content has more priority
}
return contents;
}

View File

@ -256,7 +256,7 @@ qboolean Mem_IsAllocatedExt( byte *poolptr, void *data )
void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline )
{
memheader_t *mem;
memheader_t *mem;
if( data == NULL )
Sys_Error( "Mem_CheckSentinels: data == NULL (sentinel check at %s:%i)\n", filename, fileline );
@ -269,7 +269,7 @@ void Mem_CheckHeaderSentinels( void *data, const char *filename, int fileline )
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 1 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );
}
if( *((byte *) mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 )
if( *((byte *)mem + sizeof(memheader_t) + mem->size) != MEMHEADER_SENTINEL2 )
{
mem->filename = Mem_CheckFilename( mem->filename ); // make sure what we don't crash var_args
Sys_Error( "Mem_CheckSentinels: trashed header sentinel 2 (block allocated at %s:%i, sentinel check at %s:%i)\n", mem->filename, mem->fileline, filename, fileline );

View File

@ -264,7 +264,6 @@ typedef struct sv_client_s
a program error, like an overflowed reliable buffer
=============================================================================
*/
// MAX_CHALLENGES is made large to prevent a denial
// of service attack that could cycle all of them
// out before legitimate users connected
@ -458,6 +457,7 @@ void SV_ProcessFile( sv_client_t *cl, const char *filename );
void SV_SendResource( resource_t *pResource, sizebuf_t *msg );
void SV_SendResourceList( sv_client_t *cl );
void SV_AddToMaster( netadr_t from, sizebuf_t *msg );
void Host_SetServerState( int state );
qboolean SV_IsSimulating( void );
qboolean SV_InitGame( void );
void SV_FreeClients( void );

View File

@ -16,6 +16,8 @@ GNU General Public License for more details.
#include "common.h"
#include "server.h"
extern convar_t *con_gamemaps;
/*
=================
SV_ClientPrintf
@ -282,7 +284,7 @@ void SV_NextMap_f( void )
int i, next;
search_t *t;
t = FS_Search( "maps/*.bsp", true, true ); // only in gamedir
t = FS_Search( "maps\\*.bsp", true, CVAR_TO_BOOL( con_gamemaps )); // only in gamedir
if( !t )
{
Con_Printf( "next map can't be found\n" );
@ -869,6 +871,7 @@ void SV_EntityInfo_f( void )
Con_Printf( "\n" );
}
}
/*
==================
SV_InitHostCommands

View File

@ -155,7 +155,7 @@ static void SV_AddEntitiesToPacket( edict_t *pViewEnt, edict_t *pClient, client_
if( fullvis ) continue; // portal ents will be added anyway, ignore recursion
// if its a portal entity, add everything visible from its camera position
// if it's a portal entity, add everything visible from its camera position
if( from_client && FBitSet( ent->v.effects, EF_MERGE_VISIBILITY ))
{
SetBits( sv.hostflags, SVF_MERGE_VISIBILITY );
@ -658,7 +658,7 @@ void SV_WriteEntitiesToClient( sv_client_t *cl, sizebuf_t *msg )
if( c_notsend > 0 )
Con_Printf( S_ERROR "Too many entities in visible packet list. Ignored %d entities\n", c_notsend );
cl->ignored_ents = c_notsend;
}
}
// if there were portals visible, there may be out of order entities
// in the list which will need to be resorted for the delta compression
@ -809,33 +809,18 @@ void SV_UpdateToReliableMessages( void )
continue; // reliables go to all connected or spawned
if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message ))
{
MSG_WriteBits( &cl->netchan.message, MSG_GetBuf( &sv.reliable_datagram ), MSG_GetNumBitsWritten( &sv.reliable_datagram ));
}
else
{
Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
}
else Netchan_CreateFragments( &cl->netchan, &sv.reliable_datagram );
if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.datagram ), MSG_GetNumBitsWritten( &sv.datagram ));
}
else
{
Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
}
else Con_DPrintf( S_WARN "Ignoring unreliable datagram for %s, would overflow\n", cl->name );
if( FBitSet( cl->flags, FCL_HLTV_PROXY ))
{
if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_datagram ));
}
else
{
Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
}
else Con_DPrintf( S_WARN "Ignoring spectator datagram for %s, would overflow\n", cl->name );
}
}

View File

@ -766,18 +766,18 @@ Create entity patch for selected map
*/
void SV_WriteEntityPatch( const char *filename )
{
int ver = -1, lumpofs = 0, lumplen = 0;
byte buf[MAX_SYSPATH]; // 1 kb
int lumpofs = 0, lumplen = 0;
byte buf[MAX_TOKEN]; // 1 kb
string bspfilename;
dheader_t *header;
file_t *f;
Q_strncpy( bspfilename, va( "maps/%s.bsp", filename ), sizeof( bspfilename ));
Q_strncpy( bspfilename, va( "maps/%s.bsp", filename ), sizeof( bspfilename ));
f = FS_Open( bspfilename, "rb", false );
if( !f ) return;
memset( buf, 0, MAX_SYSPATH );
FS_Read( f, buf, MAX_SYSPATH );
memset( buf, 0, MAX_TOKEN );
FS_Read( f, buf, MAX_TOKEN );
header = (dheader_t *)buf;
// check all the lumps and some other errors
@ -815,9 +815,9 @@ pfnMapIsValid use this
static char *SV_ReadEntityScript( const char *filename, int *flags )
{
string bspfilename, entfilename;
int ver = -1, lumpofs = 0, lumplen = 0;
int lumpofs = 0, lumplen = 0;
byte buf[MAX_TOKEN];
char *ents = NULL;
byte buf[1024];
dheader_t *header;
size_t ft1, ft2;
file_t *f;
@ -829,8 +829,8 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
if( !f ) return NULL;
SetBits( *flags, MAP_IS_EXIST );
memset( buf, 0, MAX_SYSPATH );
FS_Read( f, buf, MAX_SYSPATH );
memset( buf, 0, MAX_TOKEN );
FS_Read( f, buf, MAX_TOKEN );
header = (dheader_t *)buf;
// check all the lumps and some other errors
@ -848,7 +848,7 @@ static char *SV_ReadEntityScript( const char *filename, int *flags )
// check for entfile too
Q_strncpy( entfilename, va( "maps/%s.ent", filename ), sizeof( entfilename ));
// make sure what entity patch is never than bsp
// make sure what entity patch is newer than bsp
ft1 = FS_FileTime( bspfilename, false );
ft2 = FS_FileTime( entfilename, true );
@ -889,7 +889,7 @@ int SV_MapIsValid( const char *filename, const char *spawn_entity, const char *l
if( ents )
{
qboolean need_landmark = Q_strlen( landmark_name ) > 0 ? true : false;
char token[2048];
char token[MAX_TOKEN];
string check_name;
// g-cont. in-dev mode we can entering on map even without "info_player_start"
@ -1294,6 +1294,7 @@ pfnSetModel
void pfnSetModel( edict_t *e, const char *m )
{
char name[MAX_QPATH];
qboolean found = false;
model_t *mod;
int i;
@ -1306,19 +1307,17 @@ void pfnSetModel( edict_t *e, const char *m )
if( COM_CheckString( name ))
{
qboolean notfound = true;
// check to see if model was properly precached
for( i = 1; i < MAX_MODELS && sv.model_precache[i][0]; i++ )
{
if( !Q_stricmp( sv.model_precache[i], name ))
{
notfound = false;
found = true;
break;
}
}
if( notfound )
if( !found )
{
Con_Printf( S_ERROR "Failed to set model %s: was not precached\n", name );
return;
@ -2800,7 +2799,7 @@ void pfnWriteString( const char *src )
{
static char string[MAX_USERMSG_LENGTH];
int len = Q_strlen( src ) + 1;
int rem = rem = sizeof( string ) - 1;
int rem = sizeof( string ) - 1;
char *dst;
if( len == 1 )
@ -4756,7 +4755,7 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent )
// keynames with a leading underscore are used for
// utility comments and are immediately discarded by engine
if( keyname[0] == '_' && Q_strcmp( keyname, "_light" ))
if( FBitSet( world.flags, FWORLD_SKYSPHERE ) && keyname[0] == '_' )
continue;
// ignore attempts to set value ""
@ -4859,7 +4858,7 @@ qboolean SV_ParseEdict( char **pfile, edict_t *ent )
Mem_Free( pkvd[i].szValue );
}
if( classname )
if( classname && Mem_IsAllocatedExt( host.mempool, classname ))
Mem_Free( classname );
return true;

View File

@ -136,7 +136,6 @@ int SV_SoundIndex( const char *filename )
char name[MAX_QPATH];
int i;
// don't precache sentence names!
if( !COM_CheckString( filename ))
return 0;
@ -264,7 +263,7 @@ int SV_GenericIndex( const char *filename )
================
SV_ModelHandle
register unique model for a server and client
get model by handle
================
*/
model_t *SV_ModelHandle( int modelindex )
@ -300,6 +299,13 @@ void SV_ReadResourceList( const char *filename )
Mem_Free( afile );
}
/*
================
SV_CreateGenericResources
loads external resource list
================
*/
void SV_CreateGenericResources( void )
{
string filename;
@ -312,6 +318,13 @@ void SV_CreateGenericResources( void )
SV_ReadResourceList( "reslist.txt" );
}
/*
================
SV_CreateResourceList
add resources to common list
================
*/
void SV_CreateResourceList( void )
{
qboolean ffirstsent = false;
@ -582,7 +595,7 @@ void SV_ActivateServer( int runPhysics )
Mod_FreeUnused ();
host.movevars_changed = true;
sv.state = ss_active;
Host_SetServerState( ss_active );
Con_DPrintf( "level loaded at %.2f sec\n", Sys_DoubleTime() - svs.timestart );
@ -620,7 +633,7 @@ void SV_DeactivateServer( void )
svgame.globals->time = sv.time;
svgame.dllFuncs.pfnServerDeactivate();
sv.state = ss_dead;
Host_SetServerState( ss_dead );
SV_FreeEdicts ();
@ -833,7 +846,7 @@ qboolean SV_SpawnServer( const char *mapname, const char *startspot, qboolean ba
COM_FileBase( mapname, sv.name );
// precache and static commands can be issued during map initialization
sv.state = ss_loading;
Host_SetServerState( ss_loading );
if( startspot )
Q_strncpy( sv.startspot, startspot, sizeof( sv.startspot ));

View File

@ -152,6 +152,9 @@ send updates to client if changed
*/
void SV_UpdateMovevars( qboolean initialize )
{
if( sv.state == ss_dead )
return;
if( !initialize && !host.movevars_changed )
return;
@ -260,6 +263,13 @@ void SV_CheckCmdTimes( void )
}
}
/*
=================
SV_ProcessFile
process incoming file (customization)
=================
*/
void SV_ProcessFile( sv_client_t *cl, const char *filename )
{
customization_t *pList;
@ -549,11 +559,6 @@ qboolean SV_IsSimulating( void )
return false;
}
/*
=================
SV_RunGameFrame
=================
*/
/*
=================
SV_RunGameFrame
@ -639,6 +644,17 @@ void Host_ServerFrame( void )
Master_Heartbeat ();
}
/*
==================
Host_SetServerState
==================
*/
void Host_SetServerState( int state )
{
Cvar_FullSet( "host_serverstate", va( "%i", state ), FCVAR_READ_ONLY );
sv.state = state;
}
//============================================================================
/*
@ -877,7 +893,7 @@ to totally exit after returning from this function.
*/
void SV_FinalMessage( const char *message, qboolean reconnect )
{
byte msg_buf[64];
byte msg_buf[1024];
sv_client_t *cl;
sizebuf_t msg;
int i;
@ -984,6 +1000,9 @@ void SV_Shutdown( const char *finalmsg )
SV_FreeClients();
svs.maxclients = 0;
// release all models
Mod_FreeAll();
HPAK_FlushHostQueue();
Log_Printf( "Server shutdown\n" );
Log_Close();

View File

@ -73,7 +73,7 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
if( FBitSet( ed->v.flags, FL_CLIENT ))
{
// client
SV_GetTrueOrigin( &svs.clients[pe->info - 1], pe->info, pe->origin );
SV_GetTrueOrigin( sv.current_client, pe->info, pe->origin );
if( FBitSet( ed->v.flags, FL_FAKECLIENT )) // fakeclients have client flag too
{
// bot
@ -306,7 +306,7 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
model_t *mod;
physent_t *pe;
// get water edicts
// get ladder edicts
for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
{
next = l->next;
@ -362,6 +362,11 @@ static void pfnParticle( const float *origin, int color, float life, int zpos, i
MSG_WriteByte( &sv.reliable_datagram, bound( 0, life * 8, 255 ));
}
int SV_TestLine( const vec3_t start, const vec3_t end, int flags )
{
return PM_TestLineExt( svgame.pmove, svgame.pmove->physents, svgame.pmove->numphysent, start, end, flags );
}
static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
{
return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL );
@ -390,7 +395,7 @@ static int pfnPointContents( float *p, int *truecontents )
{
int cont, truecont;
truecont = cont = SV_TruePointContents( p );
truecont = cont = PM_PointContents( svgame.pmove, p );
if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN )
@ -400,7 +405,7 @@ static int pfnPointContents( float *p, int *truecontents )
static int pfnTruePointContents( float *p )
{
return SV_TruePointContents( p );
return PM_TruePointContents( svgame.pmove, p );
}
static int pfnHullPointContents( struct hull_s *hull, int num, float *p )
@ -778,11 +783,11 @@ static void SV_FinishPMove( playermove_t *pmove, sv_client_t *cl )
if( pmove->onground == -1 )
{
clent->v.flags &= ~FL_ONGROUND;
ClearBits( clent->v.flags, FL_ONGROUND );
}
else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent )
{
clent->v.flags |= FL_ONGROUND;
SetBits( clent->v.flags, FL_ONGROUND );
clent->v.groundentity = EDICT_NUM( pmove->physents[pmove->onground].info );
}
@ -903,10 +908,7 @@ void SV_SetupMoveInterpolant( sv_client_t *cl )
if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos ))
lerp->nointerp = true;
}
else
{
lerp->firstframe = true;
}
else lerp->firstframe = true;
VectorCopy( state->origin, lerp->finalpos );
}
@ -1004,10 +1006,10 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
oldlerp = &svgame.interp[i];
if( VectorCompare( oldlerp->oldpos, oldlerp->newpos ) || !oldlerp->moving )
if( VectorCompareEpsilon( oldlerp->oldpos, oldlerp->newpos, ON_EPSILON ))
continue; // they didn't actually move.
if( !oldlerp->active )
if( !oldlerp->moving || !oldlerp->active )
continue;
if( VectorCompare( oldlerp->curpos, check->edict->v.origin ))
@ -1057,9 +1059,7 @@ void SV_RunCmd( sv_client_t *cl, usercmd_t *ucmd, int random_seed )
}
if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
SV_SetupMoveInterpolant( cl );
}
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );

View File

@ -1113,6 +1113,7 @@ or custom physics implementation
*/
void SV_CustomClipMoveToEntity( edict_t *ent, const vec3_t start, vec3_t mins, vec3_t maxs, const vec3_t end, trace_t *trace )
{
// initialize custom trace
memset( trace, 0, sizeof( trace_t ));
VectorCopy( end, trace->endpos );
trace->allsolid = true;
@ -1256,7 +1257,7 @@ static void SV_ClipToLinks( areanode_t *node, moveclip_t *clip )
if( !SV_ClipToEntity( touch, clip ))
return; // trace.allsoild
}
// recurse down both sides
if( node->axis == -1 ) return;
@ -1288,7 +1289,7 @@ static void SV_ClipToPortals( areanode_t *node, moveclip_t *clip )
if( !SV_ClipToEntity( touch, clip ))
return; // trace.allsoild
}
// recurse down both sides
if( node->axis == -1 ) return;

View File

@ -485,7 +485,7 @@ void R_DrawDisk( vec3_t source, vec3_t delta, float width, float scale, float fr
scale = scale * length;
// clamp the beam width
w = fmod( freq, width ) * delta[2];
w = fmod( freq, width * 0.1f ) * delta[2];
// NOTE: we must force the degenerate triangles to be on the edge
for( i = 0; i < segments; i++ )

View File

@ -75,7 +75,7 @@ static void R_DecalUnlink( decal_t *pdecal )
else
{
tmp = pdecal->psurface->pdecals;
if( !tmp ) gEngfuncs.Host_Error( "D_DecalUnlink: bad decal list\n" );
if( !tmp ) gEngfuncs.Host_Error( "R_DecalUnlink: bad decal list\n" );
while( tmp->pnext )
{

View File

@ -111,6 +111,9 @@ void GL_ApplyTextureParams( gl_texture_t *tex )
{
vec4_t border = { 0.0f, 0.0f, 0.0f, 1.0f };
if( !glw_state.initialized )
return;
Assert( tex != NULL );
// set texture filter
@ -347,6 +350,9 @@ static size_t GL_CalcImageSize( pixformat_t format, int width, int height, int d
switch( format )
{
case PF_LUMINANCE:
size = width * height * depth;
break;
case PF_RGB_24:
case PF_BGR_24:
size = width * height * depth * 3;
@ -1086,6 +1092,10 @@ static qboolean GL_UploadTexture( gl_texture_t *tex, rgbdata_t *pic )
qboolean normalMap;
const byte *bufend;
// dedicated server
if( !glw_state.initialized )
return true;
Assert( pic != NULL );
Assert( tex != NULL );
@ -1211,6 +1221,7 @@ do specified actions on pixels
*/
static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
{
float emboss_scale = 0.0f;
uint img_flags = 0;
// force upload texture as RGB or RGBA (detail textures requires this)
@ -1256,8 +1267,12 @@ static void GL_ProcessImage( gl_texture_t *tex, rgbdata_t *pic )
if( pic->type == PF_INDEXED_24 || pic->type == PF_INDEXED_32 )
img_flags |= IMAGE_FORCE_RGBA;
// dedicated server doesn't register this variable
if( gl_emboss_scale != NULL )
emboss_scale = gl_emboss_scale->value;
// processing image before uploading (force to rgba, make luma etc)
if( pic->buffer ) gEngfuncs.Image_Process( &pic, 0, 0, img_flags, gl_emboss_scale->value );
if( pic->buffer ) gEngfuncs.Image_Process( &pic, 0, 0, img_flags, emboss_scale );
if( FBitSet( tex->flags, TF_LUMINANCE ))
ClearBits( pic->flags, IMAGE_HAS_COLOR );
@ -1271,7 +1286,7 @@ GL_CheckTexName
*/
qboolean GL_CheckTexName( const char *name )
{
if( !COM_CheckString( name ) || !glw_state.initialized )
if( !COM_CheckString( name ))
return false;
// because multi-layered textures can exceed name string
@ -1386,7 +1401,8 @@ static void GL_DeleteTexture( gl_texture_t *tex )
if( tex->original )
gEngfuncs.FS_FreeImage( tex->original );
pglDeleteTextures( 1, &tex->texnum );
if( glw_state.initialized )
pglDeleteTextures( 1, &tex->texnum );
memset( tex, 0, sizeof( *tex ));
}
@ -1644,6 +1660,7 @@ int GL_LoadTextureFromBuffer( const char *name, rgbdata_t *pic, texFlags_t flags
}
GL_ProcessImage( tex, pic );
if( !GL_UploadTexture( tex, pic ))
{
memset( tex, 0, sizeof( gl_texture_t ));
@ -1770,8 +1787,7 @@ GL_FreeTexture
void GL_FreeTexture( GLenum texnum )
{
// number 0 it's already freed
if( texnum <= 0 || !glw_state.initialized )
return;
if( texnum <= 0 ) return;
GL_DeleteTexture( &gl_textures[texnum] );
}
@ -1828,6 +1844,23 @@ void GL_ProcessTexture( int texnum, float gamma, int topColor, int bottomColor )
gEngfuncs.FS_FreeImage( pic );
}
/*
================
GL_TexMemory
return size of all uploaded textures
================
*/
int GL_TexMemory( void )
{
int i, total = 0;
for( i = 0; i < gl_numTextures; i++ )
total += gl_textures[i].size;
return total;
}
/*
==============================================================================

View File

@ -235,7 +235,6 @@ typedef struct
int recursion_level;
int max_recursion;
byte visbytes[(MAX_MAP_LEAFS+7)/8]; // member custom PVS
int lightstylevalue[MAX_LIGHTSTYLES]; // value 0 - 65536
int block_size; // lightmap blocksize
@ -360,6 +359,7 @@ void R_InitDlightTexture( void );
void R_TextureList_f( void );
void R_InitImages( void );
void R_ShutdownImages( void );
int GL_TexMemory( void );
//
// gl_rlight.c
@ -682,6 +682,7 @@ typedef struct
GLboolean texIdentityMatrix[MAX_TEXTURE_UNITS];
GLint genSTEnabled[MAX_TEXTURE_UNITS]; // 0 - disabled, OR 1 - S, OR 2 - T, OR 4 - R
GLint texCoordArrayMode[MAX_TEXTURE_UNITS]; // 0 - disabled, 1 - enabled, 2 - cubemap
GLint isFogEnabled;
int faceCull;

View File

@ -644,13 +644,13 @@ void GL_InitExtensionsBigGL()
}
GL_CheckExtension( "GL_ARB_texture_non_power_of_two", NULL, "gl_texture_npot", GL_ARB_TEXTURE_NPOT_EXT );
GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, "gl_dds_hardware_support", GL_TEXTURE_COMPRESSION_EXT );
GL_CheckExtension( "GL_ARB_texture_compression", texturecompressionfuncs, "gl_texture_dxt_compression", GL_TEXTURE_COMPRESSION_EXT );
GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT );
if( !GL_Support( GL_CLAMPTOEDGE_EXT ))
GL_CheckExtension( "GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT );
glConfig.max_texture_anisotropy = 0.0f;
GL_CheckExtension( "GL_EXT_texture_filter_anisotropic", NULL, "gl_ext_anisotropic_filter", GL_ANISOTROPY_EXT );
GL_CheckExtension( "GL_EXT_texture_filter_anisotropic", NULL, "gl_texture_anisotropic_filter", GL_ANISOTROPY_EXT );
if( GL_Support( GL_ANISOTROPY_EXT ))
pglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.max_texture_anisotropy );
@ -663,12 +663,13 @@ void GL_InitExtensionsBigGL()
if( GL_Support( GL_TEXTURE_LOD_BIAS ))
pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glConfig.max_texture_lod_bias );
GL_CheckExtension( "GL_ARB_texture_border_clamp", NULL, "gl_ext_texborder_clamp", GL_CLAMP_TEXBORDER_EXT );
GL_CheckExtension( "GL_ARB_depth_texture", NULL, "gl_depthtexture", GL_DEPTH_TEXTURE );
GL_CheckExtension( "GL_ARB_texture_float", NULL, "gl_arb_texture_float", GL_ARB_TEXTURE_FLOAT_EXT );
GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_arb_depth_float", GL_ARB_DEPTH_FLOAT_EXT );
GL_CheckExtension( "GL_ARB_texture_border_clamp", NULL, NULL, GL_CLAMP_TEXBORDER_EXT );
GL_CheckExtension( "GL_ARB_depth_texture", NULL, NULL, GL_DEPTH_TEXTURE );
GL_CheckExtension( "GL_ARB_texture_float", NULL, "gl_texture_float", GL_ARB_TEXTURE_FLOAT_EXT );
GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_texture_depth_float", GL_ARB_DEPTH_FLOAT_EXT );
GL_CheckExtension( "GL_EXT_gpu_shader4", NULL, NULL, GL_EXT_GPU_SHADER4 ); // don't confuse users
GL_CheckExtension( "GL_ARB_shading_language_100", NULL, "gl_glslprogram", GL_SHADER_GLSL100_EXT );
GL_CheckExtension( "GL_ARB_shading_language_100", NULL, NULL, GL_SHADER_GLSL100_EXT );
GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", GL_ARB_VERTEX_BUFFER_OBJECT_EXT );
// rectangle textures support

View File

@ -41,18 +41,14 @@ static int R_RankForRenderMode( int rendermode )
void R_AllowFog( qboolean allowed )
{
static int isFogEnabled;
if( allowed )
{
if( isFogEnabled )
if( glState.isFogEnabled )
pglEnable( GL_FOG );
}
else
{
isFogEnabled = pglIsEnabled( GL_FOG );
if( isFogEnabled )
if( glState.isFogEnabled )
pglDisable( GL_FOG );
}
}
@ -498,6 +494,9 @@ static void R_SetupFrame( void )
// setup viewplane dist
RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward );
// NOTE: this request is the fps-killer on some NVidia drivers
glState.isFogEnabled = pglIsEnabled( GL_FOG );
if( !gl_nosort->value )
{
// sort translucents entities by rendermode and distance
@ -701,7 +700,11 @@ static void R_CheckFog( void )
// in some cases waterlevel jumps from 3 to 1. Catch it
RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL );
RI.cached_contents = CONTENTS_EMPTY;
if( !RI.fogCustom ) pglDisable( GL_FOG );
if( !RI.fogCustom )
{
glState.isFogEnabled = false;
pglDisable( GL_FOG );
}
}
return;
}

View File

@ -156,6 +156,7 @@ void R_NewMap( void )
for( i = 0; i < WORLDMODEL->numleafs; i++ )
WORLDMODEL->leafs[i+1].efrags = NULL;
glState.isFogEnabled = false;
tr.skytexturenum = -1;
tr.max_recursion = 0;
pglDisable( GL_FOG );

View File

@ -287,9 +287,6 @@ void CL_DrawParticlesExternal( const ref_viewpass_t *rvp, qboolean trans_pass, f
R_SetupRefParams( rvp );
R_SetupFrustum();
R_SetupGL( false ); // don't touch GL-states
// setup PVS for frame
memcpy( RI.visbytes, tr.visbytes, gpGlobals->visbytes );
tr.frametime = frametime;
gEngfuncs.CL_DrawEFX( frametime, trans_pass );

View File

@ -205,7 +205,7 @@ void GL_SetupFogColorForSurfaces( void )
vec3_t fogColor;
float factor, div;
if( !pglIsEnabled( GL_FOG ))
if( !glState.isFogEnabled)
return;
if( RI.currententity && RI.currententity->curstate.rendermode == kRenderTransTexture )
@ -225,7 +225,7 @@ void GL_SetupFogColorForSurfaces( void )
void GL_ResetFogColor( void )
{
// restore fog here
if( pglIsEnabled( GL_FOG ))
if( glState.isFogEnabled )
pglFogfv( GL_FOG_COLOR, RI.fogColor );
}
@ -1155,7 +1155,7 @@ void R_RenderBrushPoly( msurface_t *fa, int cull_type )
if( CVAR_TO_BOOL( r_detailtextures ))
{
if( pglIsEnabled( GL_FOG ))
if( glState.isFogEnabled )
{
// don't apply detail textures for windows in the fog
if( RI.currententity->curstate.rendermode != kRenderTransTexture )

View File

@ -1302,8 +1302,6 @@ StudioCalcAttachments
static void R_StudioCalcAttachments( void )
{
mstudioattachment_t *pAtt;
vec3_t forward, bonepos;
vec3_t localOrg, localAng;
int i;
// calculate attachment points
@ -1312,11 +1310,6 @@ static void R_StudioCalcAttachments( void )
for( i = 0; i < Q_min( MAXSTUDIOATTACHMENTS, m_pStudioHeader->numattachments ); i++ )
{
Matrix3x4_VectorTransform( g_studio.lighttransform[pAtt[i].bone], pAtt[i].org, RI.currententity->attachment[i] );
VectorSubtract( RI.currententity->attachment[i], RI.currententity->origin, localOrg );
Matrix3x4_OriginFromMatrix( g_studio.lighttransform[pAtt[i].bone], bonepos );
VectorSubtract( localOrg, bonepos, forward ); // make forward
VectorNormalizeFast( forward );
VectorAngles( forward, localAng );
}
}
@ -3826,7 +3819,7 @@ static void R_StudioLoadTexture( model_t *mod, studiohdr_t *phdr, mstudiotexture
gEngfuncs.Image_SetMDLPointer((byte *)phdr + ptexture->index);
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768;
if( FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_LOAD_DELUXEDATA ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED ))
if( FBitSet( ENGINE_GET_PARM( PARM_FEATURES ), ENGINE_IMPROVED_LINETRACE ) && FBitSet( ptexture->flags, STUDIO_NF_MASKED ))
flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing
// build the texname

View File

@ -268,7 +268,7 @@ void TriFog( float flFogColor[3], float flStart, float flEnd, int bOn )
// check for invalid parms
if( flEnd <= flStart )
{
RI.fogCustom = false;
glState.isFogEnabled = RI.fogCustom = false;
pglDisable( GL_FOG );
return;
}