mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-01-17 22:50:51 +00:00
rewrite R_SplitEntityOnNode to be itterative rather than recursive (using
a static `stack') to avoid the function call overhead. this cuts about 40% of the execution time from this function. No matter what I tried, best results were obtained using __builtin_expect, so make sure non-gcc compilers do the right thing when they encounter it.
This commit is contained in:
parent
2b2c0401cf
commit
da994c16e5
2 changed files with 55 additions and 45 deletions
|
@ -31,6 +31,7 @@
|
|||
|
||||
#ifndef __GNUC__
|
||||
# define __attribute__(x)
|
||||
# define __builtin_expect(x,c) x
|
||||
#endif
|
||||
|
||||
#endif // __gcc_attr_h
|
||||
|
|
|
@ -87,6 +87,10 @@ R_RemoveEfrags (entity_t *ent)
|
|||
ent->efrag = NULL;
|
||||
}
|
||||
|
||||
#define NODE_STACK_SIZE 1024
|
||||
static mnode_t *node_stack[NODE_STACK_SIZE];
|
||||
static mnode_t **node_ptr = node_stack + NODE_STACK_SIZE;
|
||||
|
||||
void
|
||||
R_SplitEntityOnNode (mnode_t *node)
|
||||
{
|
||||
|
@ -95,56 +99,61 @@ R_SplitEntityOnNode (mnode_t *node)
|
|||
mleaf_t *leaf;
|
||||
int sides;
|
||||
|
||||
if (node->contents == CONTENTS_SOLID) {
|
||||
return;
|
||||
}
|
||||
*--node_ptr = 0;
|
||||
|
||||
// add an efrag if the node is a leaf
|
||||
if (node->contents < 0) {
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
while (node) {
|
||||
// add an efrag if the node is a leaf
|
||||
if (__builtin_expect (node->contents < 0, 0)) {
|
||||
if (!r_pefragtopnode)
|
||||
r_pefragtopnode = node;
|
||||
|
||||
leaf = (mleaf_t *) node;
|
||||
leaf = (mleaf_t *) node;
|
||||
|
||||
// grab an efrag off the free list
|
||||
ef = r_free_efrags;
|
||||
if (!ef) {
|
||||
Con_Printf ("Too many efrags!\n");
|
||||
return; // no free fragments...
|
||||
// grab an efrag off the free list
|
||||
ef = r_free_efrags;
|
||||
if (__builtin_expect (!ef, 0)) {
|
||||
Con_Printf ("Too many efrags!\n");
|
||||
return; // no free fragments...
|
||||
}
|
||||
r_free_efrags = r_free_efrags->entnext;
|
||||
|
||||
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;
|
||||
|
||||
node = *node_ptr++;
|
||||
} else {
|
||||
// NODE_MIXED
|
||||
splitplane = node->plane;
|
||||
sides = BOX_ON_PLANE_SIDE (r_emins, r_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;
|
||||
}
|
||||
// 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 = node->children[0];
|
||||
} else {
|
||||
if (sides & 2 && node->children[1]->contents != CONTENTS_SOLID)
|
||||
node = node->children[1];
|
||||
else
|
||||
node = *node_ptr++;
|
||||
}
|
||||
}
|
||||
r_free_efrags = r_free_efrags->entnext;
|
||||
|
||||
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;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// NODE_MIXED
|
||||
splitplane = node->plane;
|
||||
sides = BOX_ON_PLANE_SIDE (r_emins, r_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;
|
||||
}
|
||||
// recurse down the contacted sides
|
||||
if (sides & 1)
|
||||
R_SplitEntityOnNode (node->children[0]);
|
||||
|
||||
if (sides & 2)
|
||||
R_SplitEntityOnNode (node->children[1]);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
Loading…
Reference in a new issue