01 Mar 2017

This commit is contained in:
g-cont 2017-03-01 00:00:00 +03:00 committed by Alibek Omarov
parent 6e5939c6be
commit 93a387854a
12 changed files with 377 additions and 159 deletions

View File

@ -3623,7 +3623,7 @@ triangleapi_t gTriApi =
static efx_api_t gEfxApi =
{
R_AllocParticle,
CL_BlobExplosion,
R_BlobExplosion,
R_Blood,
CL_BloodSprite,
R_BloodStream,
@ -3644,8 +3644,8 @@ static efx_api_t gEfxApi =
CL_MuzzleFlash,
R_ParticleBox,
R_ParticleBurst,
CL_ParticleExplosion,
CL_ParticleExplosion2,
R_ParticleExplosion,
R_ParticleExplosion2,
R_ParticleLine,
CL_PlayerSprites,
CL_Projectile,
@ -3692,7 +3692,7 @@ static efx_api_t gEfxApi =
CL_TempEntAllocNoModel,
CL_TempEntAllocHigh,
CL_TempEntAllocCustom,
CL_GetPackedColor,
R_GetPackedColor,
R_LookupColor,
CL_DecalRemoveAll,
CL_FireCustomDecal,

View File

@ -761,6 +761,7 @@ void CL_WritePacket( void )
// update size counter for netgraph
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].sendsize = MSG_GetNumBytesWritten( &buf );
cl.commands[cls.netchan.outgoing_sequence & CL_UPDATE_MASK].heldback = false;
// composite the rest of the datagram..
if( MSG_GetNumBitsWritten( &cls.datagram ) <= MSG_GetNumBitsLeft( &buf ))

View File

