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_NOMONSTERS 1
#define MOVE_MISSILE 2 #define MOVE_MISSILE 2
typedef struct areanode_s typedef struct areanode_s {
{
int axis; // -1 = leaf node int axis; // -1 = leaf node
float dist; float dist;
struct areanode_s *children[2]; 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, qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
const vec3_t p1, const vec3_t p2, const vec3_t p1, const vec3_t p2,
trace_t *trace); 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 #endif // __world_h

View file

@ -8,7 +8,7 @@ lib_LTLIBRARIES= libQFmodels.la @VID_MODEL_TARGETS@
EXTRA_LTLIBRARIES= \ EXTRA_LTLIBRARIES= \
libQFmodels_gl.la libQFmodels_sw.la 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_LDFLAGS= -version-info 1:0:0 -no-undefined
libQFmodels_la_LIBADD= brush/libbrush.la $(top_builddir)/libs/util/libQFutil.la 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 // start position 12 units behind head
} }
static void static inline void
TraceLine (vec3_t start, vec3_t end, vec3_t impact) TraceLine (vec3_t start, vec3_t end, vec3_t impact)
{ {
trace_t trace; trace_t trace;
memset (&trace, 0, sizeof (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); VectorCopy (trace.endpos, impact);
} }

View file

@ -37,7 +37,6 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "host.h" #include "host.h"
#include "server.h" #include "server.h"
#include "sv_progs.h"
#include "world.h" #include "world.h"
#define sv_frametime host_frametime #define sv_frametime host_frametime
@ -93,9 +92,6 @@ SV_CheckAllEnts (void)
void void
SV_CheckVelocity (edict_t *ent) SV_CheckVelocity (edict_t *ent)
{ {
#if 0
float wishspeed;
#endif
int i; int i;
// bound velocity // bound velocity
@ -112,20 +108,11 @@ SV_CheckVelocity (edict_t *ent)
classname))); classname)));
SVvector (ent, origin)[i] = 0; SVvector (ent, origin)[i] = 0;
} }
#if 1
if (SVvector (ent, velocity)[i] > sv_maxvelocity->value) if (SVvector (ent, velocity)[i] > sv_maxvelocity->value)
SVvector (ent, velocity)[i] = sv_maxvelocity->value; SVvector (ent, velocity)[i] = sv_maxvelocity->value;
else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value) else if (SVvector (ent, velocity)[i] < -sv_maxvelocity->value)
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: default:
Sys_Error ("SV_Physics: bad movetype %i", Sys_Error ("SV_Physics: bad movetype %i",
(int) SVfloat (ent, movetype)); (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) if (SVfloat (touch, solid) == SOLID_TRIGGER)
Sys_Error ("Trigger in clipping list"); Sys_Error ("Trigger in clipping list");
if (clip->type == MOVE_NOMONSTERS && SVfloat (touch, solid) if (clip->type == MOVE_NOMONSTERS
!= SOLID_BSP) && SVfloat (touch, solid) != SOLID_BSP)
continue; continue;
if (clip->boxmins[0] > SVvector (touch, absmax)[0] if (clip->boxmins[0] > SVvector (touch, absmax)[0]

View file

@ -33,29 +33,12 @@
#include "QF/mathlib.h" #include "QF/mathlib.h"
#include "QF/model.h" #include "QF/model.h"
#include "world.h"
#define STOP_EPSILON 0.1 #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) #define MAX_PHYSENTS (MAX_CLIENTS + MAX_PACKET_ENTITIES)
typedef struct typedef struct {
{
vec3_t origin; vec3_t origin;
model_t *model; // only for bsp models model_t *model; // only for bsp models
vec3_t mins, maxs; // only for non-bsp models vec3_t mins, maxs; // only for non-bsp models
@ -64,8 +47,7 @@ typedef struct
} physent_t; } physent_t;
typedef struct typedef struct {
{
int sequence; // just for debugging prints int sequence; // just for debugging prints
// player state // player state
@ -88,7 +70,7 @@ typedef struct
// results // results
int numtouch; int numtouch;
int touchindex[MAX_PHYSENTS]; physent_t *touchindex[MAX_PHYSENTS];
} playermove_t; } playermove_t;
typedef struct { 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); int PM_PointContents (const vec3_t point);
qboolean PM_TestPlayerPosition (const vec3_t point); qboolean PM_TestPlayerPosition (const vec3_t point);
pmtrace_t PM_PlayerMove (const vec3_t start, const vec3_t stop); trace_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);
#endif // _PMOVE_H #endif // _PMOVE_H

View file

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

View file

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

View file

@ -45,6 +45,7 @@ static __attribute__ ((unused)) const char rcsid[] =
#include "compat.h" #include "compat.h"
#include "pmove.h" #include "pmove.h"
#include "world.h"
static hull_t box_hull; static hull_t box_hull;
static dclipnode_t box_clipnodes[6]; static dclipnode_t box_clipnodes[6];
@ -157,223 +158,6 @@ PM_PointContents (const vec3_t p)
return num; 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 PM_TestPlayerPosition
@ -421,21 +205,21 @@ bboxes_touch (const vec3_t min1, const vec3_t max1,
} }
/* PM_PlayerMove */ /* PM_PlayerMove */
pmtrace_t trace_t
PM_PlayerMove (const vec3_t start, const vec3_t end) PM_PlayerMove (const vec3_t start, const vec3_t end)
{ {
hull_t *hull; hull_t *hull;
int i, check_box, move_missed; int i, check_box, move_missed;
physent_t *pe; physent_t *pe;
pmtrace_t trace, total; trace_t trace, total;
vec3_t maxs, mins, offset, start_l, end_l; vec3_t maxs, mins, offset, start_l, end_l;
vec3_t move[2]; vec3_t move[2];
// fill in a default trace // fill in a default trace
memset (&total, 0, sizeof (pmtrace_t)); memset (&total, 0, sizeof (trace_t));
total.fraction = 1; total.fraction = 1;
total.ent = -1; total.ent = 0;
VectorCopy (end, total.endpos); VectorCopy (end, total.endpos);
for (i = 0; i < pmove.numphysent; i++) { 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); VectorSubtract (end, offset, end_l);
// fill in a default trace // fill in a default trace
memset (&trace, 0, sizeof (pmtrace_t)); memset (&trace, 0, sizeof (trace_t));
trace.fraction = 1; trace.fraction = 1;
trace.allsolid = true; 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][0] = max (start_l[0], end_l[0]);
move[1][1] = max (start_l[1], end_l[1]); move[1][1] = max (start_l[1], end_l[1]);
move[1][2] = max (start_l[2], end_l[2]); 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; move_missed = 1;
if (PM_HullPointContents (hull, hull->firstclipnode, if (PM_HullPointContents (hull, hull->firstclipnode,
start_l) != CONTENTS_SOLID) { start_l) != CONTENTS_SOLID) {
@ -489,11 +273,11 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
trace.allsolid = false; trace.allsolid = false;
} }
} }
}
if (!move_missed) { if (!move_missed) {
// trace a line through the appropriate clipping hull // trace a line through the appropriate clipping hull
PM_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace);
start_l, end_l, &trace);
} }
if (trace.allsolid) if (trace.allsolid)
@ -506,7 +290,7 @@ PM_PlayerMove (const vec3_t start, const vec3_t end)
// fix trace up by the offset // fix trace up by the offset
VectorAdd (trace.endpos, offset, trace.endpos); VectorAdd (trace.endpos, offset, trace.endpos);
total = trace; 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 // touch other objects
for (i = 0; i < pmove.numtouch; i++) { 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); ent = EDICT_NUM (&sv_pr_state, n);
if (!SVfunc (ent, touch) || (playertouch[n / 8] & (1 << (n % 8)))) if (!SVfunc (ent, touch) || (playertouch[n / 8] & (1 << (n % 8))))
continue; continue;

