move the *_RecursiveHullCheck functions from pmovetst.c and world.c to MOD_TraceLine in libs/models/trace.c, at the same time rewriting the code to work itteratively rather than recursively.

This is an imperfect revision of history.
This commit is contained in:
Bill Currie 2004-11-02 08:40:00 +00:00 committed by Jeff Teunissen
parent b95dce5deb
commit 2cb81b37f9
12 changed files with 258 additions and 418 deletions

View file

@ -55,8 +55,7 @@ typedef struct trace_s
#define MOVE_NOMONSTERS 1
#define MOVE_MISSILE 2
typedef struct areanode_s
{
typedef struct areanode_s {
int axis; // -1 = leaf node
float dist;
struct areanode_s *children[2];
@ -116,5 +115,7 @@ hull_t *SV_HullForEntity (struct edict_s *ent, const vec3_t mins,
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
const vec3_t p1, const vec3_t p2,
trace_t *trace);
qboolean MOD_TraceLine (hull_t *hull, int num,
const vec3_t start, const vec3_t end, trace_t *trace);
#endif // __world_h

View file

@ -8,7 +8,7 @@ lib_LTLIBRARIES= libQFmodels.la @VID_MODEL_TARGETS@
EXTRA_LTLIBRARIES= \
libQFmodels_gl.la libQFmodels_sw.la
models_sources = clip_hull.c model.c
models_sources = clip_hull.c model.c trace.c
libQFmodels_la_LDFLAGS= -version-info 1:0:0 -no-undefined
libQFmodels_la_LIBADD= brush/libbrush.la $(top_builddir)/libs/util/libQFutil.la

189
libs/models/trace.c Normal file
View file

@ -0,0 +1,189 @@
/*
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
static __attribute__ ((unused)) const char rcsid[] =
"$Id$";
#ifdef HAVE_STRING_H
# include <string.h>
#endif
#ifdef HAVE_STRINGS_H
# include <strings.h>
#endif
#include "QF/model.h"
#include "compat.h"
#include "world.h"
/* LINE TESTING IN HULLS */
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125)
typedef struct {
vec3_t backpt;
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;
int i, side;
if (plane->type < 3) {
t1 = start[plane->type] - plane->dist;
t2 = end[plane->type] - plane->dist;
} else {
t1 = DotProduct (plane->normal, start) - plane->dist;
t2 = DotProduct (plane->normal, end) - plane->dist;
}
side = t1 < 0;
if (side) {
frac = (t1 + DIST_EPSILON) / (t1 - t2);
// invert plane paramterers
trace->plane.normal[0] = -plane->normal[0];
trace->plane.normal[1] = -plane->normal[1];
trace->plane.normal[2] = -plane->normal[2];
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;
for (i = 0; i < 3; i++)
trace->endpos[i] = start[i] + frac * (end[i] - start[i]);
}
qboolean
MOD_TraceLine (hull_t *hull, int num, const vec3_t start, const vec3_t end,
trace_t *trace)
{
vec_t front, back;
vec3_t frontpt, backpt;
int side, empty, solid;
tracestack_t *tstack;
tracestack_t tracestack[256];
dclipnode_t *node;
mplane_t *plane, *split_plane;
VectorCopy (start, frontpt);
VectorCopy (end, backpt);
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 (empty || solid) {
// DONE!
trace->allsolid = solid & (num == CONTENTS_SOLID);
trace->startsolid = solid;
calc_impact (trace, start, end, split_plane);
return false;
}
// pop up the stack for a back side
if (tstack-- == tracestack) {
trace->allsolid = solid & (num == CONTENTS_SOLID);
trace->startsolid = solid;
return true;
}
// set the hit point for this plane
VectorCopy (backpt, frontpt);
// go down the back side
VectorCopy (tstack->backpt, backpt);
side = tstack->side;
split_plane = tstack->plane;
num = hull->clipnodes[tstack->num].children[side ^ 1];
}
node = hull->clipnodes + num;
plane = hull->planes + node->planenum;
if (plane->type < 3) {
front = frontpt[plane->type] - plane->dist;
back = backpt[plane->type] - plane->dist;
} else {
front = DotProduct (plane->normal, frontpt) - plane->dist;
back = DotProduct (plane->normal, backpt) - plane->dist;
}
if (front >= 0 && back >= 0) {
num = node->children[0];
continue;
}
if (front < 0 && back < 0) {
num = node->children[1];
continue;
}
side = front < 0;
front = front / (front - back);
tstack->num = num;
tstack->side = side;
tstack->plane = plane;
VectorCopy (backpt, tstack->backpt);
tstack++;
backpt[0] = frontpt[0] + front * (backpt[0] - frontpt[0]);
backpt[1] = frontpt[1] + front * (backpt[1] - frontpt[1]);
backpt[2] = frontpt[2] + front * (backpt[2] - frontpt[2]);
num = node->children[side];
}
}

