Browse Source

Merge 4483 update

pull/2/head
Alibek Omarov 6 years ago
parent
commit
b797e0af1a
  1. 2
      common/bspfile.h
  2. 3
      common/com_image.h
  3. 11
      common/com_model.h
  4. 2
      common/enginefeatures.h
  5. 1
      common/render_api.h
  6. 2
      engine/client/avi/avi_win.c
  7. 4
      engine/client/cl_game.c
  8. 4
      engine/client/cl_gameui.c
  9. 1
      engine/client/cl_main.c
  10. 2
      engine/client/cl_parse.c
  11. 71
      engine/client/cl_pmove.c
  12. 3
      engine/client/keys.c
  13. 3
      engine/common/cmd.c
  14. 1
      engine/common/common.h
  15. 2
      engine/common/crclib.c
  16. 4
      engine/common/host.c
  17. 27
      engine/common/imagelib/img_dds.c
  18. 1
      engine/common/imagelib/img_main.c
  19. 7
      engine/common/imagelib/img_utils.c
  20. 137
      engine/common/mod_bmodel.c
  21. 22
      engine/common/mod_studio.c
  22. 5
      engine/common/model.c
  23. 7
      engine/common/net_buffer.c
  24. 2
      engine/common/net_buffer.h
  25. 118
      engine/common/net_encode.c
  26. 2
      engine/common/pm_local.h
  27. 217
      engine/common/pm_surface.c
  28. 78
      engine/common/pm_trace.c
  29. 2
      engine/server/server.h
  30. 5
      engine/server/sv_cmds.c
  31. 23
      engine/server/sv_frame.c
  32. 33
      engine/server/sv_game.c
  33. 23
      engine/server/sv_init.c
  34. 31
      engine/server/sv_main.c
  35. 28
      engine/server/sv_pmove.c
  36. 1
      engine/server/sv_world.c
  37. 2
      ref_gl/gl_beams.c
  38. 2
      ref_gl/gl_decals.c
  39. 41
      ref_gl/gl_image.c
  40. 3
      ref_gl/gl_local.h
  41. 15
      ref_gl/gl_opengl.c
  42. 17
      ref_gl/gl_rmain.c
  43. 1
      ref_gl/gl_rmisc.c
  44. 3
      ref_gl/gl_rpart.c
  45. 6
      ref_gl/gl_rsurf.c
  46. 9
      ref_gl/gl_studio.c
  47. 2
      ref_gl/gl_triapi.c

2
common/bspfile.h

@ -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_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 TEX_SCROLL BIT( 6 ) // Doom special FX
#define IsLiquidContents( cnt ) ( cnt == CONTENTS_WATER || cnt == CONTENTS_SLIME || cnt == CONTENTS_LAVA )
// ambient sound types // ambient sound types
enum enum
{ {

3
common/com_image.h

@ -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 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) #define ImageDXT( type ) (type == PF_DXT1 || type == PF_DXT3 || type == PF_DXT5 || type == PF_ATI2)
typedef enum typedef enum
@ -20,6 +20,7 @@ typedef enum
PF_BGRA_32, // big endian RGBA (MacOS) PF_BGRA_32, // big endian RGBA (MacOS)
PF_RGB_24, // uncompressed dds or another 24-bit image PF_RGB_24, // uncompressed dds or another 24-bit image
PF_BGR_24, // big-endian RGB (MacOS) PF_BGR_24, // big-endian RGB (MacOS)
PF_LUMINANCE,
PF_DXT1, // s3tc DXT1 format PF_DXT1, // s3tc DXT1 format
PF_DXT3, // s3tc DXT3 format PF_DXT3, // s3tc DXT3 format
PF_DXT5, // s3tc DXT5 format PF_DXT5, // s3tc DXT5 format

11
common/com_model.h

@ -109,6 +109,15 @@ typedef struct
int reserved[32]; // just for future expansions or mod-makers int reserved[32]; // just for future expansions or mod-makers
} mfaceinfo_t; } 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 typedef struct
{ {
float vecs[2][4]; // [s/t] unit vectors in world space. float vecs[2][4]; // [s/t] unit vectors in world space.
@ -208,7 +217,7 @@ typedef struct mextrasurf_s
// begin userdata // begin userdata
struct msurface_s *lightmapchain; // lightmapped polys struct msurface_s *lightmapchain; // lightmapped polys
struct mextrasurf_s *detailchain; // for detail textures drawing 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 mextrasurf_s *lumachain; // draw fullbrights
struct cl_entity_s *parent; // upcast to owner entity struct cl_entity_s *parent; // upcast to owner entity

2
common/enginefeatures.h

@ -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_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_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 #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 #define ENGINE_COMPUTE_STUDIO_LERP (1<<7) // enable MOVETYPE_STEP lerping back in engine
#endif//FEATURES_H #endif//FEATURES_H

1
common/render_api.h

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

2
engine/client/avi/avi_win.c

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

4
engine/client/cl_game.c

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

4
engine/client/cl_gameui.c

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

1
engine/client/cl_main.c

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

2
engine/client/cl_parse.c

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

71
engine/client/cl_pmove.c

@ -472,7 +472,7 @@ void CL_AddLinksToPmove( frame_t *frame )
if( VectorIsNull( state->mins ) && VectorIsNull( state->maxs )) if( VectorIsNull( state->mins ) && VectorIsNull( state->maxs ))
continue; 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 ) if( clgame.pmove->nummoveent >= MAX_MOVEENTS )
continue; 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 CL_WaterEntity
@ -666,9 +605,9 @@ int CL_WaterEntity( const float *rgflPos )
oldhull = clgame.pmove->usehull; 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 ? if( pe->solid != SOLID_NOT ) // disabled ?
continue; continue;
@ -793,7 +732,7 @@ static int pfnPointContents( float *p, int *truecontents )
{ {
int cont, truecont; int cont, truecont;
truecont = cont = CL_TruePointContents( p ); truecont = cont = PM_PointContents( clgame.pmove, p );
if( truecontents ) *truecontents = truecont; if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) 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 ) 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 ) static int pfnHullPointContents( struct hull_s *hull, int num, float *p )

