quakeforge/libs/models/test/trace-id.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

162 lines
3.5 KiB
C

#include "QF/sys.h"
#include "world.h"
static int
HullPointContents (hull_t *hull, int num, const vec3_t p)
{
float d;
dclipnode_t *node;
mplane_t *plane;
while (num >= 0)
{
if (num < hull->firstclipnode || num > hull->lastclipnode)
Sys_Error ("HullPointContents: bad node number");
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
if (plane->type < 3)
d = p[plane->type] - plane->dist;
else
d = DotProduct (plane->normal, p) - plane->dist;
if (d < 0)
num = node->children[1];
else
num = node->children[0];
}
return num;
}
// 1/32 epsilon to keep floating point happy
#ifndef DIST_EPSILON
#define DIST_EPSILON (0.03125)
#endif
static qboolean
SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, const vec3_t p1, const vec3_t p2, trace_t *trace)
{
dclipnode_t *node;
mplane_t *plane;
float t1, t2;
float frac;
int i;
vec3_t mid;
int side;
float midf;
// check for empty
if (num < 0)
{
if (num != CONTENTS_SOLID)
{
trace->allsolid = false;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
}
else
trace->startsolid = true;
return true; // empty
}
if (num < hull->firstclipnode || num > hull->lastclipnode)
Sys_Error ("SV_RecursiveHullCheck: bad node number");
//
// find the point distances
//
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
if (plane->type < 3)
{
t1 = p1[plane->type] - plane->dist;
t2 = p2[plane->type] - plane->dist;
}
else
{
t1 = DotProduct (plane->normal, p1) - plane->dist;
t2 = DotProduct (plane->normal, p2) - plane->dist;
}
if (t1 >= 0 && t2 >= 0)
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
if (t1 < 0 && t2 < 0)
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
// put the crosspoint DIST_EPSILON pixels on the near side
if (t1 < 0)
frac = (t1 + DIST_EPSILON)/(t1-t2);
else
frac = (t1 - DIST_EPSILON)/(t1-t2);
if (frac < 0)
frac = 0;
if (frac > 1)
frac = 1;
midf = p1f + (p2f - p1f)*frac;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
side = (t1 < 0);
// move up to the node
if (!SV_RecursiveHullCheck (hull, node->children[side], p1f, midf, p1, mid, trace) )
return false;
if (HullPointContents (hull, node->children[side^1], mid)
!= CONTENTS_SOLID)
// go past the node
return SV_RecursiveHullCheck (hull, node->children[side^1], midf, p2f, mid, p2, trace);
if (trace->allsolid)
return false; // never got out of the solid area
//==================
// the other side of the node is solid, this is the impact point
//==================
if (!side)
{
VectorCopy (plane->normal, trace->plane.normal);
trace->plane.dist = plane->dist;
}
else
{
VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
trace->plane.dist = -plane->dist;
}
#if 0
while (HullPointContents (hull, hull->firstclipnode, mid)
== CONTENTS_SOLID)
{ // shouldn't really happen, but does occasionally
frac -= 0.1;
if (frac < 0)
{
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
//Con_DPrintf ("backup past 0\n");
return false;
}
midf = p1f + (p2f - p1f)*frac;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
}
#endif
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
return false;
}
void
MOD_TraceLine (hull_t *hull, int num,
const vec3_t start_point, const vec3_t end_point,
trace_t *trace)
{
trace->fraction = 1;
trace->allsolid = true;
SV_RecursiveHullCheck (hull, num, 0, 1, start_point, end_point, trace);
}