View file

@ -74,13 +74,13 @@ Chase_Reset (void)
// start position 12 units behind head
}
static void
static inline void
TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{
trace_t trace;
memset (&trace, 0, sizeof (trace));
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
MOD_TraceLine (cl.worldmodel->hulls, 0, start, end, &trace);
VectorCopy (trace.endpos, impact);
}

View file

@ -37,7 +37,6 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "host.h"
#include "server.h"
#include "sv_progs.h"
#include "world.h"
#define sv_frametime host_frametime
@ -93,9 +92,6 @@ SV_CheckAllEnts (void)
void
SV_CheckVelocity (edict_t *ent)
{
#if 0
float wishspeed;
#endif
int i;
// bound velocity
@ -112,20 +108,11 @@ SV_CheckVelocity (edict_t *ent)
classname)));
SVvector (ent, origin)[i] = 0;
}
#if 1
if (SVvector (ent, velocity)[i] > sv_maxvelocity->value)
SVvector (ent, velocity)[i] = sv_maxvelocity->value;
else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value)
SVvector (ent, velocity)[i] = -sv_maxvelocity->value;
#endif
}
#if 0
wishspeed = VectorLength (SVvector (ent, velocity));
if (wishspeed > sv_maxvelocity->value) {
VectorScale (SVvector (ent, velocity), sv_maxvelocity->value /
wishspeed, SVvector (ent, velocity));
}
#endif
}
/*
@ -743,6 +730,7 @@ SV_RunEntity (edict_t *ent)
default:
Sys_Error ("SV_Physics: bad movetype %i",
(int) SVfloat (ent, movetype));
break;
}
}

View file

@ -647,8 +647,8 @@ SV_ClipToLinks (areanode_t *node, moveclip_t * clip)
if (SVfloat (touch, solid) == SOLID_TRIGGER)
Sys_Error ("Trigger in clipping list");
if (clip->type == MOVE_NOMONSTERS && SVfloat (touch, solid)
!= SOLID_BSP)
if (clip->type == MOVE_NOMONSTERS
&& SVfloat (touch, solid) != SOLID_BSP)
continue;
if (clip->boxmins[0] > SVvector (touch, absmax)[0]

View file

@ -33,29 +33,12 @@
#include "QF/mathlib.h"
#include "QF/model.h"
#include "world.h"
#define STOP_EPSILON 0.1
typedef struct
{
vec3_t normal;
float dist;
} pmplane_t;
typedef struct
{
qboolean allsolid; // if true, plane is not valid
qboolean startsolid; // if true, the initial point was in a solid area
qboolean inopen, inwater;
float fraction; // time completed, 1.0 = didn't hit anything
vec3_t endpos; // final position
pmplane_t plane; // surface normal at impact
int ent; // entity the surface is on
} pmtrace_t;
#define MAX_PHYSENTS (MAX_CLIENTS + MAX_PACKET_ENTITIES)
typedef struct
{
typedef struct {
vec3_t origin;
model_t *model; // only for bsp models
vec3_t mins, maxs; // only for non-bsp models
@ -64,8 +47,7 @@ typedef struct
} physent_t;
typedef struct
{
typedef struct {
int sequence; // just for debugging prints
// player state
@ -88,7 +70,7 @@ typedef struct
// results
int numtouch;
int touchindex[MAX_PHYSENTS];
physent_t *touchindex[MAX_PHYSENTS];
} playermove_t;
typedef struct {
@ -126,9 +108,6 @@ int PM_HullPointContents (hull_t *hull, int num, const vec3_t p);
int PM_PointContents (const vec3_t point);
qboolean PM_TestPlayerPosition (const vec3_t point);
pmtrace_t PM_PlayerMove (const vec3_t start, const vec3_t stop);
qboolean PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
const vec3_t p1, const vec3_t p2,
pmtrace_t *trace);
trace_t PM_PlayerMove (const vec3_t start, const vec3_t stop);
#endif // _PMOVE_H

View file

@ -202,7 +202,7 @@ Cam_Lock (int playernum)
Sbar_Changed ();
}
static pmtrace_t
static trace_t
Cam_DoTrace (vec3_t vec1, vec3_t vec2)
{
#if 0
@ -223,7 +223,7 @@ Cam_TryFlyby (player_state_t * self, player_state_t * player, vec3_t vec,
qboolean checkvis)
{
float len;
pmtrace_t trace;
trace_t trace;
vec3_t v;
vectoangles (vec, v);
@ -256,7 +256,7 @@ static qboolean
Cam_IsVisible (player_state_t * player, vec3_t vec)
{
float d;
pmtrace_t trace;
trace_t trace;
vec3_t v;
trace = Cam_DoTrace (player->origin, vec);
@ -682,10 +682,10 @@ CL_Cam_Init_Cvars (void)
static void
TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{
pmtrace_t trace;
trace_t trace;
memset (&trace, 0, sizeof (trace));
PM_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, start, end, &trace);
MOD_TraceLine (cl.worldmodel->hulls, 0, start, end, &trace);
VectorCopy (trace.endpos, impact);
}

View file

@ -116,7 +116,7 @@ PM_FlyMove (void)
{
float time_left, d;
int blocked, bumpcount, numbumps, numplanes, i, j;
pmtrace_t trace;
trace_t trace;
vec3_t dir, end, primal_velocity, original_velocity;
vec3_t planes[MAX_CLIP_PLANES];
@ -152,7 +152,7 @@ PM_FlyMove (void)
break; // moved the entire distance
// save entity for contact
pmove.touchindex[pmove.numtouch] = trace.ent;
pmove.touchindex[pmove.numtouch] = (physent_t *) trace.ent;
pmove.numtouch++;
if (trace.plane.normal[2] > 0.7) {
@ -221,7 +221,7 @@ static void
PM_FlymodeMove (void)
{
float pmspeed;
pmtrace_t trace;
trace_t trace;
vec3_t start, dest, pmvel, pmtmp;
pmvel[0] = forward[0] * pmove.cmd.forwardmove +
@ -261,7 +261,7 @@ static void
PM_GroundMove (void)
{
float downdist, updist;
pmtrace_t trace;
trace_t trace;
vec3_t start, dest;
vec3_t original, originalvel, down, up, downvel;
@ -340,7 +340,7 @@ PM_Friction (void)
{
float drop, friction, speed, newspeed;
float *vel;
pmtrace_t trace;
trace_t trace;
vec3_t start, stop;
if (pmove.waterjumptime)
@ -443,7 +443,7 @@ PM_WaterMove (void)
{
float wishspeed;
int i;
pmtrace_t trace;
trace_t trace;
vec3_t start, dest, wishdir, wishvel;
// user intentions
@ -554,7 +554,7 @@ void
PM_CategorizePosition (void)
{
int cont;
pmtrace_t tr;
trace_t tr;
vec3_t point;
// if the player hull point one unit down is solid, the player is on ground
@ -567,18 +567,18 @@ PM_CategorizePosition (void)
onground = -1;
} else {
tr = PM_PlayerMove (pmove.origin, point);
if (tr.plane.normal[2] < 0.7)
if (tr.plane.normal[2] < 0.7 || !tr.ent)
onground = -1; // too steep
else
onground = tr.ent;
onground = (physent_t *) tr.ent - pmove.physents;
if (onground != -1) {
pmove.waterjumptime = 0;
if (!tr.startsolid && !tr.allsolid)
VectorCopy (tr.endpos, pmove.origin);
}
// standing on an entity other than the world
if (tr.ent > 0) {
pmove.touchindex[pmove.numtouch] = tr.ent;
if (tr.ent && (physent_t *) tr.ent - pmove.physents > 0) {
pmove.touchindex[pmove.numtouch] = (physent_t *) tr.ent;
pmove.numtouch++;
}
}

View file

@ -45,6 +45,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "compat.h"
#include "pmove.h"
#include "world.h"
static hull_t box_hull;
static dclipnode_t box_clipnodes[6];
@ -157,223 +158,6 @@ PM_PointContents (const vec3_t p)
return num;
}
/* LINE TESTING IN HULLS */
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125)
#if 1
static inline void
visit_leaf (int num, pmtrace_t *trace)
{
if (num != CONTENTS_SOLID) {
trace->allsolid = false;
if (num == CONTENTS_EMPTY)
trace->inopen = true;
else
trace->inwater = true;
} else
trace->startsolid = true;
}
static inline void
fill_trace (hull_t *hull, int num, int side,
const vec3_t p1, const vec3_t p2, float p1f, float p2f,
float t1, float t2, pmtrace_t *trace)
{
float frac;
int i;
mplane_t *plane;
// the other side of the node is solid, this is the impact point
// put the crosspoint DIST_EPSILON pixels on the near side to guarantee
// mid is on the correct side of the plane
plane = hull->planes + hull->clipnodes[num].planenum;
if (!side) {
VectorCopy (plane->normal, trace->plane.normal);
trace->plane.dist = plane->dist;
frac = (t1 - DIST_EPSILON) / (t1 - t2);
} else {
VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
trace->plane.dist = -plane->dist;
frac = (t1 + DIST_EPSILON) / (t1 - t2);
}
frac = bound (0, frac, 1);
trace->fraction = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
trace->endpos[i] = p1[i] + frac * (p2[i] - p1[i]);
}
static inline float
calc_mid (float t1, float t2, const vec3_t p1, const vec3_t p2,
float p1f, float p2f, vec3_t mid)
{
float frac = t1 / (t1 - t2);
int i;
for (i=0 ; i<3 ; i++)
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
return p1f + (p2f - p1f)*frac;
}
static inline void
calc_dists (const mplane_t *plane, const vec3_t p1, const vec3_t p2,
float *t1, float *t2)
{
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;
}
}
qboolean
PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
const vec3_t p1, const vec3_t p2, pmtrace_t *trace)
{
int front, back, side;
dclipnode_t *node;
float midf, t1, t2;
vec3_t mid, _p1;
while (1) {
while (num >= 0) {
node = hull->clipnodes + num;
calc_dists (hull->planes + node->planenum, p1, p2, &t1, &t2);
side = (t1 < 0);
if (t1 >= 0 != t2 >= 0)
break;
num = node->children[side];
}
if (num < 0) {
visit_leaf (num, trace);
return true;
}
midf = calc_mid (t1, t2, p1, p2, p1f, p2f, mid);
front = node->children[side];
if (!PM_RecursiveHullCheck (hull, front, p1f, midf, p1, mid, trace))
return false;
back = node->children[side ^ 1];
if (PM_HullPointContents (hull, back, mid) == CONTENTS_SOLID) {
// got out of the solid area?
if (!trace->allsolid)
fill_trace (hull, num, side, p1, p2, p1f, p2f,
t1, t2, trace);
return false;
}
num = back;
VectorCopy (mid, _p1);
p1f = midf;
p1 = _p1;
}
}
#else
qboolean
PM_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
const vec3_t p1, const vec3_t p2, pmtrace_t *trace)
{
dclipnode_t *node;
float frac, midf, t1, t2;
int side, i;
mplane_t *plane;
vec3_t mid;
loc0:
// 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
}
// 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;
}
// LordHavoc: recursion optimization
if (t1 >= 0 && t2 >= 0) {
num = node->children[0];
goto loc0;
}
if (t1 < 0 && t2 < 0) {
num = node->children[1];
goto loc0;
}
side = (t1 < 0);
frac = t1 / (t1 - t2);
//frac = bound (0, frac, 1); // is this needed?
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
// move up to the node
if (!PM_RecursiveHullCheck (hull, node->children[side],
p1f, midf, p1, mid, trace))
return false;
if (PM_HullPointContents (hull, node->children[side ^ 1], mid)
!= CONTENTS_SOLID) {
// go past the node
return PM_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 {
// invert plane paramterers
trace->plane.normal[0] = -plane->normal[0];
trace->plane.normal[1] = -plane->normal[1];
trace->plane.normal[2] = -plane->normal[2];
trace->plane.dist = -plane->dist;
}
// put the crosspoint DIST_EPSILON pixels on the near side to guarantee
// mid is on the correct side of the plane
if (side)
frac = (t1 + DIST_EPSILON) / (t1 - t2);
else
frac = (t1 - DIST_EPSILON) / (t1 - t2);
frac = bound (0, frac, 1);
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
return false;
}
#endif
/*
PM_TestPlayerPosition
@ -421,21 +205,21 @@ bboxes_touch (const vec3_t min1, const vec3_t max1,
}
/* PM_PlayerMove */
pmtrace_t
trace_t
PM_PlayerMove (const vec3_t start, const vec3_t end)
{
hull_t *hull;
int i, check_box, move_missed;
physent_t *pe;
pmtrace_t trace, total;
trace_t trace, total;
vec3_t maxs, mins, offset, start_l, end_l;
vec3_t move[2];
// fill in a default trace
memset (&total, 0, sizeof (pmtrace_t));
memset (&total, 0, sizeof (trace_t));
total.fraction = 1;
total.ent = -1;
total.ent = 0;
VectorCopy (end, total.endpos);
for (i = 0; i < pmove.numphysent; i++) {
@ -464,7 +248,7 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
VectorSubtract (end, offset, end_l);
// fill in a default trace
memset (&trace, 0, sizeof (pmtrace_t));
memset (&trace, 0, sizeof (trace_t));
trace.fraction = 1;
trace.allsolid = true;
@ -479,7 +263,7 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
move[1][0] = max (start_l[0], end_l[0]);
move[1][1] = max (start_l[1], end_l[1]);
move[1][2] = max (start_l[2], end_l[2]);
if (!bboxes_touch (move[0], move[1], mins, maxs))
if (!bboxes_touch (move[0], move[1], mins, maxs)) {
move_missed = 1;
if (PM_HullPointContents (hull, hull->firstclipnode,
start_l) != CONTENTS_SOLID) {
@ -489,11 +273,11 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
trace.allsolid = false;
}
}
}
if (!move_missed) {
// trace a line through the appropriate clipping hull
PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1,
start_l, end_l, &trace);
MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace);
}
if (trace.allsolid)
@ -506,7 +290,7 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
// fix trace up by the offset
VectorAdd (trace.endpos, offset, trace.endpos);
total = trace;
total.ent = i;
total.ent = (struct edict_s *) &pmove.physents[i];
}
}

