mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2024-11-10 15:22:04 +00:00
Break out the leaf visit code into its own funciton.
This commit is contained in:
parent
4e76aa3025
commit
053d801e92
1 changed files with 74 additions and 51 deletions
|
@ -631,31 +631,91 @@ trace_contents (hull_t *hull, trace_t *trace, clipleaf_t *leaf,
|
||||||
return contents;
|
return contents;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
typedef struct {
|
||||||
|
qboolean seen_empty;
|
||||||
|
qboolean seen_solid;
|
||||||
|
qboolean moved;
|
||||||
|
plane_t *split_plane;
|
||||||
|
vec3_t vel;
|
||||||
|
const vec_t *origin;
|
||||||
|
const vec_t *start_point;
|
||||||
|
const vec_t *end_point;
|
||||||
|
} trace_state_t;
|
||||||
|
|
||||||
|
static int
|
||||||
|
visit_leaf (hull_t *hull, int num, clipleaf_t *leaf, trace_t *trace,
|
||||||
|
trace_state_t *state)
|
||||||
|
{
|
||||||
|
// it's not possible to not be in the leaf when doing a point trace
|
||||||
|
// if leaf is null, assume we're in the leaf
|
||||||
|
// if plane is null, the trace did not cross the last node plane
|
||||||
|
int in_leaf = 1;
|
||||||
|
if (trace->type != tr_point && leaf && state->split_plane)
|
||||||
|
in_leaf = check_in_leaf (hull, trace, leaf, state->split_plane,
|
||||||
|
state->vel, state->origin);
|
||||||
|
if (in_leaf && num == CONTENTS_SOLID) {
|
||||||
|
if (!state->seen_empty && !state->seen_solid) {
|
||||||
|
// this is the first leaf visited, thus the start leaf
|
||||||
|
trace->startsolid = state->seen_solid = true;
|
||||||
|
} else if (!state->seen_empty && state->seen_solid) {
|
||||||
|
// If crossing from one solid leaf to another, treat the
|
||||||
|
// whole trace as solid (this is what id does).
|
||||||
|
// However, since allsolid is initialized to true, no need
|
||||||
|
// to do anything.
|
||||||
|
if (state->moved)
|
||||||
|
return 1;
|
||||||
|
} else {
|
||||||
|
// crossing from an empty leaf to a solid leaf: the trace
|
||||||
|
// has collided.
|
||||||
|
if (state->split_plane) {
|
||||||
|
calc_impact (hull, trace, state->start_point, state->end_point,
|
||||||
|
leaf, state->split_plane);
|
||||||
|
} else {
|
||||||
|
// if there's no split plane, then there is no impact
|
||||||
|
trace->fraction = 1.0;
|
||||||
|
}
|
||||||
|
if (trace->type == tr_point)
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (in_leaf) {
|
||||||
|
state->seen_empty = true;
|
||||||
|
trace->allsolid = false;
|
||||||
|
if (num == CONTENTS_EMPTY)
|
||||||
|
trace->inopen = true;
|
||||||
|
else
|
||||||
|
trace->inwater = true;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
VISIBLE void
|
VISIBLE void
|
||||||
MOD_TraceLine (hull_t *hull, int num,
|
MOD_TraceLine (hull_t *hull, int num,
|
||||||
const vec3_t start_point, const vec3_t end_point,
|
const vec3_t start_point, const vec3_t end_point,
|
||||||
trace_t *trace)
|
trace_t *trace)
|
||||||
{
|
{
|
||||||
vec_t start_dist, end_dist, frac[2], offset;
|
vec_t start_dist, end_dist, frac[2], offset;
|
||||||
vec3_t start, end, dist, vel;
|
vec3_t start, end, dist;
|
||||||
int side;
|
int side;
|
||||||
qboolean seen_empty, seen_solid, moved;
|
|
||||||
tracestack_t *tstack;
|
tracestack_t *tstack;
|
||||||
tracestack_t tracestack[256];
|
tracestack_t tracestack[256];
|
||||||
mclipnode_t *node;
|
mclipnode_t *node;
|
||||||
plane_t *plane, *split_plane;
|
plane_t *plane;
|
||||||
clipleaf_t *leaf;
|
clipleaf_t *leaf;
|
||||||
|
trace_state_t trace_state;
|
||||||
|
|
||||||
VectorCopy (start_point, start);
|
VectorCopy (start_point, start);
|
||||||
VectorCopy (end_point, end);
|
VectorCopy (end_point, end);
|
||||||
VectorSubtract (end, start, vel);
|
VectorSubtract (end, start, trace_state.vel);
|
||||||
VectorNormalize (vel);
|
VectorNormalize (trace_state.vel);
|
||||||
|
|
||||||
tstack = tracestack;
|
tstack = tracestack;
|
||||||
seen_empty = false;
|
trace_state.start_point = start_point;
|
||||||
seen_solid = false;
|
trace_state.end_point = end_point;
|
||||||
moved = false;
|
trace_state.origin = start;
|
||||||
split_plane = 0;
|
trace_state.seen_empty = false;
|
||||||
|
trace_state.seen_solid = false;
|
||||||
|
trace_state.moved = false;
|
||||||
|
trace_state.split_plane = 0;
|
||||||
leaf = 0;
|
leaf = 0;
|
||||||
plane = 0;
|
plane = 0;
|
||||||
|
|
||||||
|
@ -667,45 +727,8 @@ MOD_TraceLine (hull_t *hull, int num,
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
while (num < 0) {
|
while (num < 0) {
|
||||||
// it's not possible to not be in the leaf when doing a point trace
|
if (visit_leaf (hull, num, leaf, trace, &trace_state))
|
||||||
// if leaf is null, assume we're in the leaf
|
return;
|
||||||
// if plane is null, the trace did not cross the last node plane
|
|
||||||
int in_leaf = 1;
|
|
||||||
if (trace->type != tr_point && leaf && split_plane)
|
|
||||||
in_leaf = check_in_leaf (hull, trace, leaf, split_plane,
|
|
||||||
vel, start);
|
|
||||||
if (in_leaf && num == CONTENTS_SOLID) {
|
|
||||||
if (!seen_empty && !seen_solid) {
|
|
||||||
// this is the first leaf visited, thus the start leaf
|
|
||||||
trace->startsolid = seen_solid = true;
|
|
||||||
} else if (!seen_empty && seen_solid) {
|
|
||||||
// If crossing from one solid leaf to another, treat the
|
|
||||||
// whole trace as solid (this is what id does).
|
|
||||||
// However, since allsolid is initialized to true, no need
|
|
||||||
// to do anything.
|
|
||||||
if (moved)
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
// crossing from an empty leaf to a solid leaf: the trace
|
|
||||||
// has collided.
|
|
||||||
if (split_plane) {
|
|
||||||
calc_impact (hull, trace, start_point, end_point, leaf,
|
|
||||||
split_plane);
|
|
||||||
} else {
|
|
||||||
// if there's no split plane, then there is no impact
|
|
||||||
trace->fraction = 1.0;
|
|
||||||
}
|
|
||||||
if (trace->type == tr_point)
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
} else if (in_leaf) {
|
|
||||||
seen_empty = true;
|
|
||||||
trace->allsolid = false;
|
|
||||||
if (num == CONTENTS_EMPTY)
|
|
||||||
trace->inopen = true;
|
|
||||||
else
|
|
||||||
trace->inwater = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
// pop up the stack for a back side
|
// pop up the stack for a back side
|
||||||
do {
|
do {
|
||||||
|
@ -721,8 +744,8 @@ MOD_TraceLine (hull_t *hull, int num,
|
||||||
// go down the back side
|
// go down the back side
|
||||||
VectorCopy (tstack->end, end);
|
VectorCopy (tstack->end, end);
|
||||||
side = tstack->side;
|
side = tstack->side;
|
||||||
split_plane = tstack->plane;
|
trace_state.split_plane = tstack->plane;
|
||||||
moved = tstack->start_frac > 0;
|
trace_state.moved = tstack->start_frac > 0;
|
||||||
|
|
||||||
if (hull->nodeleafs)
|
if (hull->nodeleafs)
|
||||||
leaf = hull->nodeleafs[tstack->num].leafs[side ^ 1];
|
leaf = hull->nodeleafs[tstack->num].leafs[side ^ 1];
|
||||||
|
@ -788,7 +811,7 @@ MOD_TraceLine (hull_t *hull, int num,
|
||||||
// if the move is parallel to the plane, then the plane is not a good
|
// if the move is parallel to the plane, then the plane is not a good
|
||||||
// split plane
|
// split plane
|
||||||
if (start_dist == end_dist)
|
if (start_dist == end_dist)
|
||||||
tstack->plane = split_plane;
|
tstack->plane = trace_state.split_plane;
|
||||||
VectorCopy (end, tstack->end);
|
VectorCopy (end, tstack->end);
|
||||||
VectorMultAdd (start, frac[side ^ 1], dist, tstack->start);
|
VectorMultAdd (start, frac[side ^ 1], dist, tstack->start);
|
||||||
tstack->start_frac = frac[side ^ 1];
|
tstack->start_frac = frac[side ^ 1];
|
||||||
|
|
Loading…
Reference in a new issue