3
engine/client/keys.c

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

3
engine/common/cmd.c

@ -1006,9 +1006,8 @@ void Cmd_ExecuteString( char *text )
} }
else else
#endif // XASH_DEDICATED #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 ); Con_Printf( S_WARN "Unknown command \"%s\"\n", text );
} }
} }

1
engine/common/common.h

@ -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_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 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 ); void Log_Printf( const char *fmt, ... ) _format( 1 );
struct sizebuf_s *SV_GetReliableDatagram( void );
void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 ); void SV_BroadcastCommand( const char *fmt, ... ) _format( 1 );
qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent ); qboolean SV_RestoreCustomDecal( struct decallist_s *entry, edict_t *pEdict, qboolean adjacent );
void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... ) _format( 2 ); void SV_BroadcastPrintf( sv_client_t *ignore, char *fmt, ... ) _format( 2 );

2
engine/common/crclib.c

@ -229,7 +229,7 @@ qboolean CRC32_File( dword *crcvalue, const char *filename )
qboolean CRC32_MapFile( dword *crcvalue, const char *filename, qboolean multiplayer ) 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 i, num_bytes, lumplen;
int version, hdr_size; int version, hdr_size;
dheader_t *header; dheader_t *header;

4
engine/common/host.c

@ -49,6 +49,8 @@ sysinfo_t SI;
CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" ); CVAR_DEFINE( host_developer, "developer", "0", 0, "engine is in development-mode" );
CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" ); CVAR_DEFINE_AUTO( sys_ticrate, "100", 0, "framerate in dedicated mode" );
convar_t *host_serverstate;
convar_t *host_gameloaded; convar_t *host_gameloaded;
convar_t *host_clientloaded; convar_t *host_clientloaded;
convar_t *host_limitlocal; convar_t *host_limitlocal;
@ -460,6 +462,7 @@ double Host_CalcFPS( void )
else else
{ {
fps = host_maxfps->value; fps = host_maxfps->value;
if( fps == 0.0 ) fps = MAX_FPS;
fps = bound( MIN_FPS, 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"); 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_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_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" ); host_sleeptime = Cvar_Get( "sleeptime", "1", FCVAR_ARCHIVE, "milliseconds to sleep for each frame. higher values reduce fps accuracy" );

27
engine/common/imagelib/img_dds.c

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

1
engine/common/imagelib/img_main.c

@ -79,6 +79,7 @@ const bpc_desc_t PFDesc[] =
{ PF_BGRA_32, "BGRA 32",0x80E1, 4 }, { PF_BGRA_32, "BGRA 32",0x80E1, 4 },
{ PF_RGB_24, "RGB 24", 0x1908, 3 }, { PF_RGB_24, "RGB 24", 0x1908, 3 },
{ PF_BGR_24, "BGR 24", 0x80E0, 3 }, { PF_BGR_24, "BGR 24", 0x80E0, 3 },
{ PF_LUMINANCE, "LUM 8", 0x1909, 1 },
{ PF_DXT1, "DXT 1", 0x83F1, 4 }, { PF_DXT1, "DXT 1", 0x83F1, 4 },
{ PF_DXT3, "DXT 3", 0x83F2, 4 }, { PF_DXT3, "DXT 3", 0x83F2, 4 },
{ PF_DXT5, "DXT 5", 0x83F3, 4 }, { PF_DXT5, "DXT 5", 0x83F3, 4 },

7
engine/common/imagelib/img_utils.c

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

137
engine/common/mod_bmodel.c

@ -36,7 +36,7 @@ typedef struct leaflist_s
int count; int count;
int maxcount; int maxcount;
qboolean overflowed; qboolean overflowed;
short *list; int *list;
vec3_t mins, maxs; vec3_t mins, maxs;
int topnode; // for overflows where each leaf can't be stored individually int topnode; // for overflows where each leaf can't be stored individually
} leaflist_t; } leaflist_t;
@ -668,7 +668,7 @@ static void Mod_BoxLeafnums_r( leaflist_t *ll, mnode_t *node )
Mod_BoxLeafnums 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; leaflist_t ll;
@ -699,7 +699,7 @@ is potentially visible
*/ */
qboolean Mod_BoxVisible( const vec3_t mins, const vec3_t maxs, const byte *visbits ) 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; int i, count;
if( !visbits || !mins || !maxs ) if( !visbits || !mins || !maxs )
@ -884,6 +884,59 @@ int Mod_SampleSizeForFace( msurface_t *surf )
return LM_SAMPLE_SIZE; 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 Mod_MakeNormalAxial
@ -1068,6 +1121,66 @@ static void Mod_CalcSurfaceBounds( msurface_t *surf )
VectorAverage( surf->info->mins, surf->info->maxs, surf->info->origin ); 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 Mod_SetParent
@ -1520,7 +1633,7 @@ static void Mod_LoadEntities( dbspmodel_t *bmod )
{ {
byte *entpatch = NULL; byte *entpatch = NULL;
char token[MAX_TOKEN]; char token[MAX_TOKEN];
char wadstring[2048]; char wadstring[MAX_TOKEN];
string keyname; string keyname;
char *pfile; char *pfile;
@ -1822,6 +1935,8 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
for( i = 0; i < loadmodel->numtextures; i++ ) for( i = 0; i < loadmodel->numtextures; i++ )
{ {
int txFlags = 0;
if( in->dataofs[i] == -1 ) if( in->dataofs[i] == -1 )
{ {
// create default texture (some mods requires this) // create default texture (some mods requires this)
@ -1853,6 +1968,10 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
tx->width = mt->width; tx->width = mt->width;
tx->height = mt->height; 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 ) if( mt->offsets[0] > 0 )
{ {
int size = (int)sizeof( mip_t ) + ((mt->width * mt->height * 85)>>6); 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 )) 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 bmod->wadlist.wadusage[j]++; // this wad are really used
break; break;
} }
@ -1920,13 +2039,12 @@ static void Mod_LoadTextures( dbspmodel_t *bmod )
if( custom_palette ) size += sizeof( short ) + 768; if( custom_palette ) size += sizeof( short ) + 768;
Q_snprintf( texname, sizeof( texname ), "#%s:%s.mip", loadstat.name, mt->name ); 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 texture is completely missed
if( !tx->gl_texturenum ) 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 ); tx->gl_texturenum = R_GetBuiltinTexture( REF_DEFAULT_TEXTURE );
} }
@ -2225,6 +2343,7 @@ static void Mod_LoadSurfaces( dbspmodel_t *bmod )
Mod_CalcSurfaceBounds( out ); Mod_CalcSurfaceBounds( out );
Mod_CalcSurfaceExtents( out ); Mod_CalcSurfaceExtents( out );
Mod_CreateFaceBevels( out );
// grab the second sample to detect colored lighting // grab the second sample to detect colored lighting
if( test_lightsize > 0 && lightofs != -1 ) 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 ) 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 )]; byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer ); size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr; 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 ) 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 )]; byte buffer[sizeof( dheader_t ) + sizeof( dextrahdr_t )];
size_t prefetch_size = sizeof( buffer ); size_t prefetch_size = sizeof( buffer );
dextrahdr_t *extrahdr; dextrahdr_t *extrahdr;

