diff --git a/quakespasm/Quake/cl_input.c b/quakespasm/Quake/cl_input.c index 6e5fcdb5b..7cdbf77e6 100644 --- a/quakespasm/Quake/cl_input.c +++ b/quakespasm/Quake/cl_input.c @@ -298,8 +298,6 @@ void CL_BaseMove (usercmd_t *cmd) if (cls.signon != SIGNONS) return; - CL_AdjustAngles (); - Q_memset (cmd, 0, sizeof(*cmd)); if (in_strafe.state & 1) @@ -348,44 +346,47 @@ void CL_SendMove (const usercmd_t *cmd) buf.cursize = 0; buf.data = data; - cl.cmd = *cmd; + if (cmd) + { + cl.cmd = *cmd; -// -// send the movement message -// - MSG_WriteByte (&buf, clc_move); + // + // send the movement message + // + MSG_WriteByte (&buf, clc_move); - MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times + MSG_WriteFloat (&buf, cl.mtime[0]); // so server can get ping times - for (i=0 ; i<3 ; i++) - //johnfitz -- 16-bit angles for PROTOCOL_FITZQUAKE - if (cl.protocol == PROTOCOL_NETQUAKE) - MSG_WriteAngle (&buf, cl.viewangles[i], cl.protocolflags); - else - MSG_WriteAngle16 (&buf, cl.viewangles[i], cl.protocolflags); - //johnfitz + for (i=0 ; i<3 ; i++) + //johnfitz -- 16-bit angles for PROTOCOL_FITZQUAKE + if (cl.protocol == PROTOCOL_NETQUAKE) + MSG_WriteAngle (&buf, cl.viewangles[i], cl.protocolflags); + else + MSG_WriteAngle16 (&buf, cl.viewangles[i], cl.protocolflags); + //johnfitz - MSG_WriteShort (&buf, cmd->forwardmove); - MSG_WriteShort (&buf, cmd->sidemove); - MSG_WriteShort (&buf, cmd->upmove); + MSG_WriteShort (&buf, cmd->forwardmove); + MSG_WriteShort (&buf, cmd->sidemove); + MSG_WriteShort (&buf, cmd->upmove); -// -// send button bits -// - bits = 0; + // + // send button bits + // + bits = 0; - if ( in_attack.state & 3 ) - bits |= 1; - in_attack.state &= ~2; + if ( in_attack.state & 3 ) + bits |= 1; + in_attack.state &= ~2; - if (in_jump.state & 3) - bits |= 2; - in_jump.state &= ~2; + if (in_jump.state & 3) + bits |= 2; + in_jump.state &= ~2; - MSG_WriteByte (&buf, bits); + MSG_WriteByte (&buf, bits); - MSG_WriteByte (&buf, in_impulse); - in_impulse = 0; + MSG_WriteByte (&buf, in_impulse); + in_impulse = 0; + } // // deliver the message diff --git a/quakespasm/Quake/cl_main.c b/quakespasm/Quake/cl_main.c index 5d870bd9b..74d61c87d 100644 --- a/quakespasm/Quake/cl_main.c +++ b/quakespasm/Quake/cl_main.c @@ -62,6 +62,7 @@ int cl_numvisedicts; entity_t *cl_visedicts[MAX_VISEDICTS]; extern cvar_t r_lerpmodels, r_lerpmove; //johnfitz +extern float host_netinterval; //Spike /* ===================== @@ -363,7 +364,7 @@ float CL_LerpPoint (void) f = cl.mtime[0] - cl.mtime[1]; - if (!f || cls.timedemo || sv.active) + if (!f || cls.timedemo || (sv.active && !host_netinterval)) { cl.time = cl.mtime[0]; return 1; @@ -663,6 +664,25 @@ int CL_ReadFromServer (void) return 0; } +/* +================= +CL_UpdateViewAngles + +Spike: split from CL_SendCmd, to do clientside viewangle changes separately from outgoing packets. +================= +*/ +void CL_AccumulateCmd (void) +{ + if (cls.signon == SIGNONS) + { + //basic keyboard looking + CL_AdjustAngles (); + + //accumulate movement from other devices + IN_Move (&cl.pendingcmd); + } +} + /* ================= CL_SendCmd @@ -681,11 +701,16 @@ void CL_SendCmd (void) CL_BaseMove (&cmd); // allow mice or other external controllers to add to the move - IN_Move (&cmd); + cmd.forwardmove += cl.pendingcmd.forwardmove; + cmd.sidemove += cl.pendingcmd.sidemove; + cmd.upmove += cl.pendingcmd.upmove; // send the unreliable message CL_SendMove (&cmd); } + else + CL_SendMove (NULL); + memset(&cl.pendingcmd, 0, sizeof(cl.pendingcmd)); if (cls.demoplayback) { diff --git a/quakespasm/Quake/cl_parse.c b/quakespasm/Quake/cl_parse.c index 75bacdafd..2a06b0b46 100644 --- a/quakespasm/Quake/cl_parse.c +++ b/quakespasm/Quake/cl_parse.c @@ -3,6 +3,7 @@ Copyright (C) 1996-2001 Id Software, Inc. Copyright (C) 2002-2009 John Fitzgibbons and others Copyright (C) 2007-2008 Kristian Duske Copyright (C) 2010-2014 QuakeSpasm developers +Copyright (C) 2016 Spike This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License diff --git a/quakespasm/Quake/client.h b/quakespasm/Quake/client.h index 1c7db1819..00619ebeb 100644 --- a/quakespasm/Quake/client.h +++ b/quakespasm/Quake/client.h @@ -146,6 +146,7 @@ typedef struct // doesn't accidentally do something the // first frame usercmd_t cmd; // last command sent to the server + usercmd_t pendingcmd; // accumulated state from mice+joysticks. // information for local display int stats[MAX_CL_STATS]; // health, etc @@ -317,9 +318,11 @@ extern kbutton_t in_strafe; extern kbutton_t in_speed; void CL_InitInput (void); +void CL_AccumulateCmd (void); void CL_SendCmd (void); void CL_SendMove (const usercmd_t *cmd); int CL_ReadFromServer (void); +void CL_AdjustAngles (void); void CL_BaseMove (usercmd_t *cmd); void CL_ParseTEnt (void); diff --git a/quakespasm/Quake/cmd.c b/quakespasm/Quake/cmd.c index 783475fdd..bd459baba 100644 --- a/quakespasm/Quake/cmd.c +++ b/quakespasm/Quake/cmd.c @@ -137,9 +137,17 @@ void Cbuf_InsertText (const char *text) } } +//Spike: for renderer/server isolation +void Cbuf_Waited(void) +{ + cmd_wait = false; +} + /* ============ Cbuf_Execute + +Spike: reworked 'wait' for renderer/server rate independance ============ */ void Cbuf_Execute (void) @@ -149,7 +157,7 @@ void Cbuf_Execute (void) char line[1024]; int quotes; - while (cmd_text.cursize) + while (cmd_text.cursize && !cmd_wait) { // find a \n or ; line break text = (char *)cmd_text.data; @@ -191,13 +199,6 @@ void Cbuf_Execute (void) // execute the command line Cmd_ExecuteString (line, src_command); - - if (cmd_wait) - { // skip out while text still remains in buffer, leaving it - // for next frame - cmd_wait = false; - break; - } } } diff --git a/quakespasm/Quake/cmd.h b/quakespasm/Quake/cmd.h index 9f688e218..d2ad7bf9f 100644 --- a/quakespasm/Quake/cmd.h +++ b/quakespasm/Quake/cmd.h @@ -57,6 +57,13 @@ void Cbuf_Execute (void); // Normally called once per frame, but may be explicitly invoked. // Do not call inside a command function! +void Cbuf_Waited (void); +//In vanilla, the 'wait' command is used by both input configs and servers. +//mods do hacky stuff like syncing waits to StartFrame calls. +//thankfully, c2s packets and server logic can both happen at the same intervals. +//so wait sets a flag to inhibit execution of more commands, and we only clear it once we've run a network frame. +//so this function lets the cbuf know when to clear the flag again (instead of part of cbuf_execute). + //=========================================================================== /* diff --git a/quakespasm/Quake/gl_model.c b/quakespasm/Quake/gl_model.c index 2e3c31e3b..5de03a82b 100644 --- a/quakespasm/Quake/gl_model.c +++ b/quakespasm/Quake/gl_model.c @@ -924,7 +924,6 @@ void Mod_LoadTexinfo (lump_t *l) texinfo_t *in; mtexinfo_t *out; int i, j, count, miptex; - float len1, len2; int missing = 0; //johnfitz in = (texinfo_t *)(mod_base + l->fileofs); @@ -943,23 +942,6 @@ void Mod_LoadTexinfo (lump_t *l) out->vecs[0][j] = LittleFloat (in->vecs[0][j]); out->vecs[1][j] = LittleFloat (in->vecs[1][j]); } - len1 = VectorLength (out->vecs[0]); - len2 = VectorLength (out->vecs[1]); - len1 = (len1 + len2)/2; - if (len1 < 0.32) - out->mipadjust = 4; - else if (len1 < 0.49) - out->mipadjust = 3; - else if (len1 < 0.99) - out->mipadjust = 2; - else - out->mipadjust = 1; -#if 0 - if (len1 + len2 < 0.001) - out->mipadjust = 1; // don't crash - else - out->mipadjust = 1 / floor((len1+len2)/2 + 0.1); -#endif miptex = LittleLong (in->miptex); out->flags = LittleLong (in->flags); diff --git a/quakespasm/Quake/gl_model.h b/quakespasm/Quake/gl_model.h index 9eeaebdd2..7135774f5 100644 --- a/quakespasm/Quake/gl_model.h +++ b/quakespasm/Quake/gl_model.h @@ -123,7 +123,6 @@ typedef struct typedef struct { float vecs[2][4]; - float mipadjust; texture_t *texture; int flags; } mtexinfo_t; @@ -141,7 +140,6 @@ typedef struct glpoly_s typedef struct msurface_s { int visframe; // should be drawn when node is crossed - qboolean culled; // johnfitz -- for frustum culling float mins[3]; // johnfitz -- for frustum culling float maxs[3]; // johnfitz -- for frustum culling diff --git a/quakespasm/Quake/gl_rmain.c b/quakespasm/Quake/gl_rmain.c index ffad937ee..a41d8b1de 100644 --- a/quakespasm/Quake/gl_rmain.c +++ b/quakespasm/Quake/gl_rmain.c @@ -272,48 +272,21 @@ qboolean R_CullBox (vec3_t emins, vec3_t emaxs) { int i; mplane_t *p; + byte signbits; + float vec[3]; for (i = 0;i < 4;i++) { p = frustum + i; - switch(p->signbits) - { - default: - case 0: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) - return true; - break; - case 1: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emaxs[2] < p->dist) - return true; - break; - case 2: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) - return true; - break; - case 3: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emaxs[2] < p->dist) - return true; - break; - case 4: - if (p->normal[0]*emaxs[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) - return true; - break; - case 5: - if (p->normal[0]*emins[0] + p->normal[1]*emaxs[1] + p->normal[2]*emins[2] < p->dist) - return true; - break; - case 6: - if (p->normal[0]*emaxs[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) - return true; - break; - case 7: - if (p->normal[0]*emins[0] + p->normal[1]*emins[1] + p->normal[2]*emins[2] < p->dist) - return true; - break; - } + signbits = p->signbits; + vec[0] = ((signbits % 2)<1) ? emaxs[0] : emins[0]; + vec[1] = ((signbits % 4)<2) ? emaxs[1] : emins[1]; + vec[2] = ((signbits % 8)<4) ? emaxs[2] : emins[2]; + if (p->normal[0]*vec[0] + p->normal[1]*vec[1] + p->normal[2]*vec[2] < p->dist) + return true; } return false; } + /* =============== R_CullModelForEntity -- johnfitz -- uses correct bounds based on rotation @@ -585,8 +558,6 @@ void R_SetupView (void) R_MarkSurfaces (); //johnfitz -- create texture chains from PVS - R_CullSurfaces (); //johnfitz -- do after R_SetFrustum and R_MarkSurfaces - R_UpdateWarpTextures (); //johnfitz -- do this before R_Clear R_Clear (); diff --git a/quakespasm/Quake/gl_rmisc.c b/quakespasm/Quake/gl_rmisc.c index 4aac82214..becbbcaa6 100644 --- a/quakespasm/Quake/gl_rmisc.c +++ b/quakespasm/Quake/gl_rmisc.c @@ -86,17 +86,6 @@ static void R_SetClearColor_f (cvar_t *var) glClearColor (rgb[0]/255.0,rgb[1]/255.0,rgb[2]/255.0,0); } -/* -==================== -R_Novis_f -- johnfitz -==================== -*/ -static void R_VisChanged (cvar_t *var) -{ - extern int vis_changed; - vis_changed = 1; -} - /* =============== R_Model_ExtraFlags_List_f -- johnfitz -- called when r_nolerp_list or r_noshadow_list cvar changes @@ -189,7 +178,6 @@ void R_Init (void) Cvar_SetCallback (&r_wateralpha, R_SetWateralpha_f); Cvar_RegisterVariable (&r_dynamic); Cvar_RegisterVariable (&r_novis); - Cvar_SetCallback (&r_novis, R_VisChanged); Cvar_RegisterVariable (&r_speeds); Cvar_RegisterVariable (&r_pos); @@ -214,7 +202,6 @@ void R_Init (void) Cvar_RegisterVariable (&r_drawflat); Cvar_RegisterVariable (&r_flatlightstyles); Cvar_RegisterVariable (&r_oldskyleaf); - Cvar_SetCallback (&r_oldskyleaf, R_VisChanged); Cvar_RegisterVariable (&r_drawworld); Cvar_RegisterVariable (&r_showtris); Cvar_RegisterVariable (&r_showbboxes); diff --git a/quakespasm/Quake/gl_sky.c b/quakespasm/Quake/gl_sky.c index 273b8d259..e55ab56d3 100644 --- a/quakespasm/Quake/gl_sky.c +++ b/quakespasm/Quake/gl_sky.c @@ -550,8 +550,7 @@ void Sky_ProcessTextureChains (void) continue; for (s = t->texturechains[chain_world]; s; s = s->texturechain) - if (!s->culled) - Sky_ProcessPoly (s->polys); + Sky_ProcessPoly (s->polys); } } diff --git a/quakespasm/Quake/glquake.h b/quakespasm/Quake/glquake.h index 315be98b0..0f4ec391d 100644 --- a/quakespasm/Quake/glquake.h +++ b/quakespasm/Quake/glquake.h @@ -341,7 +341,6 @@ void R_NewGame (void); void R_AnimateLight (void); void R_MarkSurfaces (void); -void R_CullSurfaces (void); qboolean R_CullBox (vec3_t emins, vec3_t emaxs); void R_StoreEfrags (efrag_t **ppefrag); qboolean R_CullModelForEntity (entity_t *e); diff --git a/quakespasm/Quake/host.c b/quakespasm/Quake/host.c index ad60160f7..e549fa86c 100644 --- a/quakespasm/Quake/host.c +++ b/quakespasm/Quake/host.c @@ -56,10 +56,10 @@ client_t *host_client; // current client jmp_buf host_abortserver; byte *host_colormap; - +float host_netinterval = 1.0/72; cvar_t host_framerate = {"host_framerate","0",CVAR_NONE}; // set for slow motion cvar_t host_speeds = {"host_speeds","0",CVAR_NONE}; // set for running times -cvar_t host_maxfps = {"host_maxfps", "72", CVAR_ARCHIVE}; //johnfitz +cvar_t host_maxfps = {"host_maxfps", "200", CVAR_ARCHIVE}; //johnfitz cvar_t host_timescale = {"host_timescale", "0", CVAR_NONE}; //johnfitz cvar_t max_edicts = {"max_edicts", "8192", CVAR_NONE}; //johnfitz //ericw -- changed from 2048 to 8192, removed CVAR_ARCHIVE @@ -105,8 +105,21 @@ Max_Fps_f -- ericw */ static void Max_Fps_f (cvar_t *var) { - if (var->value > 72) - Con_Warning ("host_maxfps above 72 breaks physics.\n"); + if (var->value > 72 || var->value <= 0) + { + if (!host_netinterval) + Con_Printf ("Using renderer/network isolation.\n"); + host_netinterval = 1.0/72; + } + else + { + if (host_netinterval) + Con_Printf ("Disabling renderer/network isolation.\n"); + host_netinterval = 0; + + if (var->value > 72) + Con_Warning ("host_maxfps above 72 breaks physics.\n"); + } } /* @@ -571,7 +584,7 @@ qboolean Host_FilterTime (float time) //johnfitz -- max fps cvar maxfps = CLAMP (10.0, host_maxfps.value, 1000.0); - if (!cls.timedemo && realtime - oldrealtime < 1.0/maxfps) + if (host_maxfps.value && !cls.timedemo && realtime - oldrealtime < 1.0/maxfps) return false; // framerate is too high //johnfitz @@ -584,8 +597,8 @@ qboolean Host_FilterTime (float time) //johnfitz else if (host_framerate.value > 0) host_frametime = host_framerate.value; - else // don't allow really long or short frames - host_frametime = CLAMP (0.001, host_frametime, 0.1); //johnfitz -- use CLAMP + else if (host_maxfps.value)// don't allow really long or short frames + host_frametime = CLAMP (0.0001, host_frametime, 0.1); //johnfitz -- use CLAMP return true; } @@ -667,8 +680,9 @@ Host_Frame Runs all active servers ================== */ -void _Host_Frame (float time) +void _Host_Frame (double time) { + static double accumtime = 0; static double time1 = 0; static double time2 = 0; static double time3 = 0; @@ -681,6 +695,7 @@ void _Host_Frame (float time) rand (); // decide the simulation time + accumtime += host_netinterval?CLAMP(0, time, 0.2):0; //for renderer/server isolation if (!Host_FilterTime (time)) return; // don't run too fast, or packets will flood out @@ -692,37 +707,39 @@ void _Host_Frame (float time) // allow mice or other external controllers to add commands IN_Commands (); +//check the stdin for commands (dedicated servers) + Host_GetConsoleCommands (); + // process console commands Cbuf_Execute (); NET_Poll(); -// if running the server locally, make intentions now - if (sv.active) - CL_SendCmd (); + CL_AccumulateCmd (); -//------------------- -// -// server operations -// -//------------------- - -// check for commands typed to the host - Host_GetConsoleCommands (); - - if (sv.active) - Host_ServerFrame (); - -//------------------- -// -// client operations -// -//------------------- - -// if running the server remotely, send intentions now after -// the incoming messages have been read - if (!sv.active) + //Run the server+networking (client->server->client), at a different rate from everyt + if (accumtime >= host_netinterval) + { + float realframetime = host_frametime; + if (host_netinterval) + { + host_frametime = q_max(accumtime, host_netinterval); + accumtime -= host_frametime; + if (host_timescale.value > 0) + host_frametime *= host_timescale.value; + else if (host_framerate.value) + host_frametime = host_framerate.value; + } + else + accumtime -= host_netinterval; CL_SendCmd (); + if (sv.active) + { + Host_ServerFrame (); + } + host_frametime = realframetime; + Cbuf_Waited(); + } // fetch results from server if (cls.state == ca_connected) @@ -765,7 +782,7 @@ void _Host_Frame (float time) } -void Host_Frame (float time) +void Host_Frame (double time) { double time1, time2; static double timetotal; diff --git a/quakespasm/Quake/quakedef.h b/quakespasm/Quake/quakedef.h index 85a7e7ba7..32d86a8e2 100644 --- a/quakespasm/Quake/quakedef.h +++ b/quakespasm/Quake/quakedef.h @@ -310,7 +310,7 @@ FUNC_NORETURN void Host_EndGame (const char *message, ...) FUNC_PRINTF(1,2); #pragma aux Host_Error aborts; #pragma aux Host_EndGame aborts; #endif -void Host_Frame (float time); +void Host_Frame (double time); void Host_Quit_f (void); void Host_ClientCommands (const char *fmt, ...) FUNC_PRINTF(1,2); void Host_ShutdownServer (qboolean crash); diff --git a/quakespasm/Quake/r_world.c b/quakespasm/Quake/r_world.c index cdc8fe81e..52b4bb65f 100644 --- a/quakespasm/Quake/r_world.c +++ b/quakespasm/Quake/r_world.c @@ -28,8 +28,6 @@ extern cvar_t gl_fullbrights, r_drawflat, gl_overbright, r_oldwater, r_oldskylea byte *SV_FatPVS (vec3_t org, qmodel_t *worldmodel); -int vis_changed; //if true, force pvs to be refreshed - //============================================================================== // // SETUP CHAINS @@ -69,6 +67,26 @@ void R_ChainSurface (msurface_t *surf, texchain_t chain) surf->texinfo->texture->texturechains[chain] = surf; } +/* +================ +R_BackFaceCull -- johnfitz -- returns true if the surface is facing away from vieworg +================ +*/ +qboolean R_BackFaceCull (msurface_t *surf) +{ + double dot; + + if (surf->plane->type < 3) + dot = r_refdef.vieworg[surf->plane->type] - surf->plane->dist; + else + dot = DotProduct (r_refdef.vieworg, surf->plane->normal) - surf->plane->dist; + + if ((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) + return true; + + return false; +} + /* =============== R_MarkSurfaces -- johnfitz -- mark surfaces based on PVS and rebuild texture chains @@ -78,7 +96,6 @@ void R_MarkSurfaces (void) { byte *vis; mleaf_t *leaf; - mnode_t *node; msurface_t *surf, **mark; int i, j; qboolean nearwaterportal; @@ -102,20 +119,12 @@ void R_MarkSurfaces (void) else vis = Mod_LeafPVS (r_viewleaf, cl.worldmodel); - // if surface chains don't need regenerating, just add static entities and return - if (r_oldviewleaf == r_viewleaf && !vis_changed && !nearwaterportal) - { - leaf = &cl.worldmodel->leafs[1]; - for (i=0 ; inumleafs ; i++, leaf++) - if (vis[i>>3] & (1<<(i&7))) - if (leaf->efrags) - R_StoreEfrags (&leaf->efrags); - return; - } - - vis_changed = false; r_visframecount++; - r_oldviewleaf = r_viewleaf; + + // set all chains to null + for (i=0 ; inumtextures ; i++) + if (cl.worldmodel->textures[i]) + cl.worldmodel->textures[i]->texturechains[chain_world] = NULL; // iterate through leaves, marking surfaces leaf = &cl.worldmodel->leafs[1]; @@ -123,146 +132,32 @@ void R_MarkSurfaces (void) { if (vis[i>>3] & (1<<(i&7))) { + if (R_CullBox(leaf->minmaxs, leaf->minmaxs + 3)) + continue; + if (r_oldskyleaf.value || leaf->contents != CONTENTS_SKY) for (j=0, mark = leaf->firstmarksurface; jnummarksurfaces; j++, mark++) - (*mark)->visframe = r_visframecount; + { + surf = *mark; + if (surf->visframe != r_visframecount) + { + surf->visframe = r_visframecount; + if (!R_CullBox(surf->mins, surf->maxs) && !R_BackFaceCull (surf)) + { + rs_brushpolys++; //count wpolys here + R_ChainSurface(surf, chain_world); + R_RenderDynamicLightmaps(surf); + if (surf->texinfo->texture->warpimage) + surf->texinfo->texture->update_warp = true; + } + } + } // add static models if (leaf->efrags) R_StoreEfrags (&leaf->efrags); } } - - // set all chains to null - for (i=0 ; inumtextures ; i++) - if (cl.worldmodel->textures[i]) - cl.worldmodel->textures[i]->texturechains[chain_world] = NULL; - - // rebuild chains - -#if 1 - //iterate through surfaces one node at a time to rebuild chains - //need to do it this way if we want to work with tyrann's skip removal tool - //becuase his tool doesn't actually remove the surfaces from the bsp surfaces lump - //nor does it remove references to them in each leaf's marksurfaces list - for (i=0, node = cl.worldmodel->nodes ; inumnodes ; i++, node++) - for (j=0, surf=&cl.worldmodel->surfaces[node->firstsurface] ; jnumsurfaces ; j++, surf++) - if (surf->visframe == r_visframecount) - { - R_ChainSurface(surf, chain_world); - } -#else - //the old way - surf = &cl.worldmodel->surfaces[cl.worldmodel->firstmodelsurface]; - for (i=0 ; inummodelsurfaces ; i++, surf++) - { - if (surf->visframe == r_visframecount) - { - R_ChainSurface(surf, chain_world); - } - } -#endif -} - -/* -================ -R_BackFaceCull -- johnfitz -- returns true if the surface is facing away from vieworg -================ -*/ -qboolean R_BackFaceCull (msurface_t *surf) -{ - double dot; - - switch (surf->plane->type) - { - case PLANE_X: - dot = r_refdef.vieworg[0] - surf->plane->dist; - break; - case PLANE_Y: - dot = r_refdef.vieworg[1] - surf->plane->dist; - break; - case PLANE_Z: - dot = r_refdef.vieworg[2] - surf->plane->dist; - break; - default: - dot = DotProduct (r_refdef.vieworg, surf->plane->normal) - surf->plane->dist; - break; - } - - if ((dot < 0) ^ !!(surf->flags & SURF_PLANEBACK)) - return true; - - return false; -} - -/* -================ -R_CullSurfaces -- johnfitz -================ -*/ -void R_CullSurfaces (void) -{ - msurface_t *s; - int i; - texture_t *t; - - if (!r_drawworld_cheatsafe) - return; - -// ericw -- instead of testing (s->visframe == r_visframecount) on all world -// surfaces, use the chained surfaces, which is exactly the same set of sufaces - for (i=0 ; inumtextures ; i++) - { - t = cl.worldmodel->textures[i]; - - if (!t || !t->texturechains[chain_world]) - continue; - - for (s = t->texturechains[chain_world]; s; s = s->texturechain) - { - if (R_CullBox(s->mins, s->maxs) || R_BackFaceCull (s)) - s->culled = true; - else - { - s->culled = false; - rs_brushpolys++; //count wpolys here - if (s->texinfo->texture->warpimage) - s->texinfo->texture->update_warp = true; - } - } - } -} - -/* -================ -R_BuildLightmapChains -- johnfitz -- used for r_lightmap 1 - -ericw -- now always used at the start of R_DrawTextureChains for the -mh dynamic lighting speedup -================ -*/ -void R_BuildLightmapChains (qmodel_t *model, texchain_t chain) -{ - texture_t *t; - msurface_t *s; - int i; - - // clear lightmap chains (already done in r_marksurfaces, but clearing them here to be safe becuase of r_stereo) - for (i=0 ; inumtextures ; i++) - { - t = model->textures[i]; - - if (!t || !t->texturechains[chain]) - continue; - - for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) - R_RenderDynamicLightmaps (s); - } } //============================================================================== @@ -324,19 +219,17 @@ void R_DrawTextureChains_ShowTris (qmodel_t *model, texchain_t chain) if (r_oldwater.value && t->texturechains[chain] && (t->texturechains[chain]->flags & SURF_DRAWTURB)) { for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) - for (p = s->polys->next; p; p = p->next) - { - DrawGLTriangleFan (p); - } + for (p = s->polys->next; p; p = p->next) + { + DrawGLTriangleFan (p); + } } else { for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) - { - DrawGLTriangleFan (s->polys); - } + { + DrawGLTriangleFan (s->polys); + } } } } @@ -362,26 +255,24 @@ void R_DrawTextureChains_Drawflat (qmodel_t *model, texchain_t chain) if (r_oldwater.value && t->texturechains[chain] && (t->texturechains[chain]->flags & SURF_DRAWTURB)) { for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) - for (p = s->polys->next; p; p = p->next) - { - srand((unsigned int) (uintptr_t) p); - glColor3f (rand()%256/255.0, rand()%256/255.0, rand()%256/255.0); - DrawGLPoly (p); - rs_brushpasses++; - } - } - else - { - for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + for (p = s->polys->next; p; p = p->next) { - srand((unsigned int) (uintptr_t) s->polys); + srand((unsigned int) (uintptr_t) p); glColor3f (rand()%256/255.0, rand()%256/255.0, rand()%256/255.0); - DrawGLPoly (s->polys); + DrawGLPoly (p); rs_brushpasses++; } } + else + { + for (s = t->texturechains[chain]; s; s = s->texturechain) + { + srand((unsigned int) (uintptr_t) s->polys); + glColor3f (rand()%256/255.0, rand()%256/255.0, rand()%256/255.0); + DrawGLPoly (s->polys); + rs_brushpasses++; + } + } } glColor3f (1,1,1); srand ((int) (cl.time * 1000)); @@ -410,16 +301,15 @@ void R_DrawTextureChains_Glow (qmodel_t *model, entity_t *ent, texchain_t chain) bound = false; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - GL_Bind (glt); - bound = true; - } - DrawGLPoly (s->polys); - rs_brushpasses++; + GL_Bind (glt); + bound = true; } + DrawGLPoly (s->polys); + rs_brushpasses++; + } } } @@ -527,30 +417,29 @@ void R_DrawTextureChains_Multitexture (qmodel_t *model, entity_t *ent, texchain_ bound = false; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); + GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); - if (t->texturechains[chain]->flags & SURF_DRAWFENCE) - glEnable (GL_ALPHA_TEST); // Flip alpha test back on + if (t->texturechains[chain]->flags & SURF_DRAWFENCE) + glEnable (GL_ALPHA_TEST); // Flip alpha test back on - GL_EnableMultitexture(); // selects TEXTURE1 - bound = true; - } - GL_Bind (lightmap[s->lightmaptexturenum].texture); - glBegin(GL_POLYGON); - v = s->polys->verts[0]; - for (j=0 ; jpolys->numverts ; j++, v+= VERTEXSIZE) - { - GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]); - GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]); - glVertex3fv (v); - } - glEnd (); - rs_brushpasses++; + GL_EnableMultitexture(); // selects TEXTURE1 + bound = true; + } + GL_Bind (lightmap[s->lightmaptexturenum].texture); + glBegin(GL_POLYGON); + v = s->polys->verts[0]; + for (j=0 ; jpolys->numverts ; j++, v+= VERTEXSIZE) + { + GL_MTexCoord2fFunc (GL_TEXTURE0_ARB, v[3], v[4]); + GL_MTexCoord2fFunc (GL_TEXTURE1_ARB, v[5], v[6]); + glVertex3fv (v); } + glEnd (); + rs_brushpasses++; + } GL_DisableMultitexture(); // selects TEXTURE0 if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE) @@ -582,16 +471,15 @@ void R_DrawTextureChains_NoTexture (qmodel_t *model, texchain_t chain) bound = false; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - GL_Bind (t->gltexture); - bound = true; - } - DrawGLPoly (s->polys); - rs_brushpasses++; + GL_Bind (t->gltexture); + bound = true; } + DrawGLPoly (s->polys); + rs_brushpasses++; + } } } @@ -617,21 +505,20 @@ void R_DrawTextureChains_TextureOnly (qmodel_t *model, entity_t *ent, texchain_t bound = false; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); + GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); - if (t->texturechains[chain]->flags & SURF_DRAWFENCE) - glEnable (GL_ALPHA_TEST); // Flip alpha test back on + if (t->texturechains[chain]->flags & SURF_DRAWFENCE) + glEnable (GL_ALPHA_TEST); // Flip alpha test back on - bound = true; - } - DrawGLPoly (s->polys); - rs_brushpasses++; + bound = true; } - + DrawGLPoly (s->polys); + rs_brushpasses++; + } + if (bound && t->texturechains[chain]->flags & SURF_DRAWFENCE) glDisable (GL_ALPHA_TEST); // Flip alpha test back off } @@ -681,21 +568,20 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain bound = false; entalpha = 1.0f; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - entalpha = GL_WaterAlphaForEntitySurface (ent, s); - R_BeginTransparentDrawing (entalpha); - GL_Bind (t->gltexture); - bound = true; - } - for (p = s->polys->next; p; p = p->next) - { - DrawWaterPoly (p); - rs_brushpasses++; - } + entalpha = GL_WaterAlphaForEntitySurface (ent, s); + R_BeginTransparentDrawing (entalpha); + GL_Bind (t->gltexture); + bound = true; + } + for (p = s->polys->next; p; p = p->next) + { + DrawWaterPoly (p); + rs_brushpasses++; } + } R_EndTransparentDrawing (entalpha); } } @@ -709,27 +595,26 @@ void R_DrawTextureChains_Water (qmodel_t *model, entity_t *ent, texchain_t chain bound = false; entalpha = 1.0f; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - entalpha = GL_WaterAlphaForEntitySurface (ent, s); - R_BeginTransparentDrawing (entalpha); - GL_Bind (t->warpimage); + entalpha = GL_WaterAlphaForEntitySurface (ent, s); + R_BeginTransparentDrawing (entalpha); + GL_Bind (t->warpimage); - if (model != cl.worldmodel) - { - // ericw -- this is copied from R_DrawSequentialPoly. - // If the poly is not part of the world we have to - // set this flag - t->update_warp = true; // FIXME: one frame too late! - } - - bound = true; + if (model != cl.worldmodel) + { + // ericw -- this is copied from R_DrawSequentialPoly. + // If the poly is not part of the world we have to + // set this flag + t->update_warp = true; // FIXME: one frame too late! } - DrawGLPoly (s->polys); - rs_brushpasses++; + + bound = true; } + DrawGLPoly (s->polys); + rs_brushpasses++; + } R_EndTransparentDrawing (entalpha); } } @@ -755,11 +640,10 @@ void R_DrawTextureChains_White (qmodel_t *model, texchain_t chain) continue; for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) - { - DrawGLPoly (s->polys); - rs_brushpasses++; - } + { + DrawGLPoly (s->polys); + rs_brushpasses++; + } } glEnable (GL_TEXTURE_2D); } @@ -972,30 +856,29 @@ void R_DrawTextureChains_GLSL (qmodel_t *model, entity_t *ent, texchain_t chain) bound = false; lastlightmap = 0; // avoid compiler warning for (s = t->texturechains[chain]; s; s = s->texturechain) - if (!s->culled) + { + if (!bound) //only bind once we are sure we need this texture { - if (!bound) //only bind once we are sure we need this texture - { - GL_SelectTexture (GL_TEXTURE0); - GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); + GL_SelectTexture (GL_TEXTURE0); + GL_Bind ((R_TextureAnimation(t, ent != NULL ? ent->frame : 0))->gltexture); - if (t->texturechains[chain]->flags & SURF_DRAWFENCE) - GL_Uniform1iFunc (useAlphaTestLoc, 1); // Flip alpha test back on + if (t->texturechains[chain]->flags & SURF_DRAWFENCE) + GL_Uniform1iFunc (useAlphaTestLoc, 1); // Flip alpha test back on - bound = true; - lastlightmap = s->lightmaptexturenum; - } + bound = true; + lastlightmap = s->lightmaptexturenum; + } - if (s->lightmaptexturenum != lastlightmap) - R_FlushBatch (); + if (s->lightmaptexturenum != lastlightmap) + R_FlushBatch (); - GL_SelectTexture (GL_TEXTURE1); - GL_Bind (lightmap[s->lightmaptexturenum].texture); - lastlightmap = s->lightmaptexturenum; - R_BatchSurface (s); + GL_SelectTexture (GL_TEXTURE1); + GL_Bind (lightmap[s->lightmaptexturenum].texture); + lastlightmap = s->lightmaptexturenum; + R_BatchSurface (s); - rs_brushpasses++; - } + rs_brushpasses++; + } R_FlushBatch (); @@ -1032,12 +915,6 @@ void R_DrawTextureChains (qmodel_t *model, entity_t *ent, texchain_t chain) else entalpha = 1; -// ericw -- the mh dynamic lightmap speedup: make a first pass through all -// surfaces we are going to draw, and rebuild any lightmaps that need it. -// this also chains surfaces by lightmap which is used by r_lightmap 1. -// the previous implementation of the speedup uploaded lightmaps one frame -// late which was visible under some conditions, this method avoids that. - R_BuildLightmapChains (model, chain); R_UploadLightmaps (); if (r_drawflat_cheatsafe) diff --git a/quakespasm/Quake/snd_dma.c b/quakespasm/Quake/snd_dma.c index cc5df69d6..10d8e48a1 100644 --- a/quakespasm/Quake/snd_dma.c +++ b/quakespasm/Quake/snd_dma.c @@ -632,14 +632,15 @@ S_UpdateAmbientSounds static void S_UpdateAmbientSounds (void) { mleaf_t *l; - int vol, ambient_channel; + int ambient_channel; channel_t *chan; + static float vol, levels[NUM_AMBIENTS]; //Spike: fixing ambient levels not changing at high enough framerates due to integer precison. // no ambients when disconnected - if (cls.state != ca_connected) + if (cls.state != ca_connected || cls.signon != SIGNONS) return; // calc ambient sound levels - if (!cl.worldmodel) + if (!cl.worldmodel || cl.worldmodel->needload) return; l = Mod_PointInLeaf (listener_origin, cl.worldmodel); @@ -660,20 +661,20 @@ static void S_UpdateAmbientSounds (void) vol = 0; // don't adjust volume too fast - if (chan->master_vol < vol) + if (levels[ambient_channel] < vol) { - chan->master_vol += (int) (host_frametime * ambient_fade.value); - if (chan->master_vol > vol) - chan->master_vol = vol; + levels[ambient_channel] += (host_frametime * ambient_fade.value); + if (levels[ambient_channel] > vol) + levels[ambient_channel] = vol; } else if (chan->master_vol > vol) { - chan->master_vol -= (int) (host_frametime * ambient_fade.value); - if (chan->master_vol < vol) - chan->master_vol = vol; + levels[ambient_channel] -= (host_frametime * ambient_fade.value); + if (levels[ambient_channel] < vol) + levels[ambient_channel] = vol; } - chan->leftvol = chan->rightvol = chan->master_vol; + chan->leftvol = chan->rightvol = chan->master_vol = levels[ambient_channel]; } }