View file

@ -1734,7 +1734,7 @@ SV_RunCmd (usercmd_t *ucmd, qboolean inside)
// touch other objects
for (i = 0; i < pmove.numtouch; i++) {
n = pmove.physents[pmove.touchindex[i]].info;
n = pmove.touchindex[i]->info;
ent = EDICT_NUM (&sv_pr_state, n);
if (!SVfunc (ent, touch) || (playertouch[n / 8] & (1 << (n % 8))))
continue;

View file

@ -481,106 +481,6 @@ SV_TestEntityPosition (edict_t *ent)
return NULL;
}
/* LINE TESTING IN HULLS */
// 1/32 epsilon to keep floating point happy
#define DIST_EPSILON (0.03125)
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;
float frac, midf, t1, t2;
int side, i;
mplane_t *plane;
vec3_t mid;
// 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
}
// 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);
side = (t1 < 0);
frac = t1 / (t1 - t2);
//frac = bound (0, frac, 1); // is this needed?
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
// move up to the node
if (!SV_RecursiveHullCheck (hull, node->children[side],
p1f, midf, p1, mid, trace))
return false;
if (SV_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 {
// invert plane paramterers
trace->plane.normal[0] = -plane->normal[0];
trace->plane.normal[1] = -plane->normal[1];
trace->plane.normal[2] = -plane->normal[2];
trace->plane.dist = -plane->dist;
}
// put the crosspoint DIST_EPSILON pixels on the near side to guarantee
// mid is on the correct side of the plane
if (side)
frac = (t1 + DIST_EPSILON) / (t1 - t2);
else
frac = (t1 - DIST_EPSILON) / (t1 - t2);
frac = bound (0, frac, 1);
midf = p1f + (p2f - p1f) * frac;
for (i = 0; i < 3; i++)
mid[i] = p1[i] + frac * (p2[i] - p1[i]);
trace->fraction = midf;
VectorCopy (mid, trace->endpos);
return false;
}
/*
SV_ClipMoveToEntity
@ -588,7 +488,7 @@ SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
eventually rotation) of the end points
*/
static trace_t
SV_ClipMoveToEntity (edict_t *touched, edict_t *mover, const vec3_t start,
SV_ClipMoveToEntity (edict_t *touched, const vec3_t start,
const vec3_t mins, const vec3_t maxs, const vec3_t end)
{
hull_t *hull;
@ -609,8 +509,7 @@ SV_ClipMoveToEntity (edict_t *touched, edict_t *mover, const vec3_t start,
VectorSubtract (end, offset, end_l);
// trace a line through the apropriate clipping hull
SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l,
&trace);
MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace);
// fix trace up by the offset
if (trace.fraction != 1)
@ -675,10 +574,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t * clip)
}
if ((int) SVfloat (touch, flags) & FL_MONSTER)
trace = SV_ClipMoveToEntity (touch, clip->passedict, clip->start,
trace = SV_ClipMoveToEntity (touch, clip->start,
clip->mins2, clip->maxs2, clip->end);
else
trace = SV_ClipMoveToEntity (touch, clip->passedict, clip->start,
trace = SV_ClipMoveToEntity (touch, clip->start,
clip->mins, clip->maxs, clip->end);
if (trace.allsolid || trace.startsolid
|| trace.fraction < clip->trace.fraction) {
@ -735,7 +634,7 @@ SV_Move (const vec3_t start, const vec3_t mins, const vec3_t maxs,
memset (&clip, 0, sizeof (moveclip_t));
// clip to world
clip.trace = SV_ClipMoveToEntity (sv.edicts, passedict, start,
clip.trace = SV_ClipMoveToEntity (sv.edicts, start,
mins, maxs, end);
clip.start = start;