Remove the hard-coded bsp maximum depths.

The depth limits in the gl and glsl renderers and in the trace code really
bothered me, but then the fix hit me: at load-time, recurse the trees
normally and record the depth in the appropriate place. The node stacks can
then be allocated as necessary (I chose to add a paranoia buffer of 2, but
I expect the maximum depth will rarely be used).
This commit is contained in:
Bill Currie 2012-11-28 21:29:03 +09:00
parent 7c3ad46b48
commit a12eb940f1
6 changed files with 76 additions and 15 deletions

View file

@ -230,6 +230,7 @@ typedef struct hull_s {
vec3_t clip_mins;
vec3_t clip_maxs;
struct nodeleaf_s *nodeleafs;
int depth; ///< maximum depth of the tree
} hull_t;
// SPRITE MODELS ==============================================================
@ -393,6 +394,7 @@ typedef struct model_s {
int numnodes;
mnode_t *nodes;
int depth; ///< maximum depth of the tree
int numtexinfo;
mtexinfo_t *texinfo;
@ -449,6 +451,7 @@ void *Mod_LoadAliasFrame (void *pin, int *posenum, maliasframedesc_t *frame,
void *Mod_LoadAliasGroup (void *pin, int *posenum, maliasframedesc_t *frame,
int extra);
void Mod_FindClipDepth (hull_t *hull);
void Mod_LoadBrushModel (model_t *mod, void *buffer);
void Mod_FloodFillSkin (byte * skin, int skinwidth, int skinheight);

View file

@ -880,6 +880,48 @@ do_checksums (const bsp_t *bsp, void *_mod)
}
}
static void
recurse_draw_tree (mnode_t *node, int depth)
{
if (!node || node->contents < 0) {
if (depth > loadmodel->depth)
loadmodel->depth = depth;
return;
}
recurse_draw_tree (node->children[0], depth + 1);
recurse_draw_tree (node->children[1], depth + 1);
}
static void
Mod_FindDrawDepth (void)
{
loadmodel->depth = 0;
recurse_draw_tree (loadmodel->nodes, 1);
}
static void
recurse_clip_tree (hull_t *hull, int num, int depth)
{
mclipnode_t *node;
if (num < 0) {
if (depth > hull->depth)
hull->depth = depth;
return;
}
node = hull->clipnodes + num;
recurse_clip_tree (hull, node->children[0], depth + 1);
recurse_clip_tree (hull, node->children[1], depth + 1);
}
void
Mod_FindClipDepth (hull_t *hull)
{
hull->depth = 0;
if (hull->clipnodes) // no hull 3?
recurse_clip_tree (hull, hull->firstclipnode, 1);
}
void
Mod_LoadBrushModel (model_t *mod, void *buffer)
{
@ -913,6 +955,10 @@ Mod_LoadBrushModel (model_t *mod, void *buffer)
Mod_MakeHull0 ();
Mod_FindDrawDepth ();
for (i = 0; i < MAX_MAP_HULLS; i++)
Mod_FindClipDepth (&mod->hulls[i]);
mod->numframes = 2; // regular and alternate animation
// set up the submodels (FIXME: this is confusing)

View file

@ -255,6 +255,8 @@ run_test (test_t *test)
static int output = 0;
portlist_t *portal_list = 0;
if (!test->hull->depth)
Mod_FindClipDepth (test->hull);
if (!test->hull->nodeleafs) {
hull_t *hull = test->hull;
int i, j;

View file

@ -783,12 +783,16 @@ MOD_TraceLine (hull_t *hull, int num,
vec3_t start, end, dist;
int side;
tracestack_t *tstack;
tracestack_t tracestack[256];
tracestack_t *tracestack;
mclipnode_t *node;
plane_t *plane;
clipleaf_t *leaf;
trace_state_t trace_state;
if (!hull->depth)
Sys_Error ("hull depth not set");
// +2 for paranoia
tracestack = alloca ((hull->depth + 2) * sizeof (tracestack_t));
VectorCopy (start_point, start);
VectorCopy (end_point, end);
VectorSubtract (end, start, trace_state.dist);

View file

@ -652,16 +652,21 @@ test_node (mnode_t *node)
}
static void
R_VisitWorldNodes (mnode_t *node)
R_VisitWorldNodes (model_t *model)
{
#define NODE_STACK 1024
struct {
typedef struct {
mnode_t *node;
int side;
} *node_ptr, node_stack[NODE_STACK];
} rstack_t;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int side;
node = model->nodes;
// +2 for paranoia
node_stack = alloca ((model->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
while (1) {
@ -669,8 +674,6 @@ R_VisitWorldNodes (mnode_t *node)
side = get_side (node);
front = node->children[side];
if (test_node (front)) {
if (node_ptr - node_stack == NODE_STACK)
Sys_Error ("node_stack overflow");
node_ptr->node = node;
node_ptr->side = side;
node_ptr++;
@ -716,7 +719,7 @@ gl_R_DrawWorld (void)
gl_R_DrawSky ();
}
R_VisitWorldNodes (r_worldentity.model->nodes);
R_VisitWorldNodes (r_worldentity.model);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {

View file

@ -743,16 +743,21 @@ test_node (mnode_t *node)
}
static void
R_VisitWorldNodes (mnode_t *node)
R_VisitWorldNodes (model_t *model)
{
#define NODE_STACK 1024
struct {
typedef struct {
mnode_t *node;
int side;
} *node_ptr, node_stack[NODE_STACK];
} rstack_t;
rstack_t *node_ptr;
rstack_t *node_stack;
mnode_t *node;
mnode_t *front;
int side;
node = model->nodes;
// +2 for paranoia
node_stack = alloca ((model->depth + 2) * sizeof (rstack_t));
node_ptr = node_stack;
while (1) {
@ -760,8 +765,6 @@ R_VisitWorldNodes (mnode_t *node)
side = get_side (node);
front = node->children[side];
if (test_node (front)) {
if (node_ptr - node_stack == NODE_STACK)
Sys_Error ("node_stack overflow");
node_ptr->node = node;
node_ptr->side = side;
node_ptr++;
@ -1097,7 +1100,7 @@ glsl_R_DrawWorld (void)
currententity = &worldent;
R_VisitWorldNodes (worldent.model->nodes);
R_VisitWorldNodes (worldent.model);
if (r_drawentities->int_val) {
entity_t *ent;
for (ent = r_ent_queue; ent; ent = ent->next) {