diff --git a/libs/video/renderer/r_efrag.c b/libs/video/renderer/r_efrag.c index 8785d3d7d..4c93c935c 100644 --- a/libs/video/renderer/r_efrag.c +++ b/libs/video/renderer/r_efrag.c @@ -33,11 +33,9 @@ #include "QF/render.h" #include "QF/sys.h" +#include "qfalloca.h" #include "r_internal.h" -static mnode_t *r_pefragtopnode; -static vec3_t r_emins, r_emaxs; - typedef struct s_efrag_list { struct s_efrag_list *next; efrag_t efrags[MAX_EFRAGS]; @@ -48,10 +46,6 @@ static t_efrag_list *efrag_list; /* ENTITY FRAGMENT FUNCTIONS */ -static efrag_t **lastlink; -static entity_t *r_addent; - - static inline void init_efrag_list (t_efrag_list *efl) { @@ -133,32 +127,39 @@ R_RemoveEfrags (entity_t *ent) ent->efrag = 0; } -#define NODE_STACK_SIZE 1024 -static mnode_t *node_stack[NODE_STACK_SIZE]; -static mnode_t **node_ptr = node_stack + NODE_STACK_SIZE; - static void -R_SplitEntityOnNode (mnode_t *node) +R_SplitEntityOnNode (mod_brush_t *brush, entity_t *ent, + vec3_t emins, vec3_t emaxs) { efrag_t *ef; plane_t *splitplane; mleaf_t *leaf; int sides; + efrag_t **lastlink; + mnode_t **node_stack; + mnode_t **node_ptr; + mnode_t *node = brush->nodes; - *--node_ptr = 0; + node_stack = alloca ((brush->depth + 2) * sizeof (mnode_t *)); + node_ptr = node_stack; + + lastlink = &ent->efrag; + + *node_ptr++ = 0; while (node) { // add an efrag if the node is a leaf if (__builtin_expect (node->contents < 0, 0)) { - if (!r_pefragtopnode) - r_pefragtopnode = node; + if (!ent->topnode) { + ent->topnode = node; + } leaf = (mleaf_t *) node; ef = new_efrag (); // ensures ef->entnext is 0 // add the link to the chain of links on the entity - ef->entity = r_addent; + ef->entity = ent; *lastlink = ef; lastlink = &ef->entnext; @@ -167,28 +168,29 @@ R_SplitEntityOnNode (mnode_t *node) ef->leafnext = leaf->efrags; leaf->efrags = ef; - node = *node_ptr++; + node = *--node_ptr; } else { // NODE_MIXED splitplane = node->plane; - sides = BOX_ON_PLANE_SIDE (r_emins, r_emaxs, splitplane); + sides = BOX_ON_PLANE_SIDE (emins, emaxs, splitplane); if (sides == 3) { // split on this plane // if this is the first splitter of this bmodel, remember it - if (!r_pefragtopnode) - r_pefragtopnode = node; + if (!ent->topnode) { + ent->topnode = node; + } } // recurse down the contacted sides if (sides & 1 && node->children[0]->contents != CONTENTS_SOLID) { if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) - *--node_ptr = node->children[1]; + *node_ptr++ = node->children[1]; node = node->children[0]; } else { if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID) node = node->children[1]; else - node = *node_ptr++; + node = *--node_ptr; } } } @@ -198,6 +200,7 @@ void R_AddEfrags (mod_brush_t *brush, entity_t *ent) { model_t *entmodel; + vec3_t emins, emaxs; if (!ent->model || !r_worldentity.model) return; @@ -205,19 +208,13 @@ R_AddEfrags (mod_brush_t *brush, entity_t *ent) if (ent == &r_worldentity) return; // never add the world - r_addent = ent; - - lastlink = &ent->efrag; - r_pefragtopnode = 0; - entmodel = ent->model; - VectorAdd (ent->origin, entmodel->mins, r_emins); - VectorAdd (ent->origin, entmodel->maxs, r_emaxs); + VectorAdd (ent->origin, entmodel->mins, emins); + VectorAdd (ent->origin, entmodel->maxs, emaxs); - R_SplitEntityOnNode (brush->nodes); - - ent->topnode = r_pefragtopnode; + ent->topnode = 0; + R_SplitEntityOnNode (brush, ent, emins, emaxs); } void