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,29 +108,20 @@ 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
}
/*
SV_RunThink
SV_RunThink
Runs thinking code if time. There is some play in the exact time the think
function will be called, because it is called before any movement is done
in a frame. Not used for pushmove objects, because they must be exact.
Returns false if the entity removed itself.
Runs thinking code if time. There is some play in the exact time the think
function will be called, because it is called before any movement is done
in a frame. Not used for pushmove objects, because they must be exact.
Returns false if the entity removed itself.
*/
qboolean
SV_RunThink (edict_t *ent)
@ -188,10 +175,10 @@ SV_Impact (edict_t *e1, edict_t *e2)
}
/*
ClipVelocity
ClipVelocity
Slide off of the impacting object
returns the blocked flags (1 = floor, 2 = step / wall)
Slide off of the impacting object
returns the blocked flags (1 = floor, 2 = step / wall)
*/
static int
ClipVelocity (vec3_t in, vec3_t normal, vec3_t out, float overbounce)
@ -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,31 +47,30 @@ typedef struct
} physent_t;
typedef struct
{
int sequence; // just for debugging prints
typedef struct {
int sequence; // just for debugging prints
// player state
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int oldbuttons;
int oldonground;
float waterjumptime;
qboolean dead;
qboolean flying;
int spectator;
vec3_t origin;
vec3_t angles;
vec3_t velocity;
int oldbuttons;
int oldonground;
float waterjumptime;
qboolean dead;
qboolean flying;
int spectator;
// world state
int numphysent;
physent_t physents[MAX_PHYSENTS]; // 0 should be the world
int numphysent;
physent_t physents[MAX_PHYSENTS]; // 0 should be the world
// input
usercmd_t cmd;
usercmd_t cmd;
// results
int numtouch;
int touchindex[MAX_PHYSENTS];
int numtouch;
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) {
@ -488,12 +272,12 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
// is not solid, the whole trace is not solid
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;