From 74dfef5cd11946e5fa43f4e4f05aa3072baadc1a Mon Sep 17 00:00:00 2001 From: Bill Currie Date: Mon, 27 Aug 2001 22:16:11 +0000 Subject: [PATCH] sort-of merge world.h and (mostly: Sys/Con vs SV) world.c this winds up bringing rotated bboxes into nq :) --- nq/include/sv_progs.h | 2 + nq/include/world.h | 41 ++++++--- nq/source/pr_cmds.c | 184 ++++++++++++++++++++++++++++++++++++++- nq/source/sv_progs.c | 2 + nq/source/world.c | 198 +++++++++++++++++++++++++++++++----------- qw/include/world.h | 38 ++++---- qw/source/world.c | 29 ++++--- 7 files changed, 404 insertions(+), 90 deletions(-) diff --git a/nq/include/sv_progs.h b/nq/include/sv_progs.h index fd98c4d86..c2e94bd8a 100644 --- a/nq/include/sv_progs.h +++ b/nq/include/sv_progs.h @@ -178,6 +178,8 @@ typedef struct int pain_finished; //float int radsuit_finished; //float int speed; //Float + + int rotated_bbox; //int } sv_fields_t; extern sv_fields_t sv_fields; diff --git a/nq/include/world.h b/nq/include/world.h index 56dc92789..d852a250c 100644 --- a/nq/include/world.h +++ b/nq/include/world.h @@ -29,8 +29,9 @@ #ifndef __world_h #define __world_h -#include "QF/qtypes.h" -#include "sv_progs.h" +#include "QF/link.h" +#include "QF/mathlib.h" +#include "QF/model.h" typedef struct { @@ -43,10 +44,10 @@ 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 - plane_t plane; // surface normal at impact - edict_t *ent; // entity the surface is on + float fraction; // time completed, 1.0 = didn't hit anything + vec3_t endpos; // final position + plane_t plane; // surface normal at impact + struct edict_s *ent; // entity the surface is on } trace_t; @@ -54,16 +55,31 @@ typedef struct #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 +typedef struct areanode_s +{ + int axis; // -1 = leaf node + float dist; + struct areanode_s *children[2]; + link_t trigger_edicts; + link_t solid_edicts; +} areanode_t; + +#define AREA_DEPTH 4 +#define AREA_NODES 32 + +extern areanode_t sv_areanodes[AREA_NODES]; + +void SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, mplane_t *planes); void SV_ClearWorld (void); // called after the world model has been loaded, before linking any entities -void SV_UnlinkEdict (edict_t *ent); +void SV_UnlinkEdict (struct edict_s *ent); // call before removing an entity, and before trying to move one, // so it doesn't clip against itself // flags ent->v.modified -void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); +void SV_LinkEdict (struct edict_s *ent, qboolean touch_triggers); // Needs to be called any time an entity changes origin, mins, maxs, or solid // flags ent->v.modified // sets ent->v.absmin and ent->v.absmax @@ -75,9 +91,9 @@ int SV_TruePointContents (vec3_t p); // does not check any entities at all // the non-true version remaps the water current contents to content_water -edict_t *SV_TestEntityPosition (edict_t *ent); +struct edict_s *SV_TestEntityPosition (struct edict_s *ent); -trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); +trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, struct edict_s *passedict); // mins and maxs are reletive // if the entire move stays in a solid volume, trace.allsolid will be set @@ -90,4 +106,9 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e // passedict is explicitly excluded from clipping checks (normally NULL) +struct edict_s *SV_TestPlayerPosition (struct edict_s *ent, vec3_t origin); + +int SV_HullPointContents (hull_t *hull, int num, vec3_t p); +hull_t *SV_HullForEntity (struct edict_s *ent, vec3_t mins, vec3_t maxs, vec3_t offset); + #endif // __world_h diff --git a/nq/source/pr_cmds.c b/nq/source/pr_cmds.c index cd9a1186a..4a847170e 100644 --- a/nq/source/pr_cmds.c +++ b/nq/source/pr_cmds.c @@ -36,17 +36,19 @@ # include #endif +#include "QF/clip_hull.h" #include "QF/console.h" -#include "compat.h" #include "QF/cvar.h" #include "QF/sys.h" #include "QF/cmd.h" #include "QF/va.h" -#include "host.h" -#include "world.h" #include "QF/msg.h" + +#include "compat.h" +#include "host.h" #include "server.h" #include "sv_progs.h" +#include "world.h" #define RETURN_EDICT(p, e) ((p)->pr_globals[OFS_RETURN].integer_var = EDICT_TO_PROG(p, e)) @@ -1422,6 +1424,177 @@ PF_sqrt (progs_t *pr) #endif + +#define MAX_PF_HULLS 64 // FIXME make dynamic? +clip_hull_t *pf_hull_list[MAX_PF_HULLS]; + +static void +PF_hullpointcontents (progs_t *pr) +{ + edict_t *edict = G_EDICT (pr, OFS_PARM0); + float *mins = G_VECTOR (pr, OFS_PARM1); + float *maxs = G_VECTOR (pr, OFS_PARM2); + float *point = G_VECTOR (pr, OFS_PARM3); + hull_t *hull; + vec3_t offset; + + hull = SV_HullForEntity (edict, mins, maxs, offset); + VectorSubtract (point, offset, offset); + G_INT (pr, OFS_RETURN) = SV_HullPointContents (hull, 0, offset); +} + +static void +PF_getboxbounds (progs_t *pr) +{ + int h = G_INT (pr, OFS_PARM0) - 1; + clip_hull_t *ch; + + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) + PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); + + if (G_INT (pr, OFS_PARM1)) { + VectorCopy (ch->maxs, G_VECTOR (pr, OFS_RETURN)); + } else { + VectorCopy (ch->mins, G_VECTOR (pr, OFS_RETURN)); + } +} + +static void +PF_getboxhull (progs_t *pr) +{ + clip_hull_t *ch = 0; + int i; + + for (i = 0; i < MAX_PF_HULLS; i++) { + if (!pf_hull_list[i]) { + ch = MOD_Alloc_Hull (6, 6); + break; + } + } + + if (ch) { + pf_hull_list[i] = ch; + G_INT (pr, OFS_RETURN) = i + 1; + for (i = 0; i < MAX_MAP_HULLS; i++) + SV_InitHull (ch->hulls[i], ch->hulls[i]->clipnodes, + ch->hulls[i]->planes); + } else { + G_INT (pr, OFS_RETURN) = 0; + } +} + +static void +PF_freeboxhull (progs_t *pr) +{ + int h = G_INT (pr, OFS_PARM0) - 1; + clip_hull_t *ch; + + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) + PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); + pf_hull_list[h] = 0; + MOD_Free_Hull (ch); +} + +static vec_t +calc_dist (vec3_t p, vec3_t n, vec3_t *offsets) +{ + vec_t d = DotProduct (p, n); + vec3_t s, v; + int i; + + VectorScale (n, d, s); + for (i = 0; i < 3; i++) + if (s[i] < 0) + v[i] = offsets[0][i]; + else + v[i] = offsets[1][i]; + VectorAdd (p, v, v); + return DotProduct (v, n); +} + +static void +PF_rotate_bbox (progs_t *pr) +{ + int h = G_INT (pr, OFS_PARM0) - 1; + float *dir[3] = { + G_VECTOR (pr, OFS_PARM1), + G_VECTOR (pr, OFS_PARM2), + G_VECTOR (pr, OFS_PARM3), + }; + float *mi = G_VECTOR (pr, OFS_PARM4); + float *ma = G_VECTOR (pr, OFS_PARM5); + + vec3_t mins, maxs; + float *verts[6] = {maxs, mins, maxs, mins, maxs, mins}; + + vec3_t offsets[3][2] = { + { { 0, 0, 0 }, { 0, 0, 0} }, + { { -16, -16, -32 }, { 16, 16, 24} }, + { { -32, -32, -64 }, { 32, 32, 24} }, + }; + vec3_t v[8], d; + hull_t *hull; + clip_hull_t *ch; + int i, j; + float l; + + if (h < 0 || h > MAX_PF_HULLS - 1 || !(ch = pf_hull_list[h])) + PR_RunError (pr, "PF_freeboxhull: invalid box hull handle\n"); + + // set up the rotation matrix. the three orientation vectors form the + // columns of the rotation matrix + for (i = 0; i < 3; i++) { + for (j = 0; j < 3; j++) { + ch->axis[i][j] = dir[j][i]; + } + } + // rotate the bounding box points + for (i = 0; i < 3; i++) { + mins[i] = DotProduct (ch->axis[i], mi); + maxs[i] = DotProduct (ch->axis[i], ma); + } + // find all 8 corners of the rotated box + VectorCopy (mins, v[0]); + VectorCopy (maxs, v[1]); + VectorSubtract (maxs, mins, d); + for (i = 0; i < 3; i++) { + vec3_t x; + + l = DotProduct (d, dir[i]); + VectorScale (dir[i], l, x); + VectorAdd (mins, x, v[2 + i * 2]); + VectorSubtract (maxs, x, v[3 + i * 2]); + } + // now find the aligned bounding box + VectorCopy (v[0], ch->mins); + VectorCopy (v[0], ch->maxs); + for (i = 0; i < 8; i++) { + //Con_Printf ("'%0.1f %0.1f %0.1f'\n", v[i][0], v[i][1], v[i][2]); + for (j = 0; j < 3; j++) { + ch->mins[j] = min (ch->mins[j], v[i][j]); + ch->maxs[j] = max (ch->maxs[j], v[i][j]); + } + } + + // set up the 3 size based hulls + for (j = 0; j < 3; j++) { + hull = ch->hulls[j]; + VectorScale (offsets[j][1], -1, hull->clip_mins); + VectorScale (offsets[j][0], -1, hull->clip_maxs); + // set up the clip planes + for (i = 0; i < 6; i++) { + hull->planes[i].dist = calc_dist (verts[i], dir[i / 2], offsets[j]); + hull->planes[i].type = 4; + VectorCopy (dir[i / 2], hull->planes[i].normal); + //Con_Printf ("%f %f %f %f\n", + // hull->planes[i].dist, + // hull->planes[i].normal[0], hull->planes[i].normal[1], + // hull->planes[i].normal[2]); + } + } +} + + void PF_Fixme (progs_t *pr) { @@ -1508,5 +1681,10 @@ SV_PR_Cmds_Init () PR_AddBuiltin (&sv_pr_state, "setspawnparms", PF_setspawnparms, 78); // void(entity e) setspawnparms = #78 + PR_AddBuiltin (&sv_pr_state, "getboxbounds", PF_getboxbounds, 94); // vector (integer hull, integer max) getboxbounds = #94 + PR_AddBuiltin (&sv_pr_state, "getboxhull", PF_getboxhull, 95); // integer () getboxhull = #95 + PR_AddBuiltin (&sv_pr_state, "freeboxhull", PF_freeboxhull, 96); // void (integer hull) freeboxhull = #96 + PR_AddBuiltin (&sv_pr_state, "rotate_bbox", PF_rotate_bbox, 97); // void (integer hull, vector right, vector forward, vector up, vector mins, vector maxs) rotate_bbox = #97 + PR_AddBuiltin (&sv_pr_state, "checkextension", PF_checkextension, 99); // = #99 } diff --git a/nq/source/sv_progs.c b/nq/source/sv_progs.c index f91de31c5..6470d90a6 100644 --- a/nq/source/sv_progs.c +++ b/nq/source/sv_progs.c @@ -302,6 +302,8 @@ SV_LoadProgs (void) sv_fields.light_level = ED_GetFieldIndex (&sv_pr_state, "light_level"); sv_fields.items2 = ED_GetFieldIndex (&sv_pr_state, "items2"); sv_fields.pitch_speed = ED_GetFieldIndex (&sv_pr_state, "pitch_speed"); + + sv_fields.rotated_bbox = ED_GetFieldIndex (&sv_pr_state, "rotated_bbox"); } void diff --git a/nq/source/world.c b/nq/source/world.c index 107d991ad..5eacdd96e 100644 --- a/nq/source/world.c +++ b/nq/source/world.c @@ -29,9 +29,18 @@ #ifdef HAVE_CONFIG_H # include "config.h" #endif +#ifdef HAVE_STRING_H +# include +#endif +#ifdef HAVE_STRINGS_H +# include +#endif +#include + +#include "QF/clip_hull.h" #include "QF/console.h" -#include "QF/model.h" +#include "QF/crc.h" #include "QF/sys.h" #include "server.h" @@ -39,8 +48,8 @@ #include "world.h" /* - entities never clip against themselves, or their owner - line of sight checks trace->crosscontent, but bullets don't + entities never clip against themselves, or their owner + line of sight checks trace->crosscontent, but bullets don't */ typedef struct { @@ -57,7 +66,9 @@ typedef struct { int SV_HullPointContents (hull_t *hull, int num, vec3_t p); -/* HULL BOXES */ +/* + HULL BOXES +*/ static hull_t box_hull; static dclipnode_t box_clipnodes[6]; @@ -65,39 +76,45 @@ static mplane_t box_planes[6]; /* - SV_InitBoxHull + SV_InitHull SV_InitBoxHull Set up the planes and clipnodes so that the six floats of a bounding box can just be stored out and get a proper hull_t structure. */ void -SV_InitBoxHull (void) +SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, mplane_t *planes) { int i; int side; - box_hull.clipnodes = box_clipnodes; - box_hull.planes = box_planes; - box_hull.firstclipnode = 0; - box_hull.lastclipnode = 5; + hull->clipnodes = clipnodes; + hull->planes = planes; + hull->firstclipnode = 0; + hull->lastclipnode = 5; for (i = 0; i < 6; i++) { - box_clipnodes[i].planenum = i; + hull->clipnodes[i].planenum = i; side = i & 1; - box_clipnodes[i].children[side] = CONTENTS_EMPTY; + hull->clipnodes[i].children[side] = CONTENTS_EMPTY; if (i != 5) - box_clipnodes[i].children[side ^ 1] = i + 1; + hull->clipnodes[i].children[side ^ 1] = i + 1; else - box_clipnodes[i].children[side ^ 1] = CONTENTS_SOLID; + hull->clipnodes[i].children[side ^ 1] = CONTENTS_SOLID; - box_planes[i].type = i >> 1; - box_planes[i].normal[i >> 1] = 1; + hull->planes[i].type = i >> 1; + hull->planes[i].normal[i >> 1] = 1; } - } +void +SV_InitBoxHull (void) +{ + SV_InitHull (&box_hull, box_clipnodes, box_planes); +} + + /* SV_HullForBox @@ -117,6 +134,7 @@ SV_HullForBox (vec3_t mins, vec3_t maxs) return &box_hull; } + /* SV_HullForEntity @@ -131,10 +149,27 @@ SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) model_t *model; vec3_t size; vec3_t hullmins, hullmaxs; - hull_t *hull; + hull_t *hull = 0; + int hull_index = 0; + if ((sv_fields.rotated_bbox != -1 + && SVinteger (ent, rotated_bbox)) + || SVfloat (ent, solid) == SOLID_BSP) { + VectorSubtract (maxs, mins, size); + if (size[0] < 3) + hull_index = 0; + else if (size[0] <= 32) + hull_index = 1; + else + hull_index = 2; + } // decide which clipping hull to use, based on the size - if (SVfloat (ent, solid) == SOLID_BSP) { + if (sv_fields.rotated_bbox != -1 + && SVinteger (ent, rotated_bbox)) { + extern clip_hull_t *pf_hull_list[]; + int h = SVinteger (ent, rotated_bbox) - 1; + hull = pf_hull_list[h]->hulls[hull_index]; + } if (SVfloat (ent, solid) == SOLID_BSP) { // explicit hulls in the BSP model if (SVfloat (ent, movetype) != MOVETYPE_PUSH) Sys_Error ("SOLID_BSP without MOVETYPE_PUSH"); @@ -144,14 +179,10 @@ SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) if (!model || model->type != mod_brush) Sys_Error ("MOVETYPE_PUSH with a non bsp model"); - VectorSubtract (maxs, mins, size); - if (size[0] < 3) - hull = &model->hulls[0]; - else if (size[0] <= 32) - hull = &model->hulls[1]; - else - hull = &model->hulls[2]; + hull = &model->hulls[hull_index]; + } + if (hull) { // calculate an offset value to center the origin VectorSubtract (hull->clip_mins, mins, offset); VectorAdd (offset, SVvector (ent, origin), offset); @@ -166,21 +197,14 @@ SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset) return hull; } -/* ENTITY AREA CHECKING */ -typedef struct areanode_s { - int axis; // -1 = leaf node - float dist; - struct areanode_s *children[2]; - link_t trigger_edicts; - link_t solid_edicts; -} areanode_t; +/* + ENTITY AREA CHECKING +*/ -#define AREA_DEPTH 4 -#define AREA_NODES 32 +areanode_t sv_areanodes[AREA_NODES]; +int sv_numareanodes; -static areanode_t sv_areanodes[AREA_NODES]; -static int sv_numareanodes; areanode_t * SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) @@ -221,6 +245,7 @@ SV_CreateAreaNode (int depth, vec3_t mins, vec3_t maxs) return anode; } + void SV_ClearWorld (void) { @@ -231,6 +256,7 @@ SV_ClearWorld (void) SV_CreateAreaNode (0, sv.worldmodel->mins, sv.worldmodel->maxs); } + void SV_UnlinkEdict (edict_t *ent) { @@ -240,6 +266,7 @@ SV_UnlinkEdict (edict_t *ent) ent->area.prev = ent->area.next = NULL; } + void SV_TouchLinks (edict_t *ent, areanode_t *node) { @@ -286,6 +313,7 @@ SV_TouchLinks (edict_t *ent, areanode_t *node) SV_TouchLinks (ent, node->children[1]); } + void SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) { @@ -323,6 +351,7 @@ SV_FindTouchedLeafs (edict_t *ent, mnode_t *node) SV_FindTouchedLeafs (ent, node->children[1]); } + void SV_LinkEdict (edict_t *ent, qboolean touch_triggers) { @@ -392,7 +421,11 @@ SV_LinkEdict (edict_t *ent, qboolean touch_triggers) SV_TouchLinks (ent, sv_areanodes); } -/* POINT TESTING IN HULLS */ + +/* + POINT TESTING IN HULLS +*/ + #ifndef USE_INTEL_ASM int @@ -423,6 +456,7 @@ SV_HullPointContents (hull_t *hull, int num, vec3_t p) } #endif // !USE_INTEL_ASM + int SV_PointContents (vec3_t p) { @@ -434,16 +468,20 @@ SV_PointContents (vec3_t p) return cont; } + int SV_TruePointContents (vec3_t p) { return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); } + /* SV_TestEntityPosition This could be a lot more efficient... + A small wrapper around SV_BoxInSolidEntity that never clips against the + supplied entity. */ edict_t * SV_TestEntityPosition (edict_t *ent) @@ -461,11 +499,15 @@ SV_TestEntityPosition (edict_t *ent) return NULL; } -/* LINE TESTING IN HULLS */ + +/* + 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, vec3_t p1, vec3_t p2, trace_t *trace) @@ -590,6 +632,7 @@ SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, return false; } + /* SV_ClipMoveToEntity @@ -597,8 +640,8 @@ SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, eventually rotation) of the end points */ trace_t -SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, - vec3_t end) +SV_ClipMoveToEntity (edict_t *touched, edict_t *mover, vec3_t start, + vec3_t mins, vec3_t maxs, vec3_t end) { trace_t trace; vec3_t offset; @@ -613,7 +656,7 @@ SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, VectorCopy (end, trace.endpos); // get the clipping hull - hull = SV_HullForEntity (ent, mins, maxs, offset); + hull = SV_HullForEntity (touched, mins, maxs, offset); VectorSubtract (start, offset, start_l); VectorSubtract (end, offset, end_l); @@ -628,11 +671,12 @@ SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t maxs, // did we clip the move? if (trace.fraction < 1 || trace.startsolid) - trace.ent = ent; + trace.ent = touched; return trace; } + /* SV_ClipToLinks @@ -685,11 +729,11 @@ SV_ClipToLinks (areanode_t *node, moveclip_t * clip) } if ((int) SVfloat (touch, flags) & FL_MONSTER) - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins2, - clip->maxs2, clip->end); + trace = SV_ClipMoveToEntity (touch, clip->passedict, clip->start, + clip->mins2, clip->maxs2, clip->end); else - trace = SV_ClipMoveToEntity (touch, clip->start, clip->mins, - clip->maxs, clip->end); + trace = SV_ClipMoveToEntity (touch, clip->passedict, clip->start, + clip->mins, clip->maxs, clip->end); if (trace.allsolid || trace.startsolid || trace.fraction < clip->trace.fraction) { trace.ent = touch; @@ -712,6 +756,7 @@ SV_ClipToLinks (areanode_t *node, moveclip_t * clip) SV_ClipToLinks (node->children[1], clip); } + void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs) @@ -735,6 +780,7 @@ SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, #endif } + trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict) @@ -745,7 +791,7 @@ SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, memset (&clip, 0, sizeof (moveclip_t)); // clip to world - clip.trace = SV_ClipMoveToEntity (sv.edicts, start, mins, maxs, end); + clip.trace = SV_ClipMoveToEntity (sv.edicts, passedict, start, mins, maxs, end); clip.start = start; clip.end = end; @@ -773,3 +819,57 @@ SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, return clip.trace; } + + +edict_t * +SV_TestPlayerPosition (edict_t *ent, vec3_t origin) +{ + hull_t *hull; + edict_t *check; + vec3_t boxmins, boxmaxs; + vec3_t offset; + int e; + + // check world first + hull = &sv.worldmodel->hulls[1]; + if (SV_HullPointContents (hull, hull->firstclipnode, origin) != + CONTENTS_EMPTY) return sv.edicts; + + // check all entities + VectorAdd (origin, SVvector (ent, mins), boxmins); + VectorAdd (origin, SVvector (ent, maxs), boxmaxs); + + check = NEXT_EDICT (&sv_pr_state, sv.edicts); + for (e = 1; e < sv.num_edicts; e++, check = NEXT_EDICT (&sv_pr_state, check)) { + if (check->free) + continue; + if (check == ent) + continue; + + if (SVfloat (check, solid) != SOLID_BSP + && SVfloat (check, solid) != SOLID_BBOX + && SVfloat (check, solid) != SOLID_SLIDEBOX) + continue; + + if (boxmins[0] > SVvector (check, absmax)[0] + || boxmins[1] > SVvector (check, absmax)[1] + || boxmins[2] > SVvector (check, absmax)[2] + || boxmaxs[0] < SVvector (check, absmin)[0] + || boxmaxs[1] < SVvector (check, absmin)[1] + || boxmaxs[2] < SVvector (check, absmin)[2]) + continue; + + // get the clipping hull + hull = SV_HullForEntity (check, SVvector (ent, mins), + SVvector (ent, maxs), offset); + + VectorSubtract (origin, offset, offset); + + // test the point + if (SV_HullPointContents (hull, hull->firstclipnode, offset) != + CONTENTS_EMPTY) + return check; + } + + return NULL; +} diff --git a/qw/include/world.h b/qw/include/world.h index 272219f61..d852a250c 100644 --- a/qw/include/world.h +++ b/qw/include/world.h @@ -1,7 +1,7 @@ /* world.h - (description) + @description@ Copyright (C) 1996-1997 Id Software, Inc. @@ -25,11 +25,11 @@ $Id$ */ -// world.h -#ifndef _WORLD_H -#define _WORLD_H +#ifndef __world_h +#define __world_h +#include "QF/link.h" #include "QF/mathlib.h" #include "QF/model.h" @@ -41,15 +41,16 @@ typedef struct typedef struct { - qboolean allsolid; // if true, plane is not valid - qboolean startsolid; // if true, the initial point was in a solid area + 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 - plane_t plane; // surface normal at impact - edict_t *ent; // entity the surface is on + float fraction; // time completed, 1.0 = didn't hit anything + vec3_t endpos; // final position + plane_t plane; // surface normal at impact + struct edict_s *ent; // entity the surface is on } trace_t; + #define MOVE_NORMAL 0 #define MOVE_NOMONSTERS 1 #define MOVE_MISSILE 2 @@ -73,24 +74,26 @@ void SV_InitHull (hull_t *hull, dclipnode_t *clipnodes, mplane_t *planes); void SV_ClearWorld (void); // called after the world model has been loaded, before linking any entities -void SV_UnlinkEdict (edict_t *ent); +void SV_UnlinkEdict (struct edict_s *ent); // call before removing an entity, and before trying to move one, // so it doesn't clip against itself // flags ent->v.modified -void SV_LinkEdict (edict_t *ent, qboolean touch_triggers); +void SV_LinkEdict (struct edict_s *ent, qboolean touch_triggers); // Needs to be called any time an entity changes origin, mins, maxs, or solid // flags ent->v.modified // sets ent->v.absmin and ent->v.absmax // if touchtriggers, calls prog functions for the intersected triggers int SV_PointContents (vec3_t p); +int SV_TruePointContents (vec3_t p); // returns the CONTENTS_* value from the world at the given point. // does not check any entities at all +// the non-true version remaps the water current contents to content_water -edict_t *SV_TestEntityPosition (edict_t *ent); +struct edict_s *SV_TestEntityPosition (struct edict_s *ent); -trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict); +trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, struct edict_s *passedict); // mins and maxs are reletive // if the entire move stays in a solid volume, trace.allsolid will be set @@ -103,10 +106,9 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e // passedict is explicitly excluded from clipping checks (normally NULL) -edict_t *SV_TestPlayerPosition (edict_t *ent, vec3_t origin); +struct edict_s *SV_TestPlayerPosition (struct edict_s *ent, vec3_t origin); int SV_HullPointContents (hull_t *hull, int num, vec3_t p); -hull_t *SV_HullForEntity (edict_t *ent, vec3_t mins, vec3_t maxs, vec3_t offset); +hull_t *SV_HullForEntity (struct edict_s *ent, vec3_t mins, vec3_t maxs, vec3_t offset); - -#endif // _WORLD_H +#endif // __world_h diff --git a/qw/source/world.c b/qw/source/world.c index ec16a4f51..d935043ab 100644 --- a/qw/source/world.c +++ b/qw/source/world.c @@ -47,14 +47,10 @@ #include "world.h" /* - -entities never clip against themselves, or their owner - -line of sight checks trace->crosscontent, but bullets don't - + entities never clip against themselves, or their owner + line of sight checks trace->crosscontent, but bullets don't */ - typedef struct { vec3_t boxmins, boxmaxs; // enclose the test object along // entire move @@ -67,7 +63,6 @@ typedef struct { edict_t *passedict; } moveclip_t; - int SV_HullPointContents (hull_t *hull, int num, vec3_t p); /* @@ -463,6 +458,18 @@ SV_HullPointContents (hull_t *hull, int num, vec3_t p) int SV_PointContents (vec3_t p) +{ + int cont; + + cont = SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); + if (cont <= CONTENTS_CURRENT_0 && cont >= CONTENTS_CURRENT_DOWN) + cont = CONTENTS_WATER; + return cont; +} + + +int +SV_TruePointContents (vec3_t p) { return SV_HullPointContents (&sv.worldmodel->hulls[0], 0, p); } @@ -471,6 +478,7 @@ SV_PointContents (vec3_t p) /* SV_TestEntityPosition + This could be a lot more efficient... A small wrapper around SV_BoxInSolidEntity that never clips against the supplied entity. */ @@ -817,8 +825,8 @@ SV_TestPlayerPosition (edict_t *ent, vec3_t origin) { hull_t *hull; edict_t *check; - vec3_t boxmins, boxmaxs; - vec3_t offset; + vec3_t boxmins, boxmaxs; + vec3_t offset; int e; // check world first @@ -858,7 +866,8 @@ SV_TestPlayerPosition (edict_t *ent, vec3_t origin) // test the point if (SV_HullPointContents (hull, hull->firstclipnode, offset) != - CONTENTS_EMPTY) return check; + CONTENTS_EMPTY) + return check; } return NULL;