View file

@ -481,106 +481,6 @@ SV_TestEntityPosition (edict_t *ent)
return NULL; 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 SV_ClipMoveToEntity
@ -588,7 +488,7 @@ SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f,
eventually rotation) of the end points eventually rotation) of the end points
*/ */
static trace_t 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) const vec3_t mins, const vec3_t maxs, const vec3_t end)
{ {
hull_t *hull; hull_t *hull;
@ -609,8 +509,7 @@ SV_ClipMoveToEntity (edict_t *touched, edict_t *mover, const vec3_t start,
VectorSubtract (end, offset, end_l); VectorSubtract (end, offset, end_l);
// trace a line through the apropriate clipping hull // trace a line through the apropriate clipping hull
SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, MOD_TraceLine (hull, hull->firstclipnode, start_l, end_l, &trace);
&trace);
// fix trace up by the offset // fix trace up by the offset
if (trace.fraction != 1) if (trace.fraction != 1)
@ -675,10 +574,10 @@ SV_ClipToLinks (areanode_t *node, moveclip_t * clip)
} }
if ((int) SVfloat (touch, flags) & FL_MONSTER) 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); clip->mins2, clip->maxs2, clip->end);
else else
trace = SV_ClipMoveToEntity (touch, clip->passedict, clip->start, trace = SV_ClipMoveToEntity (touch, clip->start,
clip->mins, clip->maxs, clip->end); clip->mins, clip->maxs, clip->end);
if (trace.allsolid || trace.startsolid if (trace.allsolid || trace.startsolid
|| trace.fraction < clip->trace.fraction) { || 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)); memset (&clip, 0, sizeof (moveclip_t));
// clip to world // clip to world
clip.trace = SV_ClipMoveToEntity (sv.edicts, passedict, start, clip.trace = SV_ClipMoveToEntity (sv.edicts, start,
mins, maxs, end); mins, maxs, end);
clip.start = start; clip.start = start;