mirror of
https://git.code.sf.net/p/quake/quakeforge
synced 2025-03-22 18:31:27 +00:00
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:
parent
b95dce5deb
commit
2cb81b37f9
12 changed files with 258 additions and 418 deletions
|
@ -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
|
||||
|
|
|
@ -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
189
libs/models/trace.c
Normal 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];
|
||||
}
|
||||
}
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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]
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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++;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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];
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
Loading…
Reference in a new issue