mirror of
https://github.com/nzp-team/dquakeplus.git
synced 2024-11-22 11:51:21 +00:00
Use faster SV_RecursiveHullCheck
This commit is contained in:
parent
5b00aecb8c
commit
d6ed5b3866
7 changed files with 169 additions and 120 deletions
|
@ -58,7 +58,7 @@ 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);
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, start, end, &trace);
|
||||
|
||||
VectorCopy (trace.endpos, impact);
|
||||
}
|
||||
|
|
|
@ -365,7 +365,7 @@ qboolean TraceLineN (vec3_t start, vec3_t end, vec3_t impact, vec3_t normal)
|
|||
trace_t trace;
|
||||
|
||||
memset (&trace, 0, sizeof(trace));
|
||||
if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, end, &trace))
|
||||
if (!SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, start, end, &trace))
|
||||
{
|
||||
if (trace.fraction < 1)
|
||||
{
|
||||
|
@ -454,7 +454,7 @@ void CL_UpdateTEnts (void)
|
|||
VectorAdd(org, forward, b->end);
|
||||
|
||||
memset (&trace, 0, sizeof(trace_t));
|
||||
if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, org, b->end, &trace))
|
||||
if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, org, b->end, &trace))
|
||||
VectorCopy(trace.endpos, b->end);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -82,7 +82,7 @@ extern int nanmask;
|
|||
#define VectorNegate(a, b) ((b)[0] = -(a)[0], (b)[1] = -(a)[1], (b)[2] = -(a)[2])
|
||||
#define VectorSet(v, x, y, z) ((v)[0] = (x), (v)[1] = (y), (v)[2] = (z))
|
||||
#define VectorRandom(v) {do{(v)[0] = lhrandom(-1, 1);(v)[1] = lhrandom(-1, 1);(v)[2] = lhrandom(-1, 1);}while(DotProduct(v, v) > 1);}
|
||||
|
||||
#define DoublePrecisionDotProduct(x,y) ((double)(x)[0]*(y)[0]+(double)(x)[1]*(y)[1]+(double)(x)[2]*(y)[2])
|
||||
#define VSM(a,b,c) {c[0]=a[0]*b;c[1]=a[1]*b;c[2]=a[2]*b;}
|
||||
|
||||
#define VectorNormalizeFast( v ){float ilength = (float)rsqrt(DotProduct(v,v));v[0] *= ilength;v[1] *= ilength;v[2] *= ilength; }
|
||||
|
|
|
@ -3140,7 +3140,7 @@ void QMB_LaserSight (void)
|
|||
|
||||
memset (&trace, 0, sizeof(trace_t));
|
||||
trace.fraction = 1;
|
||||
SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, dest, &trace);
|
||||
SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, start, dest, &trace);
|
||||
|
||||
start[2]+=cl.crouch;
|
||||
AddParticle (p_streaktrail, start, 1, 2, 0.02, color, trace.endpos);// draw the line
|
||||
|
@ -3203,7 +3203,7 @@ void QMB_LightningBeam (vec3_t start, vec3_t end)
|
|||
if (qmb_initialized && r_part_sparks.value)
|
||||
{
|
||||
memset (&trace, 0, sizeof(trace_t));
|
||||
if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, 0, 1, start, end, &trace))
|
||||
if (!SV_RecursiveHullCheck(cl.worldmodel->hulls, 0, start, end, &trace))
|
||||
{
|
||||
if (trace.fraction < 1)
|
||||
{
|
||||
|
|
|
@ -1334,7 +1334,7 @@ void GL_DrawAliasBlendedShadow (aliashdr_t *paliashdr, int pose1, int pose2, ent
|
|||
VectorCopy (e->origin, downmove);
|
||||
downmove[2] = downmove[2] - 4096;
|
||||
memset (&downtrace, 0, sizeof(downtrace));
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, e->origin, downmove, &downtrace);
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, e->origin, downmove, &downtrace);
|
||||
|
||||
#ifdef PSP_VFPU
|
||||
s1 = vfpu_sinf( e->angles[1]/180*M_PI);
|
||||
|
@ -1711,7 +1711,7 @@ void GL_DrawQ2AliasShadow (entity_t *e, md2_t *pheader, int lastpose, int pose,
|
|||
VectorCopy (e->origin, downmove);
|
||||
downmove[2] = downmove[2] - 4096;
|
||||
memset (&downtrace, 0, sizeof(downtrace));
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, e->origin, downmove, &downtrace);
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, e->origin, downmove, &downtrace);
|
||||
|
||||
#ifdef PSP_VFPU
|
||||
s1 = vfpu_sinf( e->angles[1]/180*M_PI);
|
||||
|
@ -1853,7 +1853,7 @@ void R_SetupQ2AliasFrame (entity_t *e, md2_t *pheader)
|
|||
|
||||
downmove[2] = downmove[2] - 4096;
|
||||
memset (&downtrace, 0, sizeof(downtrace));
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, e->origin, downmove, &downtrace);
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, e->origin, downmove, &downtrace);
|
||||
|
||||
sceGuDisable (GU_TEXTURE_2D);
|
||||
sceGuEnable (GU_BLEND);
|
||||
|
@ -3362,7 +3362,7 @@ void R_DrawQ3Model (entity_t *ent)
|
|||
VectorCopy (ent->origin, downmove);
|
||||
downmove[2] -= farclip;
|
||||
memset (&downtrace, 0, sizeof(downtrace));
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, 0, 1, ent->origin, downmove, &downtrace);
|
||||
SV_RecursiveHullCheck (cl.worldmodel->hulls, 0, ent->origin, downmove, &downtrace);
|
||||
|
||||
lheight = ent->origin[2] - lightspot[2];
|
||||
|
||||
|
|
266
source/world.c
266
source/world.c
|
@ -591,30 +591,165 @@ LINE TESTING IN HULLS
|
|||
===============================================================================
|
||||
*/
|
||||
|
||||
enum
|
||||
{
|
||||
rht_solid,
|
||||
rht_empty,
|
||||
rht_impact
|
||||
};
|
||||
struct rhtctx_s
|
||||
{
|
||||
unsigned int hitcontents;
|
||||
vec3_t start, end;
|
||||
dclipnode_t *clipnodes;
|
||||
mplane_t *planes;
|
||||
};
|
||||
|
||||
// 1/32 epsilon to keep floating point happy
|
||||
#define DIST_EPSILON (0.03125)
|
||||
|
||||
/*
|
||||
==================
|
||||
Q1BSP_RecursiveHullTrace
|
||||
This does the core traceline/tracebox logic.
|
||||
This version is from FTE and attempts to be more numerically stable than vanilla.
|
||||
This is achieved by recursing at the actual decision points instead of vanilla's habit of vanilla's habit of using points that are outside of the child's volume.
|
||||
It also uses itself to test solidity on the other side of the node, which ensures consistent precision.
|
||||
The actual collision point is (still) biased by an epsilon, so the end point shouldn't be inside walls either way.
|
||||
FTE's version 'should' be more compatible with vanilla than DP's (which doesn't take care with allsolid).
|
||||
ezQuake also has a version of this logic, but I trust mine more.
|
||||
==================
|
||||
*/
|
||||
static int Q1BSP_RecursiveHullTrace (struct rhtctx_s *ctx, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
|
||||
{
|
||||
dclipnode_t *node;
|
||||
mplane_t *plane;
|
||||
float t1, t2;
|
||||
vec3_t mid;
|
||||
int side;
|
||||
float midf;
|
||||
int rht;
|
||||
|
||||
reenter:
|
||||
|
||||
if (num < 0)
|
||||
{
|
||||
/*hit a leaf*/
|
||||
if (num == CONTENTS_SOLID)
|
||||
{
|
||||
if (trace->allsolid)
|
||||
trace->startsolid = true;
|
||||
return rht_solid;
|
||||
}
|
||||
else
|
||||
{
|
||||
trace->allsolid = false;
|
||||
if (num == CONTENTS_EMPTY)
|
||||
trace->inopen = true;
|
||||
else if (num != CONTENTS_SOLID)
|
||||
trace->inwater = true;
|
||||
return rht_empty;
|
||||
}
|
||||
}
|
||||
|
||||
/*its a node*/
|
||||
|
||||
/*get the node info*/
|
||||
node = ctx->clipnodes + num;
|
||||
plane = ctx->planes + node->planenum;
|
||||
|
||||
if (plane->type < 3)
|
||||
{
|
||||
t1 = p1[plane->type] - plane->dist;
|
||||
t2 = p2[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DoublePrecisionDotProduct (plane->normal, p1) - plane->dist;
|
||||
t2 = DoublePrecisionDotProduct (plane->normal, p2) - plane->dist;
|
||||
}
|
||||
|
||||
/*if its completely on one side, resume on that side*/
|
||||
if (t1 >= 0 && t2 >= 0)
|
||||
{
|
||||
//return Q1BSP_RecursiveHullTrace (hull, node->children[0], p1f, p2f, p1, p2, trace);
|
||||
num = node->children[0];
|
||||
goto reenter;
|
||||
}
|
||||
if (t1 < 0 && t2 < 0)
|
||||
{
|
||||
//return Q1BSP_RecursiveHullTrace (hull, node->children[1], p1f, p2f, p1, p2, trace);
|
||||
num = node->children[1];
|
||||
goto reenter;
|
||||
}
|
||||
|
||||
if (plane->type < 3)
|
||||
{
|
||||
t1 = ctx->start[plane->type] - plane->dist;
|
||||
t2 = ctx->end[plane->type] - plane->dist;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct (plane->normal, ctx->start) - plane->dist;
|
||||
t2 = DotProduct (plane->normal, ctx->end) - plane->dist;
|
||||
}
|
||||
|
||||
side = t1 < 0;
|
||||
|
||||
midf = t1 / (t1 - t2);
|
||||
if (midf < p1f) midf = p1f;
|
||||
if (midf > p2f) midf = p2f;
|
||||
VectorInterpolate(ctx->start, midf, ctx->end, mid);
|
||||
|
||||
rht = Q1BSP_RecursiveHullTrace(ctx, node->children[side], p1f, midf, p1, mid, trace);
|
||||
if (rht != rht_empty && !trace->allsolid)
|
||||
return rht;
|
||||
rht = Q1BSP_RecursiveHullTrace(ctx, node->children[side^1], midf, p2f, mid, p2, trace);
|
||||
if (rht != rht_solid)
|
||||
return rht;
|
||||
|
||||
if (side)
|
||||
{
|
||||
/*we impacted the back of the node, so flip the plane*/
|
||||
trace->plane.dist = -plane->dist;
|
||||
VectorNegate(plane->normal, trace->plane.normal);
|
||||
midf = (t1 + DIST_EPSILON) / (t1 - t2);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*we impacted the front of the node*/
|
||||
trace->plane.dist = plane->dist;
|
||||
VectorCopy(plane->normal, trace->plane.normal);
|
||||
midf = (t1 - DIST_EPSILON) / (t1 - t2);
|
||||
}
|
||||
|
||||
t1 = DoublePrecisionDotProduct (trace->plane.normal, ctx->start) - trace->plane.dist;
|
||||
t2 = DoublePrecisionDotProduct (trace->plane.normal, ctx->end) - trace->plane.dist;
|
||||
midf = (t1 - DIST_EPSILON) / (t1 - t2);
|
||||
|
||||
midf = CLAMP(0, midf, 1);
|
||||
trace->fraction = midf;
|
||||
VectorCopy (mid, trace->endpos);
|
||||
VectorInterpolate(ctx->start, midf, ctx->end, trace->endpos);
|
||||
|
||||
return rht_impact;
|
||||
}
|
||||
|
||||
/*
|
||||
==================
|
||||
SV_RecursiveHullCheck
|
||||
|
||||
==================
|
||||
*/
|
||||
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace)
|
||||
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, vec3_t p1, vec3_t p2, trace_t *trace)
|
||||
{
|
||||
dclipnode_t *node;
|
||||
mplane_t *plane;
|
||||
float t1, t2;
|
||||
float frac;
|
||||
int i;
|
||||
vec3_t mid;
|
||||
int side;
|
||||
float midf;
|
||||
|
||||
// check for empty
|
||||
if (num < 0)
|
||||
if (p1[0] == p2[0] && p1[1] == p2[1] && p1[2] == p2[2])
|
||||
{
|
||||
if (num != CONTENTS_SOLID)
|
||||
/*points cannot cross planes, so do it faster*/
|
||||
int c = SV_HullPointContents(hull, hull->firstclipnode, p1);
|
||||
//trace->contents = c;
|
||||
|
||||
if (c != CONTENTS_SOLID)
|
||||
{
|
||||
trace->allsolid = false;
|
||||
if (num == CONTENTS_EMPTY)
|
||||
|
@ -624,103 +759,17 @@ qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec
|
|||
}
|
||||
else
|
||||
trace->startsolid = true;
|
||||
return true; // empty
|
||||
}
|
||||
|
||||
if (num < hull->firstclipnode || num > hull->lastclipnode)
|
||||
Sys_Error ("SV_RecursiveHullCheck: bad node number");
|
||||
|
||||
//
|
||||
// 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;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
{
|
||||
t1 = DotProduct (plane->normal, p1) - plane->dist;
|
||||
t2 = DotProduct (plane->normal, p2) - plane->dist;
|
||||
struct rhtctx_s ctx;
|
||||
VectorCopy(p1, ctx.start);
|
||||
VectorCopy(p2, ctx.end);
|
||||
ctx.clipnodes = hull->clipnodes;
|
||||
ctx.planes = hull->planes;
|
||||
return Q1BSP_RecursiveHullTrace(&ctx, hull->firstclipnode, 0, 1, p1, p2, trace) != rht_impact;
|
||||
}
|
||||
|
||||
#if 1
|
||||
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);
|
||||
#else
|
||||
if ( (t1 >= DIST_EPSILON && t2 >= DIST_EPSILON) || (t2 > t1 && t1 >= 0) )
|
||||
return SV_RecursiveHullCheck (hull, node->children[0], p1f, p2f, p1, p2, trace);
|
||||
if ( (t1 <= -DIST_EPSILON && t2 <= -DIST_EPSILON) || (t2 < t1 && t1 <= 0) )
|
||||
return SV_RecursiveHullCheck (hull, node->children[1], p1f, p2f, p1, p2, trace);
|
||||
#endif
|
||||
|
||||
// put the crosspoint DIST_EPSILON pixels on the near side
|
||||
if (t1 < 0)
|
||||
frac = (t1 + DIST_EPSILON)/(t1-t2);
|
||||
else
|
||||
frac = (t1 - DIST_EPSILON)/(t1-t2);
|
||||
if (frac < 0)
|
||||
frac = 0;
|
||||
if (frac > 1)
|
||||
frac = 1;
|
||||
|
||||
midf = p1f + (p2f - p1f)*frac;
|
||||
for (i=0 ; i<3 ; i++)
|
||||
mid[i] = p1[i] + frac*(p2[i] - p1[i]);
|
||||
|
||||
side = (t1 < 0);
|
||||
|
||||
// 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
|
||||
{
|
||||
VectorSubtract (vec3_origin, plane->normal, trace->plane.normal);
|
||||
trace->plane.dist = -plane->dist;
|
||||
}
|
||||
|
||||
while (SV_HullPointContents (hull, hull->firstclipnode, mid)
|
||||
== CONTENTS_SOLID)
|
||||
{ // shouldn't really happen, but does occasionally
|
||||
frac -= 0.1;
|
||||
if (frac < 0)
|
||||
{
|
||||
trace->fraction = midf;
|
||||
VectorCopy (mid, trace->endpos);
|
||||
Con_DPrintf ("backup past 0\n");
|
||||
return false;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -844,8 +893,9 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
|
|||
}
|
||||
|
||||
|
||||
// trace a line through the apropriate clipping hull
|
||||
SV_RecursiveHullCheck (hull, hull->firstclipnode, 0, 1, start_l, end_l, &trace);
|
||||
// trace a line through the apropriate clipping hull
|
||||
//(hull_t *hull, int num, vec3_t p1, vec3_t p2, trace_t *trace)
|
||||
SV_RecursiveHullCheck (hull, hull->firstclipnode, start_l, end_l, &trace);
|
||||
|
||||
if( trace.fraction != 1.0f )
|
||||
{
|
||||
|
|
|
@ -65,8 +65,7 @@ int SV_TruePointContents (vec3_t p);
|
|||
#define check_angles( x ) ( (int)x == 90 || (int)x == 180 || (int)x == 270 || (int)x == -90 || (int)x == -180 || (int)x == -270 )
|
||||
|
||||
edict_t *SV_TestEntityPosition (edict_t *ent);
|
||||
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, float p1f, float p2f, vec3_t p1, vec3_t p2, trace_t *trace);
|
||||
|
||||
qboolean SV_RecursiveHullCheck (hull_t *hull, int num, vec3_t p1, vec3_t p2, trace_t *trace);
|
||||
int SV_HullPointContents (hull_t *hull, int num, vec3_t p);
|
||||
|
||||
trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, edict_t *passedict);
|
||||
|
|
Loading…
Reference in a new issue