22
engine/common/mod_studio.c

@ -749,6 +749,8 @@ void Mod_StudioGetAttachment( const edict_t *e, int iAtt, float *origin, float *
{ {
mstudioattachment_t *pAtt; mstudioattachment_t *pAtt;
vec3_t angles2; vec3_t angles2;
matrix3x4 localPose;
matrix3x4 worldPose;
model_t *mod; model_t *mod;
mod = SV_ModelHandle( e->v.modelindex ); 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 ); 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 Matrix3x4_LoadIdentity( localPose );
if( origin != NULL ) Matrix3x4_SetOrigin( localPose, pAtt->org[0], pAtt->org[1], pAtt->org[2] );
Matrix3x4_VectorTransform( studio_bones[pAtt->bone], pAtt->org, origin ); Matrix3x4_ConcatTransforms( worldPose, studio_bones[pAtt->bone], localPose );
if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && origin != NULL && angles != NULL ) if( origin != NULL ) // origin is used always
{ Matrix3x4_OriginFromMatrix( worldPose, origin );
vec3_t forward, bonepos;
Matrix3x4_OriginFromMatrix( studio_bones[pAtt->bone], bonepos ); if( FBitSet( host.features, ENGINE_COMPUTE_STUDIO_LERP ) && angles != NULL )
VectorSubtract( origin, bonepos, forward ); // make forward Matrix3x4_AnglesFromMatrix( worldPose, angles );
VectorNormalizeFast( forward );
VectorAngles( forward, 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 ); 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( 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 );
} }
/* /*

5
engine/common/model.c

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

7
engine/common/net_buffer.c

@ -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 ) if( bSigned )
MSG_WriteSBitLong( sb, (int)data, numbits ); MSG_WriteSBitLong( sb, data, numbits );
else MSG_WriteUBitLong( sb, data, numbits ); else MSG_WriteUBitLong( sb, (uint)data, numbits );
} }
qboolean MSG_WriteBits( sizebuf_t *sb, const void *pData, int nBits ) 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 ); fa[2] = MSG_ReadBitAngle( sb, 16 );
} }
int MSG_ReadLong( sizebuf_t *sb ) int MSG_ReadLong( sizebuf_t *sb )
{ {
return MSG_ReadSBitLong( sb, sizeof( int ) << 3 ); return MSG_ReadSBitLong( sb, sizeof( int ) << 3 );

2
engine/common/net_buffer.h

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

118
engine/common/net_encode.c

@ -312,7 +312,7 @@ delta_info_t *Delta_FindStruct( const char *name )
{ {
int i; int i;
if( !name || !name[0] ) if( !COM_CheckString( name ))
return NULL; return NULL;
for( i = 0; i < NUM_FIELDS( dt_info ); i++ ) 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 )) if( !Q_strcmp( pField->name, pName ))
{ {
Con_Reportf( "Delta_Add: %s->%s already existing\n", pStructName, pName ); // update existed field
return false; // field already exist 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 ); Assert( pField != NULL );
if( !pField->name || !*pField->name ) if( !COM_CheckString( pField->name ))
return; // not initialized ? return; // not initialized ?
dt = Delta_FindStructByIndex( tableIndex ); dt = Delta_FindStructByIndex( tableIndex );
@ -626,7 +630,6 @@ qboolean Delta_ParseField( char **delta_script, const delta_field_t *pInfo, delt
} }
// read delta-bits // read delta-bits
if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL ) if(( *delta_script = COM_ParseFile( *delta_script, token )) == NULL )
{ {
Con_DPrintf( S_ERROR "Delta_ReadField: %s field bits argument is missing\n", pField->name ); 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 ); Delta_ParseTable( &pfile, dt, encodeDll, encodeFunc );
} }
Mem_Free( afile ); 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 ) void Delta_Init( void )
@ -894,73 +892,18 @@ Delta_ClampIntegerField
prevent data to out of range 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: int signbits = bSigned ? (numbits - 1) : numbits;
iValue = bound( 0, (byte)iValue, 1 ); int maxnum = BIT( signbits ) - 1;
break; int minnum = bSigned ? -maxnum : 0;
case 2: iValue = bound( minnum, iValue, maxnum );
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;
} }
return iValue; // clamped; 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 ); toF = *(byte *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= 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 ); toF = *(word *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= 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 ); toF = *(uint *)((byte *)to + pField->offset );
} }
fromF = Delta_ClampIntegerField( fromF, bSigned, pField->bits ); fromF = Delta_ClampIntegerField( pField, fromF, bSigned, pField->bits );
toF = Delta_ClampIntegerField( toF, bSigned, pField->bits ); toF = Delta_ClampIntegerField( pField, toF, bSigned, pField->bits );
if( pField->multiplier != 1.0f ) fromF *= pField->multiplier; if( pField->multiplier != 1.0f ) fromF *= pField->multiplier;
if( pField->multiplier != 1.0f ) toF *= 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 ) if( pField->flags & DT_BYTE )
{ {
iValue = *(byte *)((byte *)to + pField->offset ); 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; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_SHORT ) else if( pField->flags & DT_SHORT )
{ {
iValue = *(word *)((byte *)to + pField->offset ); 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; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_INTEGER ) else if( pField->flags & DT_INTEGER )
{ {
iValue = *(uint *)((byte *)to + pField->offset ); 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; if( pField->multiplier != 1.0f ) iValue *= pField->multiplier;
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); 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 ); flValue = *(float *)((byte *)to + pField->offset );
iValue = (int)(flValue * pField->multiplier); iValue = (int)(flValue * pField->multiplier);
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_ANGLE ) else if( pField->flags & DT_ANGLE )
@ -1212,7 +1156,7 @@ qboolean Delta_WriteField( sizebuf_t *msg, delta_t *pField, void *from, void *to
flValue = *(float *)((byte *)to + pField->offset ); 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 = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_TIMEWINDOW_BIG ) 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 ); flValue = *(float *)((byte *)to + pField->offset );
flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier ); flTime = Q_rint( timebase * pField->multiplier ) - Q_rint( flValue * pField->multiplier );
iValue = (uint)abs( flTime ); iValue = (uint)abs( flTime );
iValue = Delta_ClampIntegerField( pField, iValue, bSigned, pField->bits );
MSG_WriteBitLong( msg, iValue, pField->bits, bSigned ); MSG_WriteBitLong( msg, iValue, pField->bits, bSigned );
} }
else if( pField->flags & DT_STRING ) else if( pField->flags & DT_STRING )

2
engine/common/pm_local.h

@ -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 ); 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_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_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 ); void PM_ConvertTrace( trace_t *out, pmtrace_t *in, edict_t *ent );
// //

217
engine/common/pm_surface.c

@ -16,84 +16,160 @@ GNU General Public License for more details.
#include "common.h" #include "common.h"
#include "mathlib.h" #include "mathlib.h"
#include "pm_local.h" #include "pm_local.h"
#include "ref_common.h"
#define FRAC_EPSILON (1.0f / 32.0f)
typedef struct typedef struct
{ {
float fraction; float fraction;
int contents; int contents;
msurface_t *surface;
} linetrace_t; } 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 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; float t1, t2, frac;
int side, ds, dt; int i, side;
mplane_t *plane;
msurface_t *surf; msurface_t *surf;
vec3_t mid; vec3_t mid;
int i; loc0:
if( node->contents < 0 ) if( node->contents < 0 )
return NULL; 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; node = node->children[0];
t2 = p2[plane->type] - plane->dist; goto loc0;
} }
else
if( t1 < FRAC_EPSILON && t2 < FRAC_EPSILON )
{ {
t1 = DotProduct( plane->normal, p1 ) - plane->dist; node = node->children[1];
t2 = DotProduct( plane->normal, p2 ) - plane->dist; goto loc0;
} }
if( t1 >= 0.0f && t2 >= 0.0f ) side = (t1 < 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 );
frac = t1 / ( t1 - t2 ); frac = t1 / ( t1 - t2 );
frac = bound( 0.0f, frac, 1.0f );
if( frac < 0.0f ) frac = 0.0f;
if( frac > 1.0f ) frac = 1.0f;
VectorLerp( p1, frac, p2, mid ); VectorLerp( p1, frac, p2, mid );
side = (t1 < 0.0f); if(( surf = PM_RecursiveSurfCheck( mod, node->children[side], p1, mid )) != NULL )
return surf;
// 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 )) // walk through real faces
for( i = 0; i < node->numsurfaces; i++ )
{ {
return surf; msurface_t *surf = &mod->surfaces[node->firstsurface + i];
} mextrasurf_t *info = surf->info;
mfacebevel_t *fb = info->bevel;
int j, contents;
vec3_t delta;
surf = model->surfaces + node->firstsurface; if( !fb ) continue; // ???
for( i = 0; i < node->numsurfaces; i++, surf++ ) VectorSubtract( mid, fb->origin, delta );
{ if( DotProduct( delta, delta ) >= fb->radius )
ds = (int)((float)DotProduct( mid, surf->texinfo->vecs[0] ) + surf->texinfo->vecs[0][3] ); continue; // no intersection
dt = (int)((float)DotProduct( mid, surf->texinfo->vecs[1] ) + surf->texinfo->vecs[1][3] );
if( ds >= surf->texturemins[0] && dt >= surf->texturemins[1] ) for( j = 0; j < fb->numedges; j++ )
{ {
int s = ds - surf->texturemins[0]; if( PlaneDiff( mid, &fb->edges[j] ) > FRAC_EPSILON )
int t = dt - surf->texturemins[1]; break; // outside the bounds
}
if( j != fb->numedges )
continue; // we are outside the bounds of the facet
if( s <= surf->extents[0] && t <= surf->extents[1] ) // hit the surface
contents = PM_SampleMiptex( surf, mid );
if( contents != CONTENTS_EMPTY )
return surf; 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 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 front, back;
float frac, midf; float frac, midf;
int r, side; int i, r, side;
vec3_t mid; vec3_t mid;
loc0: loc0:
if( node->contents < 0 ) if( node->contents < 0 )
trace->contents = node->contents; {
// water, slime or lava interpret as empty
if( node->contents == CONTENTS_SOLID ) if( node->contents == CONTENTS_SOLID )
return CONTENTS_SOLID; return CONTENTS_SOLID;
if( node->contents == CONTENTS_SKY ) if( node->contents == CONTENTS_SKY )
return CONTENTS_SKY; return CONTENTS_SKY;
if( node->contents < 0 ) trace->fraction = 1.0f;
return CONTENTS_EMPTY; return CONTENTS_EMPTY;
}
front = PlaneDiff( start, node->plane ); front = PlaneDiff( start, node->plane );
back = PlaneDiff( stop, 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]; node = node->children[0];
goto loc0; goto loc0;
} }
if( front < ON_EPSILON && back < ON_EPSILON ) if( front < FRAC_EPSILON && back < FRAC_EPSILON )
{ {
node = node->children[1]; node = node->children[1];
goto loc0; goto loc0;
@ -198,15 +276,54 @@ loc0:
VectorLerp( start, frac, stop, mid ); VectorLerp( start, frac, stop, mid );
midf = p1f + ( p2f - p1f ) * frac; 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 ) if( r != CONTENTS_EMPTY )
{ {
if( trace->surface == NULL )
trace->fraction = midf; trace->fraction = midf;
trace->contents = r;
return 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 ) 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.contents = CONTENTS_EMPTY;
trace.fraction = 1.0f; trace.fraction = 1.0f;
trace.surface = NULL;
for( i = 0; i < numents; i++ ) for( i = 0; i < numents; i++ )
{ {
pe = &ents[i]; pe = &ents[i];
if( i != 0 && ( flags & PM_WORLD_ONLY )) if( i != 0 && FBitSet( flags, PM_WORLD_ONLY ))
break; break;
if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP ) if( !pe->model || pe->model->type != mod_brush || pe->solid != SOLID_BSP )
continue; continue;
if( pe->rendermode != kRenderNormal ) if( FBitSet( flags, PM_GLASS_IGNORE ) && pe->rendermode != kRenderNormal )
continue; continue;
hull = &pe->model->hulls[0]; 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.contents = CONTENTS_EMPTY;
trace_bbox.fraction = 1.0f; 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 ) if( trace_bbox.contents != CONTENTS_EMPTY || trace_bbox.fraction < trace.fraction )
{ {

78
engine/common/pm_trace.c

@ -655,3 +655,81 @@ int PM_TestPlayerPosition( playermove_t *pmove, vec3_t pos, pmtrace_t *ptrace, p
return -1; // didn't hit anything 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;
}

2
engine/server/server.h

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

5
engine/server/sv_cmds.c

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

23
engine/server/sv_frame.c

@ -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( 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 )) if( from_client && FBitSet( ent->v.effects, EF_MERGE_VISIBILITY ))
{ {
SetBits( sv.hostflags, SVF_MERGE_VISIBILITY ); SetBits( sv.hostflags, SVF_MERGE_VISIBILITY );
@ -809,33 +809,18 @@ void SV_UpdateToReliableMessages( void )
continue; // reliables go to all connected or spawned continue; // reliables go to all connected or spawned
if( MSG_GetNumBytesWritten( &sv.reliable_datagram ) < MSG_GetNumBytesLeft( &cl->netchan.message )) 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 )); 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 )) if( MSG_GetNumBytesWritten( &sv.datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.datagram ), MSG_GetNumBitsWritten( &sv.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( FBitSet( cl->flags, FCL_HLTV_PROXY ))
{ {
if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram )) if( MSG_GetNumBytesWritten( &sv.spec_datagram ) < MSG_GetNumBytesLeft( &cl->datagram ))
{
MSG_WriteBits( &cl->datagram, MSG_GetBuf( &sv.spec_datagram ), MSG_GetNumBitsWritten( &sv.spec_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 );
}
} }
} }

33
engine/server/sv_game.c

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

23
engine/server/sv_init.c

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

31
engine/server/sv_main.c

@ -152,6 +152,9 @@ send updates to client if changed
*/ */
void SV_UpdateMovevars( qboolean initialize ) void SV_UpdateMovevars( qboolean initialize )
{ {
if( sv.state == ss_dead )
return;
if( !initialize && !host.movevars_changed ) if( !initialize && !host.movevars_changed )
return; 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 ) void SV_ProcessFile( sv_client_t *cl, const char *filename )
{ {
customization_t *pList; customization_t *pList;
@ -549,11 +559,6 @@ qboolean SV_IsSimulating( void )
return false; return false;
} }
/*
=================
SV_RunGameFrame
=================
*/
/* /*
================= =================
SV_RunGameFrame SV_RunGameFrame
@ -639,6 +644,17 @@ void Host_ServerFrame( void )
Master_Heartbeat (); 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 ) void SV_FinalMessage( const char *message, qboolean reconnect )
{ {
byte msg_buf[64]; byte msg_buf[1024];
sv_client_t *cl; sv_client_t *cl;
sizebuf_t msg; sizebuf_t msg;
int i; int i;
@ -984,6 +1000,9 @@ void SV_Shutdown( const char *finalmsg )
SV_FreeClients(); SV_FreeClients();
svs.maxclients = 0; svs.maxclients = 0;
// release all models
Mod_FreeAll();
HPAK_FlushHostQueue(); HPAK_FlushHostQueue();
Log_Printf( "Server shutdown\n" ); Log_Printf( "Server shutdown\n" );
Log_Close(); Log_Close();

28
engine/server/sv_pmove.c

@ -73,7 +73,7 @@ qboolean SV_CopyEdictToPhysEnt( physent_t *pe, edict_t *ed )
if( FBitSet( ed->v.flags, FL_CLIENT )) if( FBitSet( ed->v.flags, FL_CLIENT ))
{ {
// 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 if( FBitSet( ed->v.flags, FL_FAKECLIENT )) // fakeclients have client flag too
{ {
// bot // bot
@ -306,7 +306,7 @@ void SV_AddLaddersToPmove( areanode_t *node, const vec3_t pmove_mins, const vec3
model_t *mod; model_t *mod;
physent_t *pe; physent_t *pe;
// get water edicts // get ladder edicts
for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next ) for( l = node->solid_edicts.next; l != &node->solid_edicts; l = next )
{ {
next = 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 )); 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 ) static int pfnTestPlayerPosition( float *pos, pmtrace_t *ptrace )
{ {
return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL ); return PM_TestPlayerPosition( svgame.pmove, pos, ptrace, NULL );
@ -390,7 +395,7 @@ static int pfnPointContents( float *p, int *truecontents )
{ {
int cont, truecont; int cont, truecont;
truecont = cont = SV_TruePointContents( p ); truecont = cont = PM_PointContents( svgame.pmove, p );
if( truecontents ) *truecontents = truecont; if( truecontents ) *truecontents = truecont;
if( cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN ) 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 ) 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 ) 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 ) if( pmove->onground == -1 )
{ {
clent->v.flags &= ~FL_ONGROUND; ClearBits( clent->v.flags, FL_ONGROUND );
} }
else if( pmove->onground >= 0 && pmove->onground < pmove->numphysent ) 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 ); 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 )) if( SV_UnlagCheckTeleport( state->origin, lerp->finalpos ))
lerp->nointerp = true; lerp->nointerp = true;
} }
else else lerp->firstframe = true;
{
lerp->firstframe = true;
}
VectorCopy( state->origin, lerp->finalpos ); VectorCopy( state->origin, lerp->finalpos );
} }
@ -1004,10 +1006,10 @@ void SV_RestoreMoveInterpolant( sv_client_t *cl )
oldlerp = &svgame.interp[i]; 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. continue; // they didn't actually move.
if( !oldlerp->active ) if( !oldlerp->moving || !oldlerp->active )
continue; continue;
if( VectorCompare( oldlerp->curpos, check->edict->v.origin )) 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 )) if( !FBitSet( cl->flags, FCL_FAKECLIENT ))
{
SV_SetupMoveInterpolant( cl ); SV_SetupMoveInterpolant( cl );
}
svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed ); svgame.dllFuncs.pfnCmdStart( cl->edict, ucmd, random_seed );

1
engine/server/sv_world.c

@ -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 ) 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 )); memset( trace, 0, sizeof( trace_t ));
VectorCopy( end, trace->endpos ); VectorCopy( end, trace->endpos );
trace->allsolid = true; trace->allsolid = true;

2
ref_gl/gl_beams.c

@ -485,7 +485,7 @@ void R_DrawDisk( vec3_t source, vec3_t delta, float width, float scale, float fr
scale = scale * length; scale = scale * length;
// clamp the beam width // 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 // NOTE: we must force the degenerate triangles to be on the edge
for( i = 0; i < segments; i++ ) for( i = 0; i < segments; i++ )

2
ref_gl/gl_decals.c

@ -75,7 +75,7 @@ static void R_DecalUnlink( decal_t *pdecal )
else else
{ {
tmp = pdecal->psurface->pdecals; 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 ) while( tmp->pnext )
{ {

41
ref_gl/gl_image.c

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

3
ref_gl/gl_local.h

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

15
ref_gl/gl_opengl.c

@ -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_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 ); GL_CheckExtension( "GL_EXT_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT );
if( !GL_Support( GL_CLAMPTOEDGE_EXT )) if( !GL_Support( GL_CLAMPTOEDGE_EXT ))
GL_CheckExtension( "GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT ); GL_CheckExtension( "GL_SGIS_texture_edge_clamp", NULL, "gl_clamp_to_edge", GL_CLAMPTOEDGE_EXT );
glConfig.max_texture_anisotropy = 0.0f; 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 )) if( GL_Support( GL_ANISOTROPY_EXT ))
pglGetFloatv( GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT, &glConfig.max_texture_anisotropy ); 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 )) if( GL_Support( GL_TEXTURE_LOD_BIAS ))
pglGetFloatv( GL_MAX_TEXTURE_LOD_BIAS_EXT, &glConfig.max_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_texture_border_clamp", NULL, NULL, 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_texture", NULL, NULL, GL_DEPTH_TEXTURE );
GL_CheckExtension( "GL_ARB_depth_buffer_float", NULL, "gl_arb_depth_float", GL_ARB_DEPTH_FLOAT_EXT ); 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_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 ); GL_CheckExtension( "GL_ARB_vertex_buffer_object", vbofuncs, "gl_vertex_buffer_object", GL_ARB_VERTEX_BUFFER_OBJECT_EXT );
// rectangle textures support // rectangle textures support

17
ref_gl/gl_rmain.c

@ -41,18 +41,14 @@ static int R_RankForRenderMode( int rendermode )
void R_AllowFog( qboolean allowed ) void R_AllowFog( qboolean allowed )
{ {
static int isFogEnabled;
if( allowed ) if( allowed )
{ {
if( isFogEnabled ) if( glState.isFogEnabled )
pglEnable( GL_FOG ); pglEnable( GL_FOG );
} }
else else
{ {
isFogEnabled = pglIsEnabled( GL_FOG ); if( glState.isFogEnabled )
if( isFogEnabled )
pglDisable( GL_FOG ); pglDisable( GL_FOG );
} }
} }
@ -498,6 +494,9 @@ static void R_SetupFrame( void )
// setup viewplane dist // setup viewplane dist
RI.viewplanedist = DotProduct( RI.vieworg, RI.vforward ); 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 ) if( !gl_nosort->value )
{ {
// sort translucents entities by rendermode and distance // 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 // in some cases waterlevel jumps from 3 to 1. Catch it
RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL ); RI.cached_waterlevel = ENGINE_GET_PARM( PARM_WATER_LEVEL );
RI.cached_contents = CONTENTS_EMPTY; RI.cached_contents = CONTENTS_EMPTY;
if( !RI.fogCustom ) pglDisable( GL_FOG ); if( !RI.fogCustom )
{
glState.isFogEnabled = false;
pglDisable( GL_FOG );
}
} }
return; return;
} }

1
ref_gl/gl_rmisc.c

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

3
ref_gl/gl_rpart.c

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

6
ref_gl/gl_rsurf.c

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

9
ref_gl/gl_studio.c

@ -1302,8 +1302,6 @@ StudioCalcAttachments
static void R_StudioCalcAttachments( void ) static void R_StudioCalcAttachments( void )
{ {
mstudioattachment_t *pAtt; mstudioattachment_t *pAtt;
vec3_t forward, bonepos;
vec3_t localOrg, localAng;
int i; int i;
// calculate attachment points // calculate attachment points
@ -1312,11 +1310,6 @@ static void R_StudioCalcAttachments( void )
for( i = 0; i < Q_min( MAXSTUDIOATTACHMENTS, m_pStudioHeader->numattachments ); i++ ) 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] ); 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); gEngfuncs.Image_SetMDLPointer((byte *)phdr + ptexture->index);
size = sizeof( mstudiotexture_t ) + ptexture->width * ptexture->height + 768; 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 flags |= TF_KEEP_SOURCE; // Paranoia2 texture alpha-tracing
// build the texname // build the texname

2
ref_gl/gl_triapi.c

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

Loading…
Cancel
Save