quakeforge/libs/models/test/trace-qf-bad.c
Bill Currie 925300716b [mode] Go back to using dclipnode_t everywhere
It was added only because FitzQuake used it in its pre-bsp2 large-map
support. That support has been hidden in bspfile.c for some time now.
This doesn't gain much other than having one less type to worry about.

Well tested on Conflagrant Rodent (the map that caused the need for
mclipnode_t in the first place).
2022-05-19 15:16:53 +09:00

188 lines
4.3 KiB
C

/*
trace.c
BSP line tracing
Copyright (C) 2004 Bill Currie
Author: Bill Currie <bill@taniwha.org>
Date: 2004/9/25
This program is free software; you can redistribute it and/or
modify it under the terms of the GNU General Public License
as published by the Free Software Foundation; either version 2
of the License, or (at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to:
Free Software Foundation, Inc.
59 Temple Place - Suite 330
Boston, MA 02111-1307, USA
*/
#ifdef HAVE_CONFIG_H
# include "config.h"
#endif
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/model.h"
#include "QF/sys.h"
#include "compat.h"
#include "world.h"
/* LINE TESTING IN HULLS */
// 1/32 epsilon to keep floating point happy
#ifndef DIST_EPSILON
#define DIST_EPSILON (0.03125)
#endif
typedef struct {
vec3_t end;
int side;
int num;
mplane_t *plane;
} tracestack_t;
static inline void
calc_impact (trace_t *trace, const vec3_t start, const vec3_t end,
mplane_t *plane)
{
vec_t t1, t2, frac;
vec3_t dist;
t1 = PlaneDiff (start, plane);
t2 = PlaneDiff (end, plane);
if (t1 < 0) {
frac = (t1 + DIST_EPSILON) / (t1 - t2);
// invert plane paramterers
VectorNegate (plane->normal, trace->plane.normal);
trace->plane.dist = -plane->dist;
} else {
frac = (t1 - DIST_EPSILON) / (t1 - t2);
VectorCopy (plane->normal, trace->plane.normal);
trace->plane.dist = plane->dist;
}
frac = bound (0, frac, 1);
trace->fraction = frac;
VectorSubtract (end, start, dist);
VectorMultAdd (start, frac, dist, trace->endpos);
}
VISIBLE void
MOD_TraceLine (hull_t *hull, int num,
const vec3_t start_point, const vec3_t end_point,
trace_t *trace)
{
vec_t start_dist, end_dist, frac;
vec3_t start, end, dist;
int side, empty, solid;
tracestack_t *tstack;
tracestack_t tracestack[256];
dclipnode_t *node;
mplane_t *plane, *split_plane;
VectorCopy (start_point, start);
VectorCopy (end_point, end);
tstack = tracestack;
empty = 0;
solid = 0;
split_plane = 0;
while (1) {
while (num < 0) {
if (!solid && num != CONTENTS_SOLID) {
empty = 1;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
} else if (!empty && num == CONTENTS_SOLID) {
solid = 1;
} else if (solid && num != CONTENTS_SOLID) {
//FIXME not sure what I want
//made it out of the solid and into open space, continue
//on as if we were always in empty space
empty = 1;
solid = 0;
trace->startsolid = 1;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
} else if (empty/* || solid*/) {//FIXME not sure what I want
// DONE!
trace->allsolid = solid & (num == CONTENTS_SOLID);
trace->startsolid = solid;
calc_impact (trace, start_point, end_point, split_plane);
return;
}
// pop up the stack for a back side
if (tstack-- == tracestack) {
// we've finished.
trace->allsolid = solid & (num == CONTENTS_SOLID);
trace->startsolid = solid;
return;
}
// set the hit point for this plane
VectorCopy (end, start);
// go down the back side
VectorCopy (tstack->end, end);
side = tstack->side;
split_plane = tstack->plane;
num = hull->clipnodes[tstack->num].children[side ^ 1];
}
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
start_dist = PlaneDiff (start, plane);
end_dist = PlaneDiff (end, plane);
if (start_dist >= 0 && end_dist >= 0) {
// entirely in front of the plane
num = node->children[0];
continue;
}
if (start_dist < 0 && end_dist < 0) {
// entirely behind the plane
num = node->children[1];
continue;
}
side = start_dist < 0;
frac = start_dist / (start_dist - end_dist);
frac = bound (0, frac, 1);
tstack->num = num;
tstack->side = side;
tstack->plane = plane;
VectorCopy (end, tstack->end);
tstack++;
VectorSubtract (end, start, dist);
VectorMultAdd (start, frac, dist, end);
num = node->children[side];
}
}