mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
make R_RecursiveWorldNode non-recursive (needs a new name, now :). 0.4%
speedup in null-renderer gl: unknown for sw and sw32 (could be slightly slower, left recursive version in but #if 0ed out jic)
This commit is contained in:
parent
6642686e33
commit
2d2173dc4e
3 changed files with 407 additions and 41 deletions
|
@ -543,47 +543,33 @@ R_DrawBrushModel (entity_t *e)
|
|||
|
||||
// WORLD MODEL ================================================================
|
||||
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node)
|
||||
static inline void
|
||||
visit_leaf (mleaf_t *leaf)
|
||||
{
|
||||
double dot;
|
||||
int c, side;
|
||||
mleaf_t *pleaf;
|
||||
mplane_t *plane;
|
||||
// deal with model fragments in this leaf
|
||||
if (leaf->efrags)
|
||||
R_StoreEfrags (&leaf->efrags);
|
||||
}
|
||||
|
||||
static inline int
|
||||
get_side (mnode_t *node)
|
||||
{
|
||||
// find which side of the node we are on
|
||||
mplane_t *plane = node->plane;
|
||||
|
||||
if (plane->type < 3)
|
||||
return (modelorg[plane->type] - plane->dist) < 0;
|
||||
return (DotProduct (modelorg, plane->normal) - plane->dist) < 0;
|
||||
}
|
||||
|
||||
static void
|
||||
visit_node (mnode_t *node, int side)
|
||||
{
|
||||
int c;
|
||||
msurface_t *surf;
|
||||
|
||||
if (node->contents == CONTENTS_SOLID)
|
||||
return;
|
||||
if (node->visframe != r_visframecount)
|
||||
return;
|
||||
|
||||
if (R_CullBox (node->minmaxs, node->minmaxs + 3))
|
||||
return;
|
||||
|
||||
// if a leaf node, draw stuff
|
||||
if (node->contents < 0) {
|
||||
pleaf = (mleaf_t *) node;
|
||||
// deal with model fragments in this leaf
|
||||
if (pleaf->efrags)
|
||||
R_StoreEfrags (&pleaf->efrags);
|
||||
|
||||
return;
|
||||
}
|
||||
// node is just a decision point, so go down the appropriate sides
|
||||
|
||||
// find which side of the node we are on
|
||||
plane = node->plane;
|
||||
if (plane->type < 3)
|
||||
dot = modelorg[plane->type] - plane->dist;
|
||||
else
|
||||
dot = DotProduct (modelorg, plane->normal) - plane->dist;
|
||||
side = dot < 0;
|
||||
|
||||
// recurse down the children, front side first
|
||||
R_RecursiveWorldNode (node->children[side]);
|
||||
|
||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||
side = (~side + 1) & SURF_PLANEBACK;
|
||||
side = (~side + 1) & SURF_PLANEBACK;
|
||||
// draw stuff
|
||||
if ((c = node->numsurfaces)) {
|
||||
surf = r_worldentity.model->surfaces + node->firstsurface;
|
||||
|
@ -616,8 +602,66 @@ R_RecursiveWorldNode (mnode_t *node)
|
|||
}
|
||||
}
|
||||
}
|
||||
// recurse down the back side
|
||||
R_RecursiveWorldNode (node->children[!side]);
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_node (mnode_t *node)
|
||||
{
|
||||
if (node->contents < 0)
|
||||
return 0;
|
||||
if (node->visframe != r_visframecount)
|
||||
return 0;
|
||||
if (R_CullBox (node->minmaxs, node->minmaxs + 3))
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//FIXME no longer recursive: need a new name
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node)
|
||||
{
|
||||
struct {
|
||||
mnode_t *node;
|
||||
int side;
|
||||
} *node_ptr, node_stack[256];
|
||||
mnode_t *front;
|
||||
int side;
|
||||
|
||||
node_ptr = node_stack;
|
||||
|
||||
while (1) {
|
||||
while (test_node (node)) {
|
||||
side = get_side (node);
|
||||
front = node->children[side];
|
||||
if (test_node (front)) {
|
||||
if (node_ptr - node_stack
|
||||
== sizeof (node_stack) / sizeof (node_stack[0]))
|
||||
Sys_Error ("node_stack overflow");
|
||||
node_ptr->node = node;
|
||||
node_ptr->side = side;
|
||||
node_ptr++;
|
||||
node = front;
|
||||
continue;
|
||||
}
|
||||
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) front);
|
||||
visit_node (node, side);
|
||||
node = node->children[!side];
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
if (node_ptr != node_stack) {
|
||||
node_ptr--;
|
||||
node = node_ptr->node;
|
||||
side = node_ptr->side;
|
||||
visit_node (node, side);
|
||||
node = node->children[!side];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
|
||||
void
|
||||
|
|
|
@ -395,7 +395,168 @@ R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
|
|||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
static inline void
|
||||
visit_leaf (mleaf_t *leaf)
|
||||
{
|
||||
// deal with model fragments in this leaf
|
||||
if (leaf->efrags)
|
||||
R_StoreEfrags (&leaf->efrags);
|
||||
leaf->key = r_currentkey;
|
||||
r_currentkey++; // all bmodels in a leaf share the same key
|
||||
}
|
||||
|
||||
static inline int
|
||||
get_side (mnode_t *node)
|
||||
{
|
||||
// find which side of the node we are on
|
||||
mplane_t *plane = node->plane;
|
||||
|
||||
if (plane->type < 3)
|
||||
return (modelorg[plane->type] - plane->dist) < 0;
|
||||
return (DotProduct (modelorg, plane->normal) - plane->dist) < 0;
|
||||
}
|
||||
|
||||
static void
|
||||
visit_node (mnode_t *node, int side, int clipflags)
|
||||
{
|
||||
int c;
|
||||
msurface_t *surf;
|
||||
|
||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||
side = (~side + 1) & SURF_PLANEBACK;
|
||||
// draw stuff
|
||||
if ((c = node->numsurfaces)) {
|
||||
surf = r_worldentity.model->surfaces + node->firstsurface;
|
||||
for (; c; c--, surf++) {
|
||||
if (surf->visframe != r_visframecount)
|
||||
continue;
|
||||
|
||||
// side is either 0 or SURF_PLANEBACK
|
||||
if (side ^ (surf->flags & SURF_PLANEBACK))
|
||||
continue; // wrong side
|
||||
|
||||
if (r_drawpolys) {
|
||||
if (r_worldpolysbacktofront) {
|
||||
if (numbtofpolys < MAX_BTOFPOLYS) {
|
||||
pbtofpolys[numbtofpolys].clipflags = clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
} else {
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
} else {
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
// all surfaces on the same node share the same sequence number
|
||||
r_currentkey++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_node (mnode_t *node, int *_clipflags)
|
||||
{
|
||||
int clipflags = *_clipflags;
|
||||
int i, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
double d;
|
||||
|
||||
if (node->contents < 0)
|
||||
return 0;
|
||||
if (node->visframe != r_visframecount)
|
||||
return 0;
|
||||
// cull the clipping planes if not trivial accept
|
||||
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
|
||||
// twice as fast in ASM
|
||||
if (clipflags) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!(clipflags & (1 << i)))
|
||||
continue; // don't need to clip against it
|
||||
|
||||
// generate accept and reject points
|
||||
// FIXME: do with fast look-ups or integer tests based on the
|
||||
// sign bit of the floating point values
|
||||
|
||||
pindex = pfrustum_indexes[i];
|
||||
|
||||
rejectpt[0] = (float) node->minmaxs[pindex[0]];
|
||||
rejectpt[1] = (float) node->minmaxs[pindex[1]];
|
||||
rejectpt[2] = (float) node->minmaxs[pindex[2]];
|
||||
|
||||
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d <= 0) {
|
||||
*_clipflags = clipflags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
acceptpt[0] = (float) node->minmaxs[pindex[3 + 0]];
|
||||
acceptpt[1] = (float) node->minmaxs[pindex[3 + 1]];
|
||||
acceptpt[2] = (float) node->minmaxs[pindex[3 + 2]];
|
||||
|
||||
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
if (d >= 0)
|
||||
clipflags &= ~(1 << i); // node is entirely on screen
|
||||
}
|
||||
}
|
||||
*_clipflags = clipflags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//FIXME no longer recursive: need a new name
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
struct {
|
||||
mnode_t *node;
|
||||
int side, clipflags;
|
||||
} *node_ptr, node_stack[256];
|
||||
mnode_t *front;
|
||||
int side;
|
||||
|
||||
node_ptr = node_stack;
|
||||
|
||||
while (1) {
|
||||
while (test_node (node, &clipflags)) {
|
||||
side = get_side (node);
|
||||
front = node->children[side];
|
||||
if (test_node (front, &clipflags)) {
|
||||
if (node_ptr - node_stack
|
||||
== sizeof (node_stack) / sizeof (node_stack[0]))
|
||||
Sys_Error ("node_stack overflow");
|
||||
node_ptr->node = node;
|
||||
node_ptr->side = side;
|
||||
node_ptr->clipflags = clipflags;
|
||||
node_ptr++;
|
||||
node = front;
|
||||
continue;
|
||||
}
|
||||
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) front);
|
||||
visit_node (node, side, clipflags);
|
||||
node = node->children[!side];
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
if (node_ptr != node_stack) {
|
||||
node_ptr--;
|
||||
node = node_ptr->node;
|
||||
side = node_ptr->side;
|
||||
clipflags = node_ptr->clipflags;
|
||||
visit_node (node, side, clipflags);
|
||||
node = node->children[!side];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
|
@ -544,7 +705,7 @@ R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
|||
R_RecursiveWorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
R_RenderWorld (void)
|
||||
|
|
|
@ -395,7 +395,168 @@ R_DrawSubmodelPolygons (model_t *pmodel, int clipflags)
|
|||
}
|
||||
}
|
||||
|
||||
#if 1
|
||||
static inline void
|
||||
visit_leaf (mleaf_t *leaf)
|
||||
{
|
||||
// deal with model fragments in this leaf
|
||||
if (leaf->efrags)
|
||||
R_StoreEfrags (&leaf->efrags);
|
||||
leaf->key = r_currentkey;
|
||||
r_currentkey++; // all bmodels in a leaf share the same key
|
||||
}
|
||||
|
||||
static inline int
|
||||
get_side (mnode_t *node)
|
||||
{
|
||||
// find which side of the node we are on
|
||||
mplane_t *plane = node->plane;
|
||||
|
||||
if (plane->type < 3)
|
||||
return (modelorg[plane->type] - plane->dist) < 0;
|
||||
return (DotProduct (modelorg, plane->normal) - plane->dist) < 0;
|
||||
}
|
||||
|
||||
static void
|
||||
visit_node (mnode_t *node, int side, int clipflags)
|
||||
{
|
||||
int c;
|
||||
msurface_t *surf;
|
||||
|
||||
// sneaky hack for side = side ? SURF_PLANEBACK : 0;
|
||||
side = (~side + 1) & SURF_PLANEBACK;
|
||||
// draw stuff
|
||||
if ((c = node->numsurfaces)) {
|
||||
surf = r_worldentity.model->surfaces + node->firstsurface;
|
||||
for (; c; c--, surf++) {
|
||||
if (surf->visframe != r_visframecount)
|
||||
continue;
|
||||
|
||||
// side is either 0 or SURF_PLANEBACK
|
||||
if (side ^ (surf->flags & SURF_PLANEBACK))
|
||||
continue; // wrong side
|
||||
|
||||
if (r_drawpolys) {
|
||||
if (r_worldpolysbacktofront) {
|
||||
if (numbtofpolys < MAX_BTOFPOLYS) {
|
||||
pbtofpolys[numbtofpolys].clipflags = clipflags;
|
||||
pbtofpolys[numbtofpolys].psurf = surf;
|
||||
numbtofpolys++;
|
||||
}
|
||||
} else {
|
||||
R_RenderPoly (surf, clipflags);
|
||||
}
|
||||
} else {
|
||||
R_RenderFace (surf, clipflags);
|
||||
}
|
||||
}
|
||||
// all surfaces on the same node share the same sequence number
|
||||
r_currentkey++;
|
||||
}
|
||||
}
|
||||
|
||||
static inline int
|
||||
test_node (mnode_t *node, int *_clipflags)
|
||||
{
|
||||
int clipflags = *_clipflags;
|
||||
int i, *pindex;
|
||||
vec3_t acceptpt, rejectpt;
|
||||
double d;
|
||||
|
||||
if (node->contents < 0)
|
||||
return 0;
|
||||
if (node->visframe != r_visframecount)
|
||||
return 0;
|
||||
// cull the clipping planes if not trivial accept
|
||||
// FIXME: the compiler is doing a lousy job of optimizing here; it could be
|
||||
// twice as fast in ASM
|
||||
if (clipflags) {
|
||||
for (i = 0; i < 4; i++) {
|
||||
if (!(clipflags & (1 << i)))
|
||||
continue; // don't need to clip against it
|
||||
|
||||
// generate accept and reject points
|
||||
// FIXME: do with fast look-ups or integer tests based on the
|
||||
// sign bit of the floating point values
|
||||
|
||||
pindex = pfrustum_indexes[i];
|
||||
|
||||
rejectpt[0] = (float) node->minmaxs[pindex[0]];
|
||||
rejectpt[1] = (float) node->minmaxs[pindex[1]];
|
||||
rejectpt[2] = (float) node->minmaxs[pindex[2]];
|
||||
|
||||
d = DotProduct (rejectpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
|
||||
if (d <= 0) {
|
||||
*_clipflags = clipflags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
acceptpt[0] = (float) node->minmaxs[pindex[3 + 0]];
|
||||
acceptpt[1] = (float) node->minmaxs[pindex[3 + 1]];
|
||||
acceptpt[2] = (float) node->minmaxs[pindex[3 + 2]];
|
||||
|
||||
d = DotProduct (acceptpt, view_clipplanes[i].normal);
|
||||
d -= view_clipplanes[i].dist;
|
||||
if (d >= 0)
|
||||
clipflags &= ~(1 << i); // node is entirely on screen
|
||||
}
|
||||
}
|
||||
*_clipflags = clipflags;
|
||||
return 1;
|
||||
}
|
||||
|
||||
//FIXME no longer recursive: need a new name
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
struct {
|
||||
mnode_t *node;
|
||||
int side, clipflags;
|
||||
} *node_ptr, node_stack[256];
|
||||
mnode_t *front;
|
||||
int side;
|
||||
|
||||
node_ptr = node_stack;
|
||||
|
||||
while (1) {
|
||||
while (test_node (node, &clipflags)) {
|
||||
side = get_side (node);
|
||||
front = node->children[side];
|
||||
if (test_node (front, &clipflags)) {
|
||||
if (node_ptr - node_stack
|
||||
== sizeof (node_stack) / sizeof (node_stack[0]))
|
||||
Sys_Error ("node_stack overflow");
|
||||
node_ptr->node = node;
|
||||
node_ptr->side = side;
|
||||
node_ptr->clipflags = clipflags;
|
||||
node_ptr++;
|
||||
node = front;
|
||||
continue;
|
||||
}
|
||||
if (front->contents < 0 && front->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) front);
|
||||
visit_node (node, side, clipflags);
|
||||
node = node->children[!side];
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
if (node_ptr != node_stack) {
|
||||
node_ptr--;
|
||||
node = node_ptr->node;
|
||||
side = node_ptr->side;
|
||||
clipflags = node_ptr->clipflags;
|
||||
visit_node (node, side, clipflags);
|
||||
node = node->children[!side];
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (node->contents < 0 && node->contents != CONTENTS_SOLID)
|
||||
visit_leaf ((mleaf_t *) node);
|
||||
}
|
||||
#else
|
||||
static void
|
||||
R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
||||
{
|
||||
|
@ -544,7 +705,7 @@ R_RecursiveWorldNode (mnode_t *node, int clipflags)
|
|||
R_RecursiveWorldNode (node->children[!side], clipflags);
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void
|
||||
R_RenderWorld (void)
|
||||
|
|
Loading…
Reference in a new issue