@ -20,17 +20,19 @@ GNU General Public License for more details.
#define NET_TIMINGS 1024
#define NET_TIMINGS_MASK (NET_TIMINGS - 1)
#define LATENCY_AVG_FRAC 0.5
#define FRAMERATE_AVG_FRAC 0.5
#define PACKETLOSS_AVG_FRAC 0.5
#define PACKETCHOKE_AVG_FRAC 0.5
#define NETGRAPH_LERP_HEIGHT 24
#define NETGRAPH_NET_COLORS 5
#define NUM_LATENCY_SAMPLES 8
convar_t *net_graph;
convar_t *net_graphpos;
convar_t *net_graphwidth;
convar_t *net_graphheight;
convar_t *net_graphsolid;
convar_t *net_scale;
convar_t *net_graphfillsegments;
static struct packet_latency_t
{
@ -45,30 +47,58 @@ static struct cmdinfo_t
qboolean sent;
} netstat_cmdinfo[NET_TIMINGS];
static byte netcolors[NETGRAPH_LERP_HEIGHT+5][4] =
static byte netcolors[NETGRAPH_NET_COLORS+NETGRAPH_LERP_HEIGHT][4] =
{
{ 255, 0, 0, 255 },
{ 0, 0, 255, 255 },
{ 255, 0, 0, 255 },
{ 240, 127, 63, 255 },
{ 255, 255, 0, 255 },
{ 63, 255, 63, 150 }
// other will be generated through NetGraph_InitColors()
};
static byte sendcolor[4] = { 88, 29, 130, 255 };
static byte holdcolor[4] = { 255, 0, 0, 200 };
static byte extrap_base_color[4] = { 255, 255, 255, 255 };
static netbandwidthgraph_t netstat_graph[NET_TIMINGS];
static float packet_loss;
static float packet_choke;
static float framerate = 0.0;
static int maxmsgbytes = 0;
/*
==========
NetGraph_DrawLine
NetGraph_DrawRect
CL_FillRGBA shortcut
NetGraph_FillRGBA shortcut
==========
*/
static void NetGraph_DrawRect( wrect_t *rect, byte colors[4] )
{
CL_FillRGBA( rect->left, rect->top, rect->right, rect->bottom, colors[0], colors[1], colors[2], colors[3] );
pglColor4ubv( colors ); // color for this quad
pglVertex2f( rect->left, rect->top );
pglVertex2f( rect->left + rect->right, rect->top );
pglVertex2f( rect->left + rect->right, rect->top + rect->bottom );
pglVertex2f( rect->left, rect->top + rect->bottom );
}
/*
==========
NetGraph_AtEdge
edge detect
==========
*/
qboolean NetGraph_AtEdge( int x, int width )
{
if( x > 3 )
{
if( x >= width - 4 )
return true;
return false;
}
return true;
}
/*
@ -80,21 +110,47 @@ init netgraph colors
*/
void NetGraph_InitColors( void )
{
int i;
byte mincolor[2][3];
byte maxcolor[2][3];
float dc[2][3];
int i, hfrac;
float f;
mincolor[0][0] = 63;
mincolor[0][1] = 0;
mincolor[0][2] = 100;
maxcolor[0][0] = 0;
maxcolor[0][1] = 63;
maxcolor[0][2] = 255;
mincolor[1][0] = 255;
mincolor[1][1] = 127;
mincolor[1][2] = 0;
maxcolor[1][0] = 250;
maxcolor[1][1] = 0;
maxcolor[1][2] = 0;
for( i = 0; i < 3; i++ )
{
dc[0][i] = (float)(maxcolor[0][i] - mincolor[0][i]);
dc[1][i] = (float)(maxcolor[1][i] - mincolor[1][i]);
}
hfrac = NETGRAPH_LERP_HEIGHT / 3;
for( i = 0; i < NETGRAPH_LERP_HEIGHT; i++ )
{
if( i <= NETGRAPH_LERP_HEIGHT / 3 )
if( i < hfrac )
{
netcolors[i + 5][0] = i * -7.875f + 63;
netcolors[i + 5][1] = i * 7.875f;
netcolors[i + 5][2] = i * 19.375f + 100;
f = (float)i / (float)hfrac;
VectorMA( mincolor[0], f, dc[0], netcolors[NETGRAPH_NET_COLORS + i] );
}
else
{
netcolors[i + 5][0] = ( i - 8 ) * -0.3125f + 255;
netcolors[i + 5][1] = ( i - 8 ) * -7.9375f + 127;
netcolors[i + 5][2] = 0;
f = (float)(i - hfrac) / (float)(NETGRAPH_LERP_HEIGHT - hfrac );
VectorMA( mincolor[1], f, dc[1], netcolors[NETGRAPH_NET_COLORS + i] );
}
}
}
@ -106,14 +162,23 @@ NetGraph_GetFrameData
get frame data info, like chokes, packet losses, also update graph, packet and cmdinfo
==========
*/
void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_count )
void NetGraph_GetFrameData( float *latency, int *latency_count )
{
int i, choke_count = 0, loss_count = 0;
float loss, choke;
int i, choke_count = 0, loss_count = 0;
double newtime = Sys_DoubleTime();
static double nexttime = 0;
float loss, choke;
*biggest_message = *latency_count = 0;
*latency_count = 0;
*latency = 0.0f;
if( newtime >= nexttime )
{
// soft fading of net peak usage
maxmsgbytes = Q_max( 0, maxmsgbytes - 50 );
nexttime = newtime + 0.05;
}
for( i = cls.netchan.incoming_sequence - CL_UPDATE_BACKUP + 1; i <= cls.netchan.incoming_sequence; i++ )
{
frame_t *f = cl.frames + ( i & CL_UPDATE_MASK );
@ -121,8 +186,7 @@ void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_c
netbandwidthgraph_t *g = netstat_graph + ( i & NET_TIMINGS_MASK );
p->choked = f->receivedtime == -2.0f ? true : false;
if( p->choked )
choke_count++;
if( p->choked ) choke_count++;
if( !f->valid )
{
@ -144,17 +208,20 @@ void NetGraph_GetFrameData( int *biggest_message, float *latency, int *latency_c
if( i > cls.netchan.incoming_sequence - NUM_LATENCY_SAMPLES )
{
*latency += 1000.0f * f->latency;
latency_count++;
(*latency) += 1000.0f * f->latency;
(*latency_count)++;
}
}
memcpy( g, &f->graphdata, sizeof( netbandwidthgraph_t ));
if( *biggest_message < g->msgbytes )
*biggest_message = g->msgbytes;
if( g->msgbytes > maxmsgbytes )
maxmsgbytes = g->msgbytes;
}
if( maxmsgbytes > 1000 )
maxmsgbytes = 1000;
for( i = cls.netchan.outgoing_sequence - CL_UPDATE_BACKUP + 1; i <= cls.netchan.outgoing_sequence; i++ )
{
netstat_cmdinfo[i & NET_TIMINGS_MASK].cmd_lerp = cl.commands[i & CL_UPDATE_MASK].frame_lerp;
@ -180,12 +247,9 @@ NetGraph_DrawTimes
void NetGraph_DrawTimes( wrect_t rect, int x, int w )
{
int i, j, extrap_point = NETGRAPH_LERP_HEIGHT / 3, a, h;
POINT pt = { Q_max( x + w - 1 - 25, 1 ), Q_max( rect.top + rect.bottom - 4 - NETGRAPH_LERP_HEIGHT + 1, 1 ) };
rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 };
wrect_t fill;
Con_DrawString( pt.x, pt.y, va( "%i/s", cl_cmdrate->value ), colors );
for( a = 0; a < w; a++ )
{
i = ( cls.netchan.outgoing_sequence - a ) & NET_TIMINGS_MASK;
@ -202,10 +266,15 @@ void NetGraph_DrawTimes( wrect_t rect, int x, int w )
h -= extrap_point;
fill.top -= extrap_point;
if( !net_graphsolid->value )
{
fill.top -= (h - 1);
start = (h - 1);
}
for( j = start; j < h; j++ )
{
memcpy( colors, netcolors[j + extrap_point], sizeof( byte ) * 3 );
NetGraph_DrawRect( &fill, colors );
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + extrap_point] );
fill.top--;
}
}
@ -216,40 +285,60 @@ void NetGraph_DrawTimes( wrect_t rect, int x, int w )
fill.top -= h;
h = extrap_point - h;
if( !net_graphsolid->value )
h = 1;
for( j = 0; j < h; j++ )
{
memcpy( colors, netcolors[j + oldh], sizeof( byte ) * 3 );
NetGraph_DrawRect( &fill, colors );
NetGraph_DrawRect( &fill, netcolors[NETGRAPH_NET_COLORS + j + oldh] );
fill.top--;
}
}
fill.top = rect.top + rect.bottom - 4 - extrap_point;
CL_FillRGBA( fill.left, fill.top, fill.right, fill.bottom, 255, 255, 255, 255 );
if( NetGraph_AtEdge( a, w ))
NetGraph_DrawRect( &fill, extrap_base_color );
fill.top = rect.top + rect.bottom - 3;
fill.top = rect.top + rect.bottom - 4;
if( !netstat_cmdinfo[i].sent )
CL_FillRGBA( fill.left, fill.top, fill.right, fill.bottom, 255, 0, 0, 255 );
if( netstat_cmdinfo[i].sent )
NetGraph_DrawRect( &fill, sendcolor );
else NetGraph_DrawRect( &fill, holdcolor );
}
}
//left = x
//right = width
//top = y
//bottom = height
/*
===========
NetGraph_DrawHatches
===========
*/
void NetGraph_DrawHatches( int x, int y, int maxmsgbytes )
void NetGraph_DrawHatches( int x, int y )
{
int ystep = max((int)( 10.0 / net_scale->value ), 1 );
int ystep = (int)( 10.0f / net_scale->value );
byte colorminor[4] = { 0, 63, 63, 200 };
byte color[4] = { 0, 200, 0, 255 };
wrect_t hatch = { x, 4, y, 1 };
int starty;
ystep = Q_max( ystep, 1 );
for( starty = hatch.top; hatch.top > 0 && ((starty - hatch.top) * net_scale->value < (maxmsgbytes + 50)); hatch.top -= ystep )
{
CL_FillRGBA( hatch.left, hatch.top, hatch.right, hatch.bottom, 63, 63, 0, 200 );
if(!((int)((starty - hatch.top) * net_scale->value ) % 50 ))
{
NetGraph_DrawRect( &hatch, color );
}
else if( ystep > 5 )
{
NetGraph_DrawRect( &hatch, colorminor );
}
}
}
@ -259,28 +348,68 @@ NetGraph_DrawTextFields
===========
*/
void NetGraph_DrawTextFields( int x, int y, int count, float avg, int packet_loss, int packet_choke )
void NetGraph_DrawTextFields( int x, int y, int w, wrect_t rect, int count, float avg, int packet_loss, int packet_choke )
{
static int lastout;
rgba_t colors = { 0.9 * 255, 0.9 * 255, 0.7 * 255, 255 };
int i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK;
float latency = count > 0 ? Q_max( 0, avg / count - 0.5 * host.frametime - 1000.0 / cl_updaterate->value ) : 0;
float framerate = 1.0 / host.frametime;
int ptx = Q_max( x + w - NETGRAPH_LERP_HEIGHT - 1, 1 );
int pty = Q_max( rect.top + rect.bottom - NETGRAPH_LERP_HEIGHT - 3, 1 );
int out, i = ( cls.netchan.outgoing_sequence - 1 ) & NET_TIMINGS_MASK;
int j = cls.netchan.incoming_sequence & NET_TIMINGS_MASK;
int last_y = y - net_graphheight->value;
Con_DrawString( x, y - net_graphheight->value, va( "%.1f fps" , framerate ), colors );
Con_DrawString( x + 75, y - net_graphheight->value, va( "%i ms" , (int)latency ), colors );
Con_DrawString( x + 150, y - net_graphheight->value, va( "%i/s" , cl_updaterate->value ), colors );
if( count > 0 )
{
avg = avg / (float)( count - ( host.frametime * FRAMERATE_AVG_FRAC ));
if( netstat_cmdinfo[i].size )
lastout = netstat_cmdinfo[i].size;
if( cl_updaterate->value > 0.0f )
avg -= 1000.0f / cl_updaterate->value;
Con_DrawString( x, y - net_graphheight->value + 15, va( "in : %i %.2f k/s", netstat_graph[i].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors );
// can't be below zero
avg = Q_max( 0.0, avg );
}
else avg = 0.0;
Con_DrawString( x, y - net_graphheight->value + 30, va( "out: %i %.2f k/s", lastout, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors );
// move rolling average
framerate = FRAMERATE_AVG_FRAC * host.frametime + ( 1.0 - FRAMERATE_AVG_FRAC ) * framerate;
Con_SetFont( 0 );
if( net_graph->value > 2 )
Con_DrawString( x, y - net_graphheight->value + 45, va( "loss: %i choke: %i", packet_loss, packet_choke ), colors );
if( framerate > 0.0f )
{
y -= net_graphheight->value;
Con_DrawString( x, y, va( "%.1f fps" , 1.0f / framerate ), colors );
if( avg > 1.0f )
Con_DrawString( x + 75, y, va( "%i ms" , (int)avg ), colors );
y += 15;
out = netstat_cmdinfo[i].size;
if( !out ) out = lastout;
else lastout = out;
Con_DrawString( x, y, va( "in : %i %.2f k/s", netstat_graph[j].msgbytes, cls.netchan.flow[FLOW_INCOMING].avgkbytespersec ), colors );
y += 15;
Con_DrawString( x, y, va( "out: %i %.2f k/s", out, cls.netchan.flow[FLOW_OUTGOING].avgkbytespersec ), colors );
y += 15;
if( net_graph->value > 2 )
{
int loss = (int)(( packet_loss + PACKETLOSS_AVG_FRAC ) - 0.01 );
int choke = (int)(( packet_choke + PACKETCHOKE_AVG_FRAC ) - 0.01 );
Con_DrawString( x, y, va( "loss: %i choke: %i", loss, choke ), colors );
}
}
if( net_graph->value < 3 )
Con_DrawString( ptx, pty, va( "%i/s", (int)cl_cmdrate->value ), colors );
Con_DrawString( ptx, last_y, va( "%i/s" , (int)cl_updaterate->value ), colors );
Con_RestoreFont();
}
/*
@ -291,13 +420,13 @@ NetGraph_DrawDataSegment
*/
int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b, byte a )
{
int h = bytes / net_scale->value;
byte colors[4] = { r, g, b, a };
float h = bytes / net_scale->value;
byte colors[4] = { r, g, b, a };
fill->top -= h;
fill->top -= (int)h;
if( net_graphfillsegments->value )
fill->bottom = h;
if( net_graphsolid->value )
fill->bottom = (int)h;
else fill->bottom = 1;
if( fill->top > 1 )
@ -305,6 +434,7 @@ int NetGraph_DrawDataSegment( wrect_t *fill, int bytes, byte r, byte g, byte b,
NetGraph_DrawRect( fill, colors );
return 1;
}
return 0;
}
@ -350,9 +480,10 @@ NetGraph_DrawDataUsage
===========
*/
void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes )
void NetGraph_DrawDataUsage( int x, int y, int w )
{
int a, i, h, lastvalidh = 0, ping;
int pingheight = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2;
wrect_t fill = { 0 };
byte color[4];
@ -366,31 +497,53 @@ void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes )
if( !ping ) h = lastvalidh;
else lastvalidh = h;
if( h > net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2 )
h = net_graphheight->value - NETGRAPH_LERP_HEIGHT - 2;
if( h > pingheight )
h = pingheight;
fill.left = x + w - a - 1;
fill.top = y - h;
fill.right = 1;
fill.bottom = ping ? 1: h;
NetGraph_DrawRect( &fill, color );
if( !ping )
{
if( fill.bottom > 3 )
{
fill.bottom = 2;
NetGraph_DrawRect( &fill, color );
fill.top += fill.bottom - 2;
NetGraph_DrawRect( &fill, color );
}
else
{
NetGraph_DrawRect( &fill, color );
}
}
else
{
NetGraph_DrawRect( &fill, color );
}
fill.top = y;
fill.bottom = 1;
color[0] = 0; color[1] = 255; color[2] = 0; color[3] = 160;
color[0] = 0;
color[1] = 255;
color[2] = 0;
color[3] = 160;
NetGraph_DrawRect( &fill, color );
if( NetGraph_AtEdge( a, w ))
NetGraph_DrawRect( &fill, color );
if( net_graph->value < 2 )
continue;
color[0] = color[1] = color[2] = color[3] = 255;
fill.top = y - net_graphheight->value - 1;
fill.bottom = 1;
color[0] = color[1] = color[2] = color[3] = 255;
NetGraph_DrawRect( &fill, color );
if( NetGraph_AtEdge( a, w ))
NetGraph_DrawRect( &fill, color );
fill.top -= 1;
@ -418,21 +571,19 @@ void NetGraph_DrawDataUsage( int x, int y, int w, int maxmsgbytes )
if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].usr, 200, 200, 200, 128 ))
continue;
// special case for absolute usage
h = netstat_graph[i].msgbytes / net_scale->value;
color[0] = color[1] = color[2] = 240; color[3] = 255;
if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].voicebytes, 255, 255, 255, 255 ))
continue;
fill.top = y - net_graphheight->value - 1;
fill.bottom = 1;
fill.top = y - net_graphheight->value - 1 - h;
fill.top -= 2;
if( fill.top < 2 ) continue;
NetGraph_DrawRect( &fill, color );
if( !NetGraph_DrawDataSegment( &fill, netstat_graph[i].msgbytes, 240, 240, 240, 128 ))
continue;
}
if( net_graph->value >= 2 )
NetGraph_DrawHatches( x, y - net_graphheight->value - 1, maxmsgbytes );
NetGraph_DrawHatches( x, y - net_graphheight->value - 1 );
}
/*
@ -479,7 +630,6 @@ void SCR_DrawNetGraph( void )
wrect_t rect;
float avg_ping;
int ping_count;
int maxmsgbytes;
int w, x, y;
if( !host.developer )
@ -496,15 +646,27 @@ void SCR_DrawNetGraph( void )
NetGraph_GetScreenPos( &rect, &w, &x, &y );
NetGraph_GetFrameData( &maxmsgbytes, &avg_ping, &ping_count );
NetGraph_GetFrameData( &avg_ping, &ping_count );
NetGraph_DrawTextFields( x, y, w, rect, ping_count, avg_ping, packet_loss, packet_choke );
if( net_graph->value < 3 )
{
NetGraph_DrawTimes( rect, x, w );
NetGraph_DrawDataUsage( x, y, w, maxmsgbytes );
}
pglEnable( GL_BLEND );
pglDisable( GL_TEXTURE_2D );
pglTexEnvf( GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE );
pglBlendFunc( GL_SRC_ALPHA, GL_ONE );
pglBegin( GL_QUADS ); // draw all the fills as a long solid sequence of quads for speedup reasons
NetGraph_DrawTextFields( x, y, ping_count, avg_ping, packet_loss, packet_choke );
// NOTE: fill colors without texture at this point
NetGraph_DrawDataUsage( x, y, w );
NetGraph_DrawTimes( rect, x, w );
pglEnd();
pglColor4ub( 255, 255, 255, 255 );
pglEnable( GL_TEXTURE_2D );
pglDisable( GL_BLEND );
}
}
void CL_InitNetgraph( void )
@ -514,7 +676,7 @@ void CL_InitNetgraph( void )
net_scale = Cvar_Get( "net_scale", "5", FCVAR_ARCHIVE, "network usage graph scale level" );
net_graphwidth = Cvar_Get( "net_graphwidth", "192", FCVAR_ARCHIVE, "network usage graph width" );
net_graphheight = Cvar_Get( "net_graphheight", "64", FCVAR_ARCHIVE, "network usage graph height" );
net_graphfillsegments = Cvar_Get( "net_graphfillsegments", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
net_graphsolid = Cvar_Get( "net_graphsolid", "1", FCVAR_ARCHIVE, "fill segments in network usage graph" );
packet_loss = packet_choke = 0.0;
NetGraph_InitColors();

View File

@ -1865,7 +1865,8 @@ void CL_ParseServerMessage( sizebuf_t *msg )
}
}
cls_message_debug.parsing = false; // done
cl.frames[cl.parsecountmod].graphdata.msgbytes += MSG_GetNumBytesRead( msg ) - starting_count;
cls_message_debug.parsing = false; // done
// we don't know if it is ok to save a demo message until
// after we have parsed the frame

View File

@ -41,6 +41,7 @@ TEMPENTITY *cl_active_tents;
TEMPENTITY *cl_free_tents;
TEMPENTITY *cl_tempents = NULL; // entities pool
int cl_muzzleflash[MAX_MUZZLEFLASH]; // muzzle flashes
model_t *cl_particleTex = NULL;
/*
================
@ -57,6 +58,7 @@ void CL_RegisterMuzzleFlashes( void )
// update registration for shellchrome
cls.hChromeSprite = pfnSPR_Load( "sprites/shellchrome.spr" );
cl_particleTex = Mod_Handle( CL_FindModelIndex( "sprites/dot.spr" ));
}
/*
@ -1914,7 +1916,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[0] = MSG_ReadCoord( &buf );
pos[1] = MSG_ReadCoord( &buf );
pos[2] = MSG_ReadCoord( &buf );
CL_BlobExplosion( pos );
R_BlobExplosion( pos );
break;
case TE_SMOKE:
pos[0] = MSG_ReadCoord( &buf );
@ -1959,7 +1961,7 @@ void CL_ParseTempEntity( sizebuf_t *msg )
pos[2] = MSG_ReadCoord( &buf );
color = MSG_ReadByte( &buf );
count = MSG_ReadByte( &buf );
CL_ParticleExplosion2( pos, color, count );
R_ParticleExplosion2( pos, color, count );
break;
case TE_BSPDECAL:
pos[0] = MSG_ReadCoord( &buf );

View File

@ -19,12 +19,12 @@ GNU General Public License for more details.
// EfxAPI
struct particle_s *R_AllocParticle( void (*callback)( struct particle_s*, float ));
void CL_Explosion( vec3_t pos, int model, float scale, float framerate, int flags );
void CL_ParticleExplosion( const vec3_t org );
void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength );
void R_ParticleExplosion( const vec3_t org );
void R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength );
void R_Implosion( const vec3_t end, float radius, int count, float life );
void R_Blood( const vec3_t org, const vec3_t dir, int pcolor, int speed );
void R_BloodStream( const vec3_t org, const vec3_t dir, int pcolor, int speed );
void CL_BlobExplosion( const vec3_t org );
void R_BlobExplosion( const vec3_t org );
void R_EntityParticles( cl_entity_t *ent );
void R_FlickerParticles( const vec3_t org );
void R_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int count );
@ -33,7 +33,7 @@ void R_LavaSplash( const vec3_t org );
void R_TeleportSplash( const vec3_t org );
void R_RocketTrail( vec3_t start, vec3_t end, int type );
short R_LookupColor( byte r, byte g, byte b );
void CL_GetPackedColor( short *packed, short color );
void R_GetPackedColor( short *packed, short color );
void R_TracerEffect( const vec3_t start, const vec3_t end );
void R_UserTracerParticle( float *org, float *vel, float life, int colorIndex, float length, byte deathcontext, void (*deathfunc)( struct particle_s* ));
struct particle_s *R_TracerParticles( float *org, float *vel, float life );
@ -114,4 +114,6 @@ void TriRenderMode( int mode );
void TriCullFace( int mode );
void TriEnd( void );
extern model_t *cl_particleTex;
#endif//CL_TENT_H

View File

@ -622,6 +622,7 @@ extern convar_t *scr_viewsize;
extern convar_t *scr_download;
extern convar_t *scr_loading;
extern convar_t *scr_dark; // start from dark
extern convar_t *net_graph;
extern convar_t *rate;
//=============================================================================

View File

@ -407,6 +407,7 @@ void GL_ResetFogColor( void );
void R_SpriteInit( void );
void Mod_LoadSpriteModel( model_t *mod, const void *buffer, qboolean *loaded, uint texFlags );
mspriteframe_t *R_GetSpriteFrame( const model_t *pModel, int frame, float yaw );
void R_SetSpriteRendermode( const model_t *pModel );
void R_DrawSpriteModel( cl_entity_t *e );
//

View File

@ -113,12 +113,12 @@ short R_LookupColor( byte r, byte g, byte b )
/*
================
CL_GetPackedColor
R_GetPackedColor
in hardware mode does nothing
================
*/
void CL_GetPackedColor( short *packed, short color )
void R_GetPackedColor( short *packed, short color )
{
if( packed ) *packed = 0;
}
@ -139,9 +139,9 @@ void CL_InitParticles( void )
// this is used for EF_BRIGHTFIELD
for( i = 0; i < NUMVERTEXNORMALS; i++ )
{
cl_avelocities[i][0] = COM_RandomLong( 0, 255 ) * 0.01f;
cl_avelocities[i][1] = COM_RandomLong( 0, 255 ) * 0.01f;
cl_avelocities[i][2] = COM_RandomLong( 0, 255 ) * 0.01f;
cl_avelocities[i][0] = COM_RandomFloat( 0.0f, 2.55f );
cl_avelocities[i][1] = COM_RandomFloat( 0.0f, 2.55f );
cl_avelocities[i][2] = COM_RandomFloat( 0.0f, 2.55f );
}
tracerred = Cvar_Get( "tracerred", "0.8", 0, "tracer red component weight ( 0 - 1.0 )" );
@ -360,6 +360,7 @@ void CL_DrawParticles( double frametime )
float grav = frametime * clgame.movevars.gravity * 0.05f;
vec3_t right, up;
color24 *pColor;
int alpha;
float size;
if( !cl_draw_particles->value )
@ -370,13 +371,15 @@ void CL_DrawParticles( double frametime )
if( !cl_active_particles )
return; // nothing to draw?
GL_SetRenderMode( kRenderTransTexture );
GL_Bind( GL_TEXTURE0, cls.particleImage );
if( !TriSpriteTexture( cl_particleTex, 0 ))
return;
R_SetSpriteRendermode( cl_particleTex );
pglBegin( GL_QUADS );
for( p = cl_active_particles; p; p = p->next )
{
if( p->type != pt_blob )
if(( p->type != pt_blob ) || ( p->packedColor == 255 ))
{
size = PART_SIZE; // get initial size of particle
@ -386,7 +389,7 @@ void CL_DrawParticles( double frametime )
size += (p->org[2] - RI.vieworg[2]) * RI.cull_vforward[2];
if( size < 20.0f ) size = PART_SIZE;
else size = PART_SIZE + size * 0.004f;
else size = PART_SIZE + size * 0.002f;
// scale the axes by radius
VectorScale( RI.cull_vright, size, right );
@ -396,7 +399,11 @@ void CL_DrawParticles( double frametime )
pColor = &clgame.palette[p->color];
// FIXME: should we pass color through lightgamma table?
pglColor4ub( pColor->r, pColor->g, pColor->b, 255 );
alpha = 255 * (p->die - cl.time) * 2;
if( alpha > 255 || cl_draw_particles->value < 2.0f || p->type == pt_static )
alpha = 255;
pglColor4ub( pColor->r, pColor->g, pColor->b, alpha );
pglTexCoord2f( 0.0f, 1.0f );
pglVertex3f( p->org[0] - right[0] + up[0], p->org[1] - right[1] + up[1], p->org[2] - right[2] + up[2] );
@ -436,17 +443,34 @@ void CL_DrawParticles( double frametime )
p->ramp += time3;
if( p->ramp >= 8.0f ) p->die = -1.0f;
else p->color = ramp2[(int)p->ramp];
VectorMA( p->vel,-dvel, p->vel, p->vel );
VectorMA( p->vel,-frametime, p->vel, p->vel );
p->vel[2] -= grav;
break;
case pt_blob:
if( p->packedColor == 255 )
{
// normal blob explosion
VectorMA( p->vel, dvel, p->vel, p->vel );
p->vel[2] -= grav;
break;
}
case pt_blob2:
p->ramp += time2;
if( p->ramp >= 9.0f ) p->ramp = 0.0f;
p->color = gSparkRamp[(int)p->ramp];
VectorMA( p->vel, -frametime * 0.5f, p->vel, p->vel );
p->type = COM_RandomLong( 0, 3 ) ? pt_blob : pt_blob2;
p->vel[2] -= grav * 5.0f;
if( p->packedColor == 255 )
{
// normal blob explosion
p->vel[0] -= p->vel[0] * dvel;
p->vel[1] -= p->vel[1] * dvel;
p->vel[2] -= grav;
}
else
{
p->ramp += time2;
if( p->ramp >= 9.0f ) p->ramp = 0.0f;
p->color = gSparkRamp[(int)p->ramp];
VectorMA( p->vel, -frametime * 0.5f, p->vel, p->vel );
p->type = COM_RandomLong( 0, 3 ) ? pt_blob : pt_blob2;
p->vel[2] -= grav * 5.0f;
}
break;
case pt_grav:
p->vel[2] -= grav * 20.0f;
@ -519,6 +543,7 @@ void CL_DrawTracers( double frametime )
float scale, atten, gravity;
vec3_t screenLast, screen;
vec3_t start, end, delta;
int texWidth = 32;
particle_t *p;
if( !cl_draw_tracers->value )
@ -541,13 +566,16 @@ void CL_DrawTracers( double frametime )
if( !cl_active_tracers )
return; // nothing to draw?
if( !TriSpriteTexture( cl_particleTex, 0 ))
return;
R_SetSpriteRendermode( cl_particleTex );
R_GetSpriteParms( &texWidth, NULL, NULL, 0, cl_particleTex );
gravity = frametime * clgame.movevars.gravity;
scale = 1.0 - (frametime * 0.9);
if( scale < 0.0f ) scale = 0.0f;
GL_Bind( GL_TEXTURE0, cls.particleImage ); // FIXME: load a sprites/dot.spr instead
GL_SetRenderMode( kRenderTransAdd );
for( p = cl_active_tracers; p; p = p->next )
{
atten = (p->die - cl.time);
@ -580,7 +608,7 @@ void CL_DrawTracers( double frametime )
VectorSubtract( normal, tmp2, normal );
// compute four vertexes
VectorScale( normal, gTracerSize[p->type] * 2.0f, tmp );
VectorScale( normal, gTracerSize[p->type] * (texWidth / 16), tmp );
VectorSubtract( start, tmp, verts[0] );
VectorAdd( start, tmp, verts[1] );
VectorAdd( verts[0], delta, verts[2] );
@ -663,7 +691,6 @@ void R_EntityParticles( cl_entity_t *ent )
VectorSet( forward, cp * cy, cp * sy, -sp );
p->die = cl.time + 0.001f;
p->type = pt_explode;
p->color = 111; // yellow
VectorMAMAM( 1.0f, ent->origin, 64.0f, cl_avertexnormals[i], 16.0f, forward, p->org );
@ -672,11 +699,11 @@ void R_EntityParticles( cl_entity_t *ent )
/*
===============
CL_ParticleExplosion
R_ParticleExplosion
===============
*/
void CL_ParticleExplosion( const vec3_t org )
void R_ParticleExplosion( const vec3_t org )
{
particle_t *p;
int i, j;
@ -686,38 +713,28 @@ void CL_ParticleExplosion( const vec3_t org )
p = R_AllocParticle( NULL );
if( !p ) return;
p->die += 5.0f;
p->die = cl.time + 5.0f;
p->ramp = COM_RandomLong( 0, 3 );
p->color = ramp1[0];
p->ramp = rand() & 3;
if( i & 1 )
for( j = 0; j < 3; j++ )
{
p->type = pt_explode;
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
}
else
{
p->type = pt_explode2;
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f );
p->vel[j] = COM_RandomFloat( -256.0f, 256.0f );
}
if( i & 1 ) p->type = pt_explode;
else p->type = pt_explode2;
}
}
/*
===============
CL_ParticleExplosion2
R_ParticleExplosion2
===============
*/
void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
void R_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
{
int i, j;
int colorMod = 0;
@ -728,27 +745,28 @@ void CL_ParticleExplosion2( const vec3_t org, int colorStart, int colorLength )
p = R_AllocParticle( NULL );
if( !p ) return;
p->die += 0.3f;
p->die = cl.time + 0.3f;
p->color = colorStart + ( colorMod % colorLength );
p->packedColor = 255; // use old code for blob particles
colorMod++;
p->type = pt_blob;
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f );
p->vel[j] = COM_RandomFloat( -256.0f, 256.0f );
}
}
}
/*
===============
CL_BlobExplosion
R_BlobExplosion
===============
*/
void CL_BlobExplosion( const vec3_t org )
void R_BlobExplosion( const vec3_t org )
{
particle_t *p;
int i, j;
@ -758,29 +776,24 @@ void CL_BlobExplosion( const vec3_t org )
p = R_AllocParticle( NULL );
if( !p ) return;
p->die += 1.0f + (rand() & 8) * 0.05f;
p->die = cl.time + COM_RandomFloat( 2.0f, 2.4f );
p->packedColor = 255; // use old code for blob particles
if( i & 1 )
{
p->type = pt_explode;
p->color = 66 + rand() % 6;
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
p->type = pt_blob;
p->color = COM_RandomLong( 66, 71 );
}
else
{
p->type = pt_explode2;
p->color = 150 + rand() % 6;
p->type = pt_blob2;
p->color = COM_RandomLong( 150, 155 );
}
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + ((rand() % 32) - 16);
p->vel[j] = (rand() % 512) - 256;
}
for( j = 0; j < 3; j++ )
{
p->org[j] = org[j] + COM_RandomFloat( -16.0f, 16.0f );
p->vel[j] = COM_RandomFloat( -256.0f, 256.0f );
}
}
}
@ -800,7 +813,7 @@ void R_RunParticleEffect( const vec3_t org, const vec3_t dir, int color, int cou
if( count == 1024 )
{
// rocket explosion
CL_ParticleExplosion( org );
R_ParticleExplosion( org );
return;
}

View File

@ -450,6 +450,38 @@ void Mod_UnloadSpriteModel( model_t *mod )
================
R_GetSpriteFrame
assume pModel is valid
================
*/
void R_SetSpriteRendermode( const model_t *pModel )
{
msprite_t *psprite;
if( !pModel ) return;
psprite = (msprite_t *)pModel->cache.data;
if( !psprite ) return;
switch( psprite->texFormat )
{
case SPR_NORMAL:
GL_SetRenderMode( kRenderNormal );
break;
case SPR_ADDITIVE:
GL_SetRenderMode( kRenderTransAdd );
break;
case SPR_INDEXALPHA:
GL_SetRenderMode( kRenderTransTexture );
break;
case SPR_ALPHTEST:
GL_SetRenderMode( kRenderTransAlpha );
break;
}
}
/*
================
R_GetSpriteFrame
assume pModel is valid
================
*/

View File

@ -2039,7 +2039,7 @@ void Con_DrawVersion( void )
if( !host.force_draw_version )
{
if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 )
if(( cls.key_dest != key_menu && !draw_version ) || CL_IsDevOverviewMode() == 2 || net_graph->value )
return;
}

View File

@ -314,6 +314,9 @@ void SV_ActivateServer( void )
// ricochet sprite
pfnPrecacheModel( "sprites/richo1.spr" );
// particle & tracer texture
pfnPrecacheModel( "sprites/dot.spr" );
// Activate the DLL server code
svgame.dllFuncs.pfnServerActivate( svgame.edicts, svgame.numEntities, svgame.globals->maxClients );