-// 1/32 epsilon to keep floating point happy
-#define DIST_EPSILON (0.03125)
-
-#define HULLCHECKSTATE_EMPTY 0
-#define HULLCHECKSTATE_SOLID 1
-#define HULLCHECKSTATE_DONE 2
-
-// LordHavoc: FIXME: this is not thread safe, if threading matters here, pass
-// this as a struct to RecursiveHullCheck, RecursiveHullCheck_Impact, etc...
-RecursiveHullCheckTraceInfo_t RecursiveHullCheckInfo;
-#define RHC RecursiveHullCheckInfo
-
-void SV_RecursiveHullCheck_Impact (mplane_t *plane, int side)
-{
- // LordHavoc: using doubles for extra accuracy
- double t1, t2, frac;
-
- // LordHavoc: now that we have found the impact, recalculate the impact
- // point from scratch for maximum accuracy, with an epsilon bias on the
- // surface distance
- frac = plane->dist;
- if (side)
- {
- frac -= DIST_EPSILON;
- VectorNegate (plane->normal, RHC.trace->plane.normal);
- RHC.trace->plane.dist = -plane->dist;
- }
- else
- {
- frac += DIST_EPSILON;
- VectorCopy (plane->normal, RHC.trace->plane.normal);
- RHC.trace->plane.dist = plane->dist;
- }
-
- if (plane->type < 3)
- {
- t1 = RHC.start[plane->type] - frac;
- t2 = RHC.start[plane->type] + RHC.dist[plane->type] - frac;
- }
- else
- {
- t1 = plane->normal[0] * RHC.start[0] + plane->normal[1] * RHC.start[1] + plane->normal[2] * RHC.start[2] - frac;
- t2 = plane->normal[0] * (RHC.start[0] + RHC.dist[0]) + plane->normal[1] * (RHC.start[1] + RHC.dist[1]) + plane->normal[2] * (RHC.start[2] + RHC.dist[2]) - frac;
- }
-
- frac = t1 / (t1 - t2);
- frac = bound(0.0f, frac, 1.0);
-
- RHC.trace->fraction = frac;
- RHC.trace->endpos[0] = RHC.start[0] + frac * RHC.dist[0];
- RHC.trace->endpos[1] = RHC.start[1] + frac * RHC.dist[1];
- RHC.trace->endpos[2] = RHC.start[2] + frac * RHC.dist[2];
-}
-
-int SV_RecursiveHullCheck (int num, double p1f, double p2f, double p1[3], double p2[3])
-{
- dclipnode_t *node;
- int side;
- double midf, mid[3];
- // LordHavoc: FIXME: this is not thread safe... if threading matters here,
- // remove the static prefixes
- static int ret;
- static mplane_t *plane;
- static double t1, t2, frac;
-
- // LordHavoc: a goto! everyone flee in terror... :)
-loc0:
- // check for empty
- if (num < 0)
- {
- RHC.trace->endcontents = num;
- if (RHC.trace->startcontents)
- {
- if (num == RHC.trace->startcontents)
- RHC.trace->allsolid = false;
- else
- {
- // if the first leaf is solid, set startsolid
- if (RHC.trace->allsolid)
- RHC.trace->startsolid = true;
- return HULLCHECKSTATE_SOLID;
- }
- return HULLCHECKSTATE_EMPTY;
- }
- else
- {
- if (num != CONTENTS_SOLID)
- {
- RHC.trace->allsolid = false;
- if (num == CONTENTS_EMPTY)
- RHC.trace->inopen = true;
- else
- RHC.trace->inwater = true;
- }
- else
- {
- // if the first leaf is solid, set startsolid
- if (RHC.trace->allsolid)
- RHC.trace->startsolid = true;
- return HULLCHECKSTATE_SOLID;
- }
- return HULLCHECKSTATE_EMPTY;
- }
- }
-
- // find the point distances
- node = RHC.hull->clipnodes + num;
-
- plane = RHC.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;
- }
-
- // LordHavoc: rearranged the side/frac code
- if (t1 >= 0)
- {
- if (t2 >= 0)
- {
- num = node->children[0];
- goto loc0;
- }
- // put the crosspoint DIST_EPSILON pixels on the near side
- side = 0;
- }
- else
- {
- if (t2 < 0)
- {
- num = node->children[1];
- goto loc0;
- }
- // put the crosspoint DIST_EPSILON pixels on the near side
- side = 1;
- }
-
- frac = t1 / (t1 - t2);
- frac = bound(0.0f, frac, 1.0);
-
- midf = p1f + ((p2f - p1f) * frac);
- mid[0] = RHC.start[0] + midf * RHC.dist[0];
- mid[1] = RHC.start[1] + midf * RHC.dist[1];
- mid[2] = RHC.start[2] + midf * RHC.dist[2];
-
- // front side first
- ret = SV_RecursiveHullCheck (node->children[side], p1f, midf, p1, mid);
- if (ret != HULLCHECKSTATE_EMPTY)
- return ret; // solid or done
- ret = SV_RecursiveHullCheck (node->children[!side], midf, p2f, mid, p2);
- if (ret != HULLCHECKSTATE_SOLID)
- return ret; // empty or done
-
- // front is air and back is solid, this is the impact point...
- SV_RecursiveHullCheck_Impact(RHC.hull->planes + node->planenum, side);
-
- return HULLCHECKSTATE_DONE;
-}
-