From 62364be9495c4c996cd5aa6a7b3b1d5a1a73d0bd Mon Sep 17 00:00:00 2001 From: Rudolf Polzer Date: Fri, 3 Jan 2014 12:47:37 +0100 Subject: [PATCH] Implemented. --- server.h | 1 + sv_phys.c | 18 +++++++++++++++++- world.c | 21 +++++++++++++++++++-- world.h | 1 + 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/server.h b/server.h index 0dfaf034..b7714cd6 100644 --- a/server.h +++ b/server.h @@ -581,6 +581,7 @@ trace_t SV_TraceBox(const vec3_t start, const vec3_t mins, const vec3_t maxs, co trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_t *passedict, int hitsupercontentsmask); trace_t SV_TracePoint(const vec3_t start, int type, prvm_edict_t *passedict, int hitsupercontentsmask); int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_edict_t **resultedicts); +int SV_EntitiesInBoxNearLine(const vec3_t mins, const vec3_t maxs, const vec3_t start, const vec3_t end, vec_t distance, int maxedicts, prvm_edict_t **resultedicts); qboolean SV_CanSeeBox(int numsamples, vec_t enlarge, vec3_t eye, vec3_t entboxmins, vec3_t entboxmaxs); diff --git a/sv_phys.c b/sv_phys.c index e88baa25..37d63575 100644 --- a/sv_phys.c +++ b/sv_phys.c @@ -350,7 +350,7 @@ trace_t SV_TraceLine(const vec3_t start, const vec3_t end, int type, prvm_edict_ // clip to entities // because this uses World_EntitiestoBox, we know all entity boxes overlap // the clip region, so we can skip culling checks in the loop below - numtouchedicts = SV_EntitiesInBox(clipboxmins, clipboxmaxs, MAX_EDICTS, touchedicts); + numtouchedicts = SV_EntitiesInBoxNearLine(clipboxmins, clipboxmaxs, clipstart, clipend, 0, MAX_EDICTS, touchedicts); if (numtouchedicts > MAX_EDICTS) { // this never happens @@ -749,6 +749,22 @@ int SV_EntitiesInBox(const vec3_t mins, const vec3_t maxs, int maxedicts, prvm_e return World_EntitiesInBox(&sv.world, paddedmins, paddedmaxs, maxedicts, resultedicts); } +int SV_EntitiesInBoxNearLine(const vec3_t mins, const vec3_t maxs, const vec3_t start, const vec3_t end, vec_t distance, int maxedicts, prvm_edict_t **resultedicts) +{ + prvm_prog_t *prog = SVVM_prog; + vec3_t paddedmins, paddedmaxs; + if (sv_areadebug.integer) + return SV_EntitiesInBox(mins, maxs, maxedicts, resultedicts); + if (maxedicts < 1 || resultedicts == NULL) + return 0; + // LordHavoc: discovered this actually causes its own bugs (dm6 teleporters being too close to info_teleport_destination) + //VectorSet(paddedmins, mins[0] - 10, mins[1] - 10, mins[2] - 1); + //VectorSet(paddedmaxs, maxs[0] + 10, maxs[1] + 10, maxs[2] + 1); + VectorCopy(mins, paddedmins); + VectorCopy(maxs, paddedmaxs); + return World_EntitiesInBoxNearLine(&sv.world, paddedmins, paddedmaxs, start, end, distance, maxedicts, resultedicts); +} + void SV_LinkEdict_TouchAreaGrid_Call(prvm_edict_t *touch, prvm_edict_t *ent) { prvm_prog_t *prog = SVVM_prog; diff --git a/world.c b/world.c index 553cabef..376fc997 100644 --- a/world.c +++ b/world.c @@ -263,15 +263,32 @@ int World_EntitiesInBox(world_t *world, const vec3_t requestmins, const vec3_t r return numlist; } -qboolean IsNearLine(vec3_t mins, vec3_t maxs, vec3_t linestart, vec3_t lineend, vec_t distance) +static qboolean IsNearLine(const vec3_t mins, const vec3_t maxs, const vec3_t linestart, const vec3_t lineend, vec_t distance) { + vec3_t center, linedirection, center_to_start, center_to_start_projection; + vec_t radius, center_to_start_projection_length, line_center_distance; // This tests only the infinite length line - linestart and lineend // themselves don't matter as long as they are on the line. // Also, we approximate even more: // we just test whether distance between center of mins, maxs is and // the line is smaller or equal the distance + the radius of the mins, // maxs. - return true; + VectorMAM(0.5, mins, 0.5, maxs, center); + + radius = VectorDistance(center, mins) + distance; + + VectorSubtract(lineend, linestart, linedirection); + VectorNormalize(linedirection); + + VectorSubtract(linestart, center, center_to_start); + + center_to_start_projection_length = DotProduct(center_to_start, linedirection); + + VectorScale(linedirection, center_to_start_projection_length, center_to_start_projection); + + line_center_distance = VectorDistance(center_to_start_projection, center_to_start); + + return line_center_distance <= radius; } int World_EntitiesInBoxNearLine(world_t *world, const vec3_t requestmins, const vec3_t requestmaxs, const vec3_t requeststart, const vec3_t requestend, vec_t requestdistance, int maxlist, prvm_edict_t **list) diff --git a/world.h b/world.h index e43ebd14..afbe57cf 100644 --- a/world.h +++ b/world.h @@ -115,6 +115,7 @@ void World_LinkEdict(world_t *world, struct prvm_edict_s *ent, const vec3_t mins /// \returns list of entities touching a box int World_EntitiesInBox(world_t *world, const vec3_t mins, const vec3_t maxs, int maxlist, struct prvm_edict_s **list); +int World_EntitiesInBoxNearLine(world_t *world, const vec3_t mins, const vec3_t maxs, const vec3_t start, const vec3_t end, vec_t distance, int maxlist, struct prvm_edict_s **list); void World_Start(world_t *world); void World_End(world_t *world); -- 2.39.2