diff --git a/quakespasm/Quake/cl_main.c b/quakespasm/Quake/cl_main.c index 30c8718d..132e4e10 100644 --- a/quakespasm/Quake/cl_main.c +++ b/quakespasm/Quake/cl_main.c @@ -51,7 +51,6 @@ cvar_t cl_minpitch = {"cl_minpitch", "-90", CVAR_ARCHIVE}; //johnfitz -- variabl client_static_t cls; client_state_t cl; // FIXME: put these on hunk? -efrag_t cl_efrags[MAX_EFRAGS]; entity_t cl_static_entities[MAX_STATIC_ENTITIES]; lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; dlight_t cl_dlights[MAX_DLIGHTS]; @@ -72,8 +71,6 @@ CL_ClearState */ void CL_ClearState (void) { - int i; - if (!sv.active) Host_ClearMemory (); @@ -83,7 +80,6 @@ void CL_ClearState (void) SZ_Clear (&cls.message); // clear other arrays - memset (cl_efrags, 0, sizeof(cl_efrags)); memset (cl_dlights, 0, sizeof(cl_dlights)); memset (cl_lightstyle, 0, sizeof(cl_lightstyle)); memset (cl_temp_entities, 0, sizeof(cl_temp_entities)); @@ -93,14 +89,6 @@ void CL_ClearState (void) cl_max_edicts = CLAMP (MIN_EDICTS,(int)max_edicts.value,MAX_EDICTS); cl_entities = (entity_t *) Hunk_AllocName (cl_max_edicts*sizeof(entity_t), "cl_entities"); //johnfitz - -// -// allocate the efrags and chain together into a free list -// - cl.free_efrags = cl_efrags; - for (i=0 ; imodel) { // empty slot - if (ent->forcelink) - R_RemoveEfrags (ent); // just became empty + + // ericw -- efrags are only used for static entities in GLQuake + // ent can't be static, so this is a no-op. + //if (ent->forcelink) + // R_RemoveEfrags (ent); // just became empty continue; } diff --git a/quakespasm/Quake/client.h b/quakespasm/Quake/client.h index 3939061f..0db68da1 100644 --- a/quakespasm/Quake/client.h +++ b/quakespasm/Quake/client.h @@ -85,8 +85,6 @@ typedef struct vec3_t start, end; } beam_t; -#define MAX_EFRAGS 8192 //ericw -- was 2048 //johnfitz -- was 640 - #define MAX_MAPSTRING 2048 #define MAX_DEMOS 8 #define MAX_DEMONAME 16 @@ -214,6 +212,7 @@ typedef struct // refresh related state struct qmodel_s *worldmodel; // cl_entitites[0].model struct efrag_s *free_efrags; + int num_efrags; int num_entities; // held in cl_entities array int num_statics; // held in cl_staticentities array entity_t viewent; // the gun model @@ -271,7 +270,6 @@ extern cvar_t m_side; extern client_state_t cl; // FIXME, allocate dynamically -extern efrag_t cl_efrags[MAX_EFRAGS]; extern entity_t cl_static_entities[MAX_STATIC_ENTITIES]; extern lightstyle_t cl_lightstyle[MAX_LIGHTSTYLES]; extern dlight_t cl_dlights[MAX_DLIGHTS]; diff --git a/quakespasm/Quake/gl_refrag.c b/quakespasm/Quake/gl_refrag.c index 5a2f3311..ee2350ce 100644 --- a/quakespasm/Quake/gl_refrag.c +++ b/quakespasm/Quake/gl_refrag.c @@ -33,55 +33,57 @@ mnode_t *r_pefragtopnode; ENTITY FRAGMENT FUNCTIONS +ericw -- GLQuake only uses efrags for static entities, and they're never +removed, so I trimmed out unused functionality and fields in efrag_t. + +Now, efrags are just a linked list for each leaf of the static +entities that touch that leaf. The efrags are hunk-allocated so there is no +fixed limit. + +This is inspired by MH's tutorial, and code from RMQEngine. +http://forums.insideqc.com/viewtopic.php?t=1930 + =============================================================================== */ -efrag_t **lastlink; - vec3_t r_emins, r_emaxs; entity_t *r_addent; -/* -================ -R_RemoveEfrags +#define EXTRA_EFRAGS 128 -Call when removing an object from the world or moving it to another position -================ -*/ -void R_RemoveEfrags (entity_t *ent) +// based on RMQEngine +static efrag_t *R_GetEfrag (void) { - efrag_t *ef, *old, *walk, **prev; - - ef = ent->efrag; - - while (ef) + // we could just Hunk_Alloc a single efrag_t and return it, but since + // the struct is so small (2 pointers) allocate groups of them + // to avoid wasting too much space on the hunk allocation headers. + + if (cl.free_efrags) { - prev = &ef->leaf->efrags; - while (1) - { - walk = *prev; - if (!walk) - break; - if (walk == ef) - { // remove this fragment - *prev = ef->leafnext; - break; - } - else - prev = &walk->leafnext; - } - - old = ef; - ef = ef->entnext; - - // put it on the free list - old->entnext = cl.free_efrags; - cl.free_efrags = old; + efrag_t *ef = cl.free_efrags; + cl.free_efrags = ef->leafnext; + ef->leafnext = NULL; + + cl.num_efrags++; + + return ef; + } + else + { + int i; + + cl.free_efrags = (efrag_t *) Hunk_AllocName (EXTRA_EFRAGS * sizeof (efrag_t), "efrags"); + + for (i = 0; i < EXTRA_EFRAGS - 1; i++) + cl.free_efrags[i].leafnext = &cl.free_efrags[i + 1]; + + cl.free_efrags[i].leafnext = NULL; + + // call recursively to get a newly allocated free efrag + return R_GetEfrag (); } - - ent->efrag = NULL; } /* @@ -111,29 +113,10 @@ void R_SplitEntityOnNode (mnode_t *node) leaf = (mleaf_t *)node; // grab an efrag off the free list - ef = cl.free_efrags; - if (!ef) - { - //johnfitz -- less spammy overflow message - if (!dev_overflows.efrags || dev_overflows.efrags + CONSOLE_RESPAM_TIME < realtime ) - { - Con_Printf ("Too many efrags!\n"); - dev_overflows.efrags = realtime; - } - //johnfitz - return; // no free fragments... - } - cl.free_efrags = cl.free_efrags->entnext; - + ef = R_GetEfrag(); ef->entity = r_addent; -// add the entity link - *lastlink = ef; - lastlink = &ef->entnext; - ef->entnext = NULL; - // set the leaf links - ef->leaf = leaf; ef->leafnext = leaf->efrags; leaf->efrags = ef; @@ -168,20 +151,14 @@ R_CheckEfrags -- johnfitz -- check for excessive efrag count */ void R_CheckEfrags (void) { - efrag_t *ef; - int count; - if (cls.signon < 2) return; //don't spam when still parsing signon packet full of static ents - for (count=MAX_EFRAGS, ef = cl.free_efrags; ef; count--, ef = ef->entnext) - ; + if (cl.num_efrags > 640 && dev_peakstats.efrags <= 640) + Con_DWarning ("%i efrags exceeds standard limit of 640.\n", cl.num_efrags); - if (count > 640 && dev_peakstats.efrags <= 640) - Con_DWarning ("%i efrags exceeds standard limit of 640 (max = %d).\n", count, MAX_EFRAGS); - - dev_stats.efrags = count; - dev_peakstats.efrags = q_max(count, dev_peakstats.efrags); + dev_stats.efrags = cl.num_efrags; + dev_peakstats.efrags = q_max(cl.num_efrags, dev_peakstats.efrags); } /* @@ -199,7 +176,6 @@ void R_AddEfrags (entity_t *ent) r_addent = ent; - lastlink = &ent->efrag; r_pefragtopnode = NULL; entmodel = ent->model; diff --git a/quakespasm/Quake/render.h b/quakespasm/Quake/render.h index cfdf3f3f..4ecb9733 100644 --- a/quakespasm/Quake/render.h +++ b/quakespasm/Quake/render.h @@ -34,10 +34,8 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. typedef struct efrag_s { - struct mleaf_s *leaf; struct efrag_s *leafnext; struct entity_s *entity; - struct efrag_s *entnext; } efrag_t; //johnfitz -- for lerping @@ -147,7 +145,6 @@ void R_ViewChanged (vrect_t *pvrect, int lineadj, float aspect); void R_CheckEfrags (void); //johnfitz void R_AddEfrags (entity_t *ent); -void R_RemoveEfrags (entity_t *ent); void R_NewMap (void);