collision code cleanups (model->brush.TraceBox is now used for everything except...
authorhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 22 Jul 2003 18:50:38 +0000 (18:50 +0000)
committerhavoc <havoc@d7cf8633-e32d-0410-b094-e92efae38249>
Tue, 22 Jul 2003 18:50:38 +0000 (18:50 +0000)
git-svn-id: svn://svn.icculus.org/twilight/trunk/darkplaces@3312 d7cf8633-e32d-0410-b094-e92efae38249

cl_collision.c
collision.c
collision.h
model_brush.c
model_shared.h
sv_main.c
world.c
world.h

index 5b85035..1abd1cb 100644 (file)
@@ -38,19 +38,19 @@ float CL_TraceLine (const vec3_t start, const vec3_t end, vec3_t impact, vec3_t
        entity_render_t *ent;
        float tracemins[3], tracemaxs[3];
        trace_t trace;
+       matrix4x4_t matrix, imatrix;
+       float tempnormal[3], starttransformed[3], endtransformed[3];
 
        if (hitent)
                *hitent = NULL;
        Mod_CheckLoaded(cl.worldmodel);
        if (cl.worldmodel && cl.worldmodel->brush.TraceBox)
-               cl.worldmodel->brush.TraceBox(cl.worldmodel, vec3_origin, vec3_origin, &trace, NULL, start, vec3_origin, vec3_origin, end);
-       else
-               Collision_ClipTrace(&trace, NULL, cl.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, start, vec3_origin, vec3_origin, end);
+               cl.worldmodel->brush.TraceBox(cl.worldmodel, &trace, start, start, end, end);
 
        if (impact)
-               VectorCopy (trace.endpos, impact);
+               VectorLerp(start, trace.fraction, end, impact);
        if (normal)
-               VectorCopy (trace.plane.normal, normal);
+               VectorCopy(trace.plane.normal, normal);
        cl_traceline_endcontents = trace.endcontents;
        maxfrac = trace.fraction;
        if (hitent && trace.fraction < 1)
@@ -72,23 +72,32 @@ float CL_TraceLine (const vec3_t start, const vec3_t end, vec3_t impact, vec3_t
                        if (ent->mins[0] > tracemaxs[0] || ent->maxs[0] < tracemins[0]
                         || ent->mins[1] > tracemaxs[1] || ent->maxs[1] < tracemins[1]
                         || ent->mins[2] > tracemaxs[2] || ent->maxs[2] < tracemins[2])
-                               continue;
+                               continue;
+
+                       Matrix4x4_CreateFromQuakeEntity(&matrix, ent->origin[0], ent->origin[1], ent->origin[2], ent->angles[0], ent->angles[1], ent->angles[2], 1);
+                       Matrix4x4_Invert_Simple(&imatrix, &matrix);
+                       Matrix4x4_Transform(&imatrix, start, starttransformed);
+                       Matrix4x4_Transform(&imatrix, end, endtransformed);
 
                        if (ent->model && ent->model->brush.TraceBox)
-                               ent->model->brush.TraceBox(ent->model, ent->origin, ent->angles, &trace, NULL, start, vec3_origin, vec3_origin, end);
-                       else
-                               Collision_ClipTrace(&trace, ent, ent->model, ent->origin, ent->angles, ent->mins, ent->maxs, start, vec3_origin, vec3_origin, end);
+                               ent->model->brush.TraceBox(ent->model, &trace, starttransformed, starttransformed, endtransformed, endtransformed);
 
-                       if (trace.allsolid || trace.startsolid || trace.fraction < maxfrac)
+                       if (trace.allsolid || trace.startsolid || maxfrac > trace.fraction)
                        {
-                               maxfrac = trace.fraction;
-                               if (impact)
-                                       VectorCopy(trace.endpos, impact);
-                               if (normal)
-                                       VectorCopy(trace.plane.normal, normal);
                                cl_traceline_endcontents = trace.endcontents;
                                if (hitent)
                                        *hitent = ent;
+                               if (maxfrac > trace.fraction)
+                               {
+                                       maxfrac = trace.fraction;
+                                       if (impact)
+                                               VectorLerp(start, trace.fraction, end, impact);
+                                       if (normal)
+                                       {
+                                               VectorCopy(trace.plane.normal, tempnormal);
+                                               Matrix4x4_Transform3x3(&matrix, tempnormal, normal);
+                                       }
+                               }
                        }
                }
        }
@@ -105,9 +114,13 @@ void CL_FindNonSolidLocation(const vec3_t in, vec3_t out, vec_t radius)
 
 int CL_PointContents(const vec3_t p)
 {
+       CL_TraceLine (p, p, NULL, NULL, 0, true, NULL);
+       return cl_traceline_endcontents;
+       /*
        // FIXME: check multiple brush models
-       if (cl.worldmodel && cl.worldmodel->brush.PointContents)
-               return cl.worldmodel->brush.PointContents(cl.worldmodel, p);
-       return CONTENTS_EMPTY;
+       if (cl.worldmodel && cl.worldmodel->brush.PointContentsQ1)
+               return cl.worldmodel->brush.PointContentsQ1(cl.worldmodel, p);
+       return 0;
+       */
 }
 
index 168ca70..2124918 100644 (file)
@@ -25,7 +25,7 @@ RecursiveHullCheckTraceInfo_t;
 #define HULLCHECKSTATE_SOLID 1
 #define HULLCHECKSTATE_DONE 2
 
-static int RecursiveHullCheck (RecursiveHullCheckTraceInfo_t *t, int num, double p1f, double p2f, double p1[3], double p2[3])
+static int RecursiveHullCheck(RecursiveHullCheckTraceInfo_t *t, int num, double p1f, double p2f, double p1[3], double p2[3])
 {
        // status variables, these don't need to be saved on the stack when
        // recursing...  but are because this should be thread-safe
@@ -45,9 +45,9 @@ loc0:
        if (num < 0)
        {
                t->trace->endcontents = num;
-               if (t->trace->startcontents)
+               if (t->trace->thiscontents)
                {
-                       if (num == t->trace->startcontents)
+                       if (num == t->trace->thiscontents)
                                t->trace->allsolid = false;
                        else
                        {
@@ -165,6 +165,7 @@ loc0:
        return HULLCHECKSTATE_DONE;
 }
 
+#if 0
 // used if start and end are the same
 static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num)
 {
@@ -174,9 +175,9 @@ static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num)
 
        // check for empty
        t->trace->endcontents = num;
-       if (t->trace->startcontents)
+       if (t->trace->thiscontents)
        {
-               if (num == t->trace->startcontents)
+               if (num == t->trace->thiscontents)
                        t->trace->allsolid = false;
                else
                {
@@ -203,6 +204,7 @@ static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num)
                }
        }
 }
+#endif
 
 void Collision_RoundUpToHullSize(const model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs)
 {
@@ -271,170 +273,30 @@ void Collision_Init (void)
        }
 }
 
-
-static hull_t *HullForBBoxEntity (const vec3_t corigin, const vec3_t cmins, const vec3_t cmaxs, const vec3_t mins, const vec3_t maxs, vec3_t offset)
-{
-       vec3_t hullmins, hullmaxs;
-
-       // create a temp hull from bounding box sizes
-       VectorCopy (corigin, offset);
-       VectorSubtract (cmins, maxs, hullmins);
-       VectorSubtract (cmaxs, mins, hullmaxs);
-
-       //To keep everything totally uniform, bounding boxes are turned into small
-       //BSP trees instead of being compared directly.
-       box_planes[0].dist = hullmaxs[0];
-       box_planes[1].dist = hullmins[0];
-       box_planes[2].dist = hullmaxs[1];
-       box_planes[3].dist = hullmins[1];
-       box_planes[4].dist = hullmaxs[2];
-       box_planes[5].dist = hullmins[2];
-       return &box_hull;
-}
-
-static const hull_t *HullForBrushModel (const model_t *cmodel, const vec3_t corigin, const vec3_t mins, const vec3_t maxs, vec3_t offset)
-{
-       vec3_t size;
-       const hull_t *hull;
-
-       // decide which clipping hull to use, based on the size
-       // explicit hulls in the BSP model
-       VectorSubtract (maxs, mins, size);
-       // LordHavoc: FIXME!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
-       if (cmodel->brushq1.ishlbsp)
-       {
-               if (size[0] < 3)
-                       hull = &cmodel->brushq1.hulls[0]; // 0x0x0
-               else if (size[0] <= 32)
-               {
-                       if (size[2] < 54) // pick the nearest of 36 or 72
-                               hull = &cmodel->brushq1.hulls[3]; // 32x32x36
-                       else
-                               hull = &cmodel->brushq1.hulls[1]; // 32x32x72
-               }
-               else
-                       hull = &cmodel->brushq1.hulls[2]; // 64x64x64
-       }
-       else
-       {
-               if (size[0] < 3)
-                       hull = &cmodel->brushq1.hulls[0]; // 0x0x0
-               else if (size[0] <= 32)
-                       hull = &cmodel->brushq1.hulls[1]; // 32x32x56
-               else
-                       hull = &cmodel->brushq1.hulls[2]; // 64x64x88
-       }
-
-       // calculate an offset value to center the origin
-       VectorSubtract (hull->clip_mins, mins, offset);
-       VectorAdd (offset, corigin, offset);
-
-       return hull;
-}
-
-void Collision_ClipTrace (trace_t *trace, const void *cent, const model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end)
+void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end)
 {
        RecursiveHullCheckTraceInfo_t rhc;
-       vec3_t offset, forward, left, up;
-       double startd[3], endd[3], tempd[3];
-
        // fill in a default trace
-       memset (&rhc, 0, sizeof(rhc));
-       memset (trace, 0, sizeof(trace_t));
-
+       memset(&rhc, 0, sizeof(rhc));
+       memset(trace, 0, sizeof(trace_t));
+       //To keep everything totally uniform, bounding boxes are turned into small
+       //BSP trees instead of being compared directly.
+       // create a temp hull from bounding box sizes
+       box_planes[0].dist = cmaxs[0] - mins[0];
+       box_planes[1].dist = cmins[0] - maxs[0];
+       box_planes[2].dist = cmaxs[1] - mins[1];
+       box_planes[3].dist = cmins[1] - maxs[1];
+       box_planes[4].dist = cmaxs[2] - mins[2];
+       box_planes[5].dist = cmins[2] - maxs[2];
+       // trace a line through the generated clipping hull
+       rhc.hull = &box_hull;
        rhc.trace = trace;
-
        rhc.trace->fraction = 1;
        rhc.trace->allsolid = true;
-
-       if (cmodel && cmodel->type == mod_brush)
-       {
-               // brush model
-
-               // get the clipping hull
-               rhc.hull = HullForBrushModel (cmodel, corigin, mins, maxs, offset);
-
-               VectorSubtract(start, offset, startd);
-               VectorSubtract(end, offset, endd);
-
-               // rotate start and end into the model's frame of reference
-               if (cangles[0] || cangles[1] || cangles[2])
-               {
-                       AngleVectorsFLU (cangles, forward, left, up);
-                       VectorCopy(startd, tempd);
-                       startd[0] = DotProduct (tempd, forward);
-                       startd[1] = DotProduct (tempd, left);
-                       startd[2] = DotProduct (tempd, up);
-                       VectorCopy(endd, tempd);
-                       endd[0] = DotProduct (tempd, forward);
-                       endd[1] = DotProduct (tempd, left);
-                       endd[2] = DotProduct (tempd, up);
-               }
-
-               // trace a line through the appropriate clipping hull
-               VectorCopy(startd, rhc.start);
-               VectorCopy(endd, rhc.end);
-               VectorCopy(rhc.end, rhc.trace->endpos);
-               VectorSubtract(rhc.end, rhc.start, rhc.dist);
-               if (rhc.dist[0] || rhc.dist[1] || rhc.dist[2])
-                       RecursiveHullCheck (&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
-               else
-                       RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode);
-               if (rhc.trace->fraction < 0 || rhc.trace->fraction > 1) Con_Printf("fraction out of bounds %f %s:%d\n", rhc.trace->fraction, __FILE__, __LINE__);
-
-               // if we hit, unrotate endpos and normal, and store the entity we hit
-               if (rhc.trace->fraction != 1)
-               {
-                       // rotate endpos back to world frame of reference
-                       if (cangles[0] || cangles[1] || cangles[2])
-                       {
-                               VectorNegate (cangles, offset);
-                               AngleVectorsFLU (offset, forward, left, up);
-
-                               VectorCopy (rhc.trace->endpos, tempd);
-                               rhc.trace->endpos[0] = DotProduct (tempd, forward);
-                               rhc.trace->endpos[1] = DotProduct (tempd, left);
-                               rhc.trace->endpos[2] = DotProduct (tempd, up);
-
-                               VectorCopy (rhc.trace->plane.normal, tempd);
-                               rhc.trace->plane.normal[0] = DotProduct (tempd, forward);
-                               rhc.trace->plane.normal[1] = DotProduct (tempd, left);
-                               rhc.trace->plane.normal[2] = DotProduct (tempd, up);
-                       }
-                       rhc.trace->ent = (void *) cent;
-               }
-               else if (rhc.trace->allsolid || rhc.trace->startsolid)
-                       rhc.trace->ent = (void *) cent;
-               // fix offset
-               VectorAdd (rhc.trace->endpos, offset, rhc.trace->endpos);
-       }
-       else
-       {
-               // bounding box
-
-               rhc.hull = HullForBBoxEntity (corigin, cmins, cmaxs, mins, maxs, offset);
-
-               // trace a line through the generated clipping hull
-               VectorSubtract(start, offset, rhc.start);
-               VectorSubtract(end, offset, rhc.end);
-               VectorCopy(rhc.end, rhc.trace->endpos);
-               VectorSubtract(rhc.end, rhc.start, rhc.dist);
-               if (rhc.dist[0] || rhc.dist[1] || rhc.dist[2])
-                       RecursiveHullCheck (&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
-               else
-                       RecursiveHullCheckPoint (&rhc, rhc.hull->firstclipnode);
-               if (rhc.trace->fraction < 0 || rhc.trace->fraction > 1) Con_Printf("fraction out of bounds %f %s:%d\n", rhc.trace->fraction, __FILE__, __LINE__);
-
-               // if we hit, store the entity we hit
-               if (rhc.trace->fraction != 1)
-               {
-                       // fix offset
-                       VectorAdd (rhc.trace->endpos, offset, rhc.trace->endpos);
-                       rhc.trace->ent = (void *) cent;
-               }
-               else if (rhc.trace->allsolid || rhc.trace->startsolid)
-                       rhc.trace->ent = (void *) cent;
-       }
+       VectorCopy(start, rhc.start);
+       VectorCopy(end, rhc.end);
+       VectorSubtract(rhc.end, rhc.start, rhc.dist);
+       RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
 }
 
 
@@ -1149,3 +1011,73 @@ void Collision_PolygonClipTrace (trace_t *trace, const void *cent, model_t *cmod
                VectorCopy(end, trace->endpos);
 }
 
+
+// LordHavoc: currently unused and not yet tested
+// note: this can be used for tracing a moving sphere vs a stationary sphere,
+// by simply adding the moving sphere's radius to the sphereradius parameter,
+// all the results are correct (impactpoint, impactnormal, and fraction)
+float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double *sphereorigin, double sphereradius, double *impactpoint, double *impactnormal)
+{
+       double dir[3], scale, v[3], deviationdist, impactdist, linelength;
+       // make sure the impactpoint and impactnormal are valid even if there is
+       // no collision
+       impactpoint[0] = lineend[0];
+       impactpoint[1] = lineend[1];
+       impactpoint[2] = lineend[2];
+       impactnormal[0] = 0;
+       impactnormal[1] = 0;
+       impactnormal[2] = 0;
+       // calculate line direction
+       dir[0] = lineend[0] - linestart[0];
+       dir[1] = lineend[1] - linestart[1];
+       dir[2] = lineend[2] - linestart[2];
+       // normalize direction
+       linelength = sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]);
+       if (linelength)
+       {
+               scale = 1.0 / linelength;
+               dir[0] *= scale;
+               dir[1] *= scale;
+               dir[2] *= scale;
+       }
+       // this dotproduct calculates the distance along the line at which the
+       // sphere origin is (nearest point to the sphere origin on the line)
+       impactdist = dir[0] * (sphereorigin[0] - linestart[0]) + dir[1] * (sphereorigin[1] - linestart[1]) + dir[2] * (sphereorigin[2] - linestart[2]);
+       // calculate point on line at that distance, and subtract the
+       // sphereorigin from it, so we have a vector to measure for the distance
+       // of the line from the sphereorigin (deviation, how off-center it is)
+       v[0] = linestart[0] + impactdist * dir[0] - sphereorigin[0];
+       v[1] = linestart[1] + impactdist * dir[1] - sphereorigin[1];
+       v[2] = linestart[2] + impactdist * dir[2] - sphereorigin[2];
+       deviationdist = v[0] * v[0] + v[1] * v[1] + v[2] * v[2];
+       // if outside the radius, it's a miss for sure
+       // (we do this comparison using squared radius to avoid a sqrt)
+       if (deviationdist > sphereradius*sphereradius)
+               return 1; // miss (off to the side)
+       // nudge back to find the correct impact distance
+       impactdist += (sqrt(deviationdist) - sphereradius);
+       if (impactdist >= linelength)
+               return 1; // miss (not close enough)
+       if (impactdist < 0)
+               return 1; // miss (linestart is past or inside sphere)
+       // calculate new impactpoint
+       impactpoint[0] = linestart[0] + impactdist * dir[0];
+       impactpoint[1] = linestart[1] + impactdist * dir[1];
+       impactpoint[2] = linestart[2] + impactdist * dir[2];
+       // calculate impactnormal (surface normal at point of impact)
+       impactnormal[0] = impactpoint[0] - sphereorigin[0];
+       impactnormal[1] = impactpoint[1] - sphereorigin[1];
+       impactnormal[2] = impactpoint[2] - sphereorigin[2];
+       // normalize impactnormal
+       scale = impactnormal[0] * impactnormal[0] + impactnormal[1] * impactnormal[1] + impactnormal[2] * impactnormal[2];
+       if (scale)
+       {
+               scale = 1.0 / sqrt(scale);
+               impactnormal[0] *= scale;
+               impactnormal[1] *= scale;
+               impactnormal[2] *= scale;
+       }
+       // return fraction of movement distance
+       return impactdist / linelength;
+}
+
index 2b2bda8..90f5df7 100644 (file)
@@ -2,13 +2,14 @@
 #ifndef COLLISION_H
 #define COLLISION_H
 
-typedef struct
+typedef struct plane_s
 {
        vec3_t  normal;
        float   dist;
-} plane_t;
+}
+plane_t;
 
-typedef struct
+typedef struct trace_s
 {
        // if true, the entire trace was in solid
        int allsolid;
@@ -29,15 +30,15 @@ typedef struct
        void *ent;
        // if not zero, treats this value as empty, and all others as solid (impact
        // on content change)
-       int startcontents;
-       // the contents that was hit at the end or impact point
+       int thiscontents;
+       // the contents at the impact or end point
        int endcontents;
 }
 trace_t;
 
 void Collision_RoundUpToHullSize(const model_t *cmodel, const vec3_t inmins, const vec3_t inmaxs, vec3_t outmins, vec3_t outmaxs);
-void Collision_Init (void);
-void Collision_ClipTrace (trace_t *trace, const void *cent, const model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
+void Collision_Init(void);
+void Collision_ClipTrace_Box(trace_t *trace, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
 
 typedef struct colpointf_s
 {
@@ -99,6 +100,6 @@ double Collision_TraceBrushPolygonDouble(const colbrushd_t *thisbrush_start, con
 float Collision_TraceBrushBModel(const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model, float *impactnormal, int *startsolid, int *allsolid);
 float Collision_TraceBrushBModelTransform(const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, model_t *model, float *impactnormal, const matrix4x4_t *modelmatrixstart, const matrix4x4_t *modelmatrixend, int *startsolid, int *allsolid);
 
-void Collision_PolygonClipTrace (trace_t *trace, const void *cent, model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
+void Collision_PolygonClipTrace(trace_t *trace, const void *cent, model_t *cmodel, const vec3_t corigin, const vec3_t cangles, const vec3_t cmins, const vec3_t cmaxs, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
 
 #endif
index 1e17042..2a466fc 100644 (file)
@@ -64,6 +64,7 @@ static mleaf_t *Mod_Q1BSP_PointInLeaf(model_t *model, const vec3_t p)
        return (mleaf_t *)node;
 }
 
+/*
 static int Mod_Q1BSP_PointContents(model_t *model, const vec3_t p)
 {
        mnode_t *node;
@@ -81,6 +82,7 @@ static int Mod_Q1BSP_PointContents(model_t *model, const vec3_t p)
 
        return ((mleaf_t *)node)->contents;
 }
+*/
 
 typedef struct findnonsolidlocationinfo_s
 {
@@ -263,6 +265,205 @@ static void Mod_Q1BSP_FindNonSolidLocation(model_t *model, const vec3_t in, vec3
        VectorCopy(info.center, out);
 }
 
+typedef struct
+{
+       // the hull we're tracing through
+       const hull_t *hull;
+
+       // the trace structure to fill in
+       trace_t *trace;
+
+       // start, end, and end - start (in model space)
+       double start[3];
+       double end[3];
+       double dist[3];
+}
+RecursiveHullCheckTraceInfo_t;
+
+// 1/32 epsilon to keep floating point happy
+#define DIST_EPSILON (0.03125)
+
+#define HULLCHECKSTATE_EMPTY 0
+#define HULLCHECKSTATE_SOLID 1
+#define HULLCHECKSTATE_DONE 2
+
+static int Mod_Q1BSP_RecursiveHullCheck(RecursiveHullCheckTraceInfo_t *t, int num, double p1f, double p2f, double p1[3], double p2[3])
+{
+       // status variables, these don't need to be saved on the stack when
+       // recursing...  but are because this should be thread-safe
+       // (note: tracing against a bbox is not thread-safe, yet)
+       int ret;
+       mplane_t *plane;
+       double t1, t2;
+
+       // variables that need to be stored on the stack when recursing
+       dclipnode_t *node;
+       int side;
+       double midf, mid[3];
+
+       // LordHavoc: a goto!  everyone flee in terror... :)
+loc0:
+       // check for empty
+       if (num < 0)
+       {
+               t->trace->endcontents = num;
+               if (t->trace->thiscontents)
+               {
+                       if (num == t->trace->thiscontents)
+                               t->trace->allsolid = false;
+                       else
+                       {
+                               // if the first leaf is solid, set startsolid
+                               if (t->trace->allsolid)
+                                       t->trace->startsolid = true;
+                               return HULLCHECKSTATE_SOLID;
+                       }
+                       return HULLCHECKSTATE_EMPTY;
+               }
+               else
+               {
+                       if (num != CONTENTS_SOLID)
+                       {
+                               t->trace->allsolid = false;
+                               if (num == CONTENTS_EMPTY)
+                                       t->trace->inopen = true;
+                               else
+                                       t->trace->inwater = true;
+                       }
+                       else
+                       {
+                               // if the first leaf is solid, set startsolid
+                               if (t->trace->allsolid)
+                                       t->trace->startsolid = true;
+                               return HULLCHECKSTATE_SOLID;
+                       }
+                       return HULLCHECKSTATE_EMPTY;
+               }
+       }
+
+       // find the point distances
+       node = t->hull->clipnodes + num;
+
+       plane = t->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)
+       {
+               if (t2 < 0)
+               {
+                       num = node->children[1];
+                       goto loc0;
+               }
+               side = 1;
+       }
+       else
+       {
+               if (t2 >= 0)
+               {
+                       num = node->children[0];
+                       goto loc0;
+               }
+               side = 0;
+       }
+
+       // the line intersects, find intersection point
+       // LordHavoc: this uses the original trace for maximum accuracy
+       if (plane->type < 3)
+       {
+               t1 = t->start[plane->type] - plane->dist;
+               t2 = t->end[plane->type] - plane->dist;
+       }
+       else
+       {
+               t1 = DotProduct (plane->normal, t->start) - plane->dist;
+               t2 = DotProduct (plane->normal, t->end) - plane->dist;
+       }
+
+       midf = t1 / (t1 - t2);
+       midf = bound(p1f, midf, p2f);
+       VectorMA(t->start, midf, t->dist, mid);
+
+       // recurse both sides, front side first
+       ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[side], p1f, midf, p1, mid);
+       // if this side is not empty, return what it is (solid or done)
+       if (ret != HULLCHECKSTATE_EMPTY)
+               return ret;
+
+       ret = Mod_Q1BSP_RecursiveHullCheck(t, node->children[side ^ 1], midf, p2f, mid, p2);
+       // if other side is not solid, return what it is (empty or done)
+       if (ret != HULLCHECKSTATE_SOLID)
+               return ret;
+
+       // front is air and back is solid, this is the impact point...
+       if (side)
+       {
+               t->trace->plane.dist = -plane->dist;
+               VectorNegate (plane->normal, t->trace->plane.normal);
+       }
+       else
+       {
+               t->trace->plane.dist = plane->dist;
+               VectorCopy (plane->normal, t->trace->plane.normal);
+       }
+
+       // bias away from surface a bit
+       t1 = DotProduct(t->trace->plane.normal, t->start) - (t->trace->plane.dist + DIST_EPSILON);
+       t2 = DotProduct(t->trace->plane.normal, t->end) - (t->trace->plane.dist + DIST_EPSILON);
+
+       midf = t1 / (t1 - t2);
+       t->trace->fraction = bound(0.0f, midf, 1.0);
+
+       return HULLCHECKSTATE_DONE;
+}
+
+static void Mod_Q1BSP_TraceBox(struct model_s *model, trace_t *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs)
+{
+       // this function currently only supports same size start and end
+       double boxsize[3];
+       RecursiveHullCheckTraceInfo_t rhc;
+
+       memset(&rhc, 0, sizeof(rhc));
+       memset(trace, 0, sizeof(trace_t));
+       rhc.trace = trace;
+       rhc.trace->fraction = 1;
+       rhc.trace->allsolid = true;
+       VectorSubtract(boxstartmaxs, boxstartmins, boxsize);
+       if (boxsize[0] < 3)
+               rhc.hull = &model->brushq1.hulls[0]; // 0x0x0
+       else if (model->brushq1.ishlbsp)
+       {
+               if (boxsize[0] <= 32)
+               {
+                       if (boxsize[2] < 54) // pick the nearest of 36 or 72
+                               rhc.hull = &model->brushq1.hulls[3]; // 32x32x36
+                       else
+                               rhc.hull = &model->brushq1.hulls[1]; // 32x32x72
+               }
+               else
+                       rhc.hull = &model->brushq1.hulls[2]; // 64x64x64
+       }
+       else
+       {
+               if (boxsize[0] <= 32)
+                       rhc.hull = &model->brushq1.hulls[1]; // 32x32x56
+               else
+                       rhc.hull = &model->brushq1.hulls[2]; // 64x64x88
+       }
+       VectorSubtract(boxstartmins, rhc.hull->clip_mins, rhc.start);
+       VectorSubtract(boxendmins, rhc.hull->clip_mins, rhc.end);
+       VectorSubtract(rhc.end, rhc.start, rhc.dist);
+       Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end);
+}
+
 static qbyte *Mod_Q1BSP_DecompressVis(model_t *model, qbyte *in)
 {
        static qbyte decompressed[MAX_MAP_LEAFS/8];
@@ -2679,7 +2880,7 @@ void Mod_Q1BSP_Load(model_t *mod, void *buffer)
        mod->brushq1.ishlbsp = i == 30;
 
        mod->brush.FindNonSolidLocation = Mod_Q1BSP_FindNonSolidLocation;
-       mod->brush.PointContents = Mod_Q1BSP_PointContents;
+       mod->brush.TraceBox = Mod_Q1BSP_TraceBox;
        mod->brushq1.PointInLeaf = Mod_Q1BSP_PointInLeaf;
        mod->brushq1.LeafPVS = Mod_Q1BSP_LeafPVS;
        mod->brushq1.BuildPVSTextureChains = Mod_Q1BSP_BuildPVSTextureChains;
index d3f12f9..2de9ec8 100644 (file)
@@ -122,12 +122,13 @@ typedef struct model_sprite_s
 }
 model_sprite_t;
 
+struct trace_s;
+
 typedef struct model_brush_s
 {
        char *entities;
        void (*FindNonSolidLocation)(struct model_s *model, const vec3_t in, vec3_t out, vec_t radius);
-       int (*PointContents)(struct model_s *model, const float *p);
-       void (*TraceBox)(struct model_s *model, const vec3_t corigin, const vec3_t cangles, void *trace, const void *cent, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end);
+       void (*TraceBox)(struct model_s *model, struct trace_s *trace, const vec3_t boxstartmins, const vec3_t boxstartmaxs, const vec3_t boxendmins, const vec3_t boxendmaxs);
 }
 model_brush_t;
 
index 74fd70b..bf05f17 100644 (file)
--- a/sv_main.c
+++ b/sv_main.c
@@ -476,7 +476,6 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
        edict_t *ent;
        eval_t *val;
        entity_state_t *baseline; // LordHavoc: delta or startup baseline
-       trace_t trace;
        model_t *model;
 
        Mod_CheckLoaded(sv.worldmodel);
@@ -605,12 +604,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
                                testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
 
-                               if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
-                                       sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, testeye, vec3_origin, vec3_origin, testorigin);
-                               else
-                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
-
-                               if (trace.fraction == 1)
+                               if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_NOMONSTERS, NULL).fraction == 1)
                                        client->visibletime[e] = realtime + 1;
                                else
                                {
@@ -619,12 +613,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                        testorigin[1] = bound(entmins[1], testeye[1], entmaxs[1]);
                                        testorigin[2] = bound(entmins[2], testeye[2], entmaxs[2]);
 
-                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
-                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, testeye, vec3_origin, vec3_origin, testorigin);
-                                       else
-                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
-
-                                       if (trace.fraction == 1)
+                                       if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_NOMONSTERS, NULL).fraction == 1)
                                                client->visibletime[e] = realtime + 1;
                                        else if (realtime > client->visibletime[e])
                                        {
@@ -817,7 +806,6 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
        vec3_t origin, angles, entmins, entmaxs, lightmins, lightmaxs, testorigin, testeye;
        edict_t *ent;
        eval_t *val;
-       trace_t trace;
        model_t *model;
        entity_state_t *s;
 
@@ -988,11 +976,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                testorigin[0] = (entmins[0] + entmaxs[0]) * 0.5f;
                                testorigin[1] = (entmins[1] + entmaxs[1]) * 0.5f;
                                testorigin[2] = (entmins[2] + entmaxs[2]) * 0.5f;
-                               if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
-                                       sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
-                               else
-                                       Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
-                               if (trace.fraction == 1)
+                               if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_NOMONSTERS, NULL).fraction == 1)
                                        client->visibletime[e] = realtime + 1;
                                else
                                {
@@ -1000,11 +984,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                        testorigin[0] = lhrandom(entmins[0], entmaxs[0]);
                                        testorigin[1] = lhrandom(entmins[1], entmaxs[1]);
                                        testorigin[2] = lhrandom(entmins[2], entmaxs[2]);
-                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
-                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
-                                       else
-                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
-                                       if (trace.fraction == 1)
+                                       if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_NOMONSTERS, NULL).fraction == 1)
                                                client->visibletime[e] = realtime + 1;
                                        else
                                        {
@@ -1014,11 +994,7 @@ void SV_WriteEntitiesToClient (client_t *client, edict_t *clent, sizebuf_t *msg)
                                                        testorigin[0] = lhrandom(lightmins[0], lightmaxs[0]);
                                                        testorigin[1] = lhrandom(lightmins[1], lightmaxs[1]);
                                                        testorigin[2] = lhrandom(lightmins[2], lightmaxs[2]);
-                                                       if (sv.worldmodel && sv.worldmodel->brush.TraceBox)
-                                                               sv.worldmodel->brush.TraceBox(sv.worldmodel, vec3_origin, vec3_origin, &trace, NULL, testeye, vec3_origin, vec3_origin, testorigin);
-                                                       else
-                                                               Collision_ClipTrace(&trace, NULL, sv.worldmodel, vec3_origin, vec3_origin, vec3_origin, vec3_origin, testeye, vec3_origin, vec3_origin, testorigin);
-                                                       if (trace.fraction == 1)
+                                                       if (SV_Move(testeye, vec3_origin, vec3_origin, testorigin, MOVE_NOMONSTERS, NULL).fraction == 1)
                                                                client->visibletime[e] = realtime + 1;
                                                        else
                                                        {
diff --git a/world.c b/world.c
index defb53c..8e3d3a4 100644 (file)
--- a/world.c
+++ b/world.c
@@ -453,11 +453,14 @@ Handles selection or creation of a clipping hull, and offseting (and
 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)
+trace_t SV_ClipMoveToEntity(edict_t *ent, const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end)
 {
        int i;
        trace_t trace;
        model_t *model = NULL;
+       matrix4x4_t matrix, imatrix;
+       float tempnormal[3], starttransformed[3], endtransformed[3];
+       float starttransformedmins[3], starttransformedmaxs[3], endtransformedmins[3], endtransformedmaxs[3];
 
        if ((int) ent->v->solid == SOLID_BSP)
        {
@@ -479,13 +482,29 @@ trace_t SV_ClipMoveToEntity (edict_t *ent, vec3_t start, vec3_t mins, vec3_t max
                        Host_Error ("SV_ClipMoveToEntity: SOLID_BSP without MOVETYPE_PUSH");
        }
 
-       if (model && model->brush.TraceBox)
-               model->brush.TraceBox(model, ent->v->origin, ent->v->angles, &trace, ent, start, mins, maxs, end);
-       // FIXME: these should go away
-       else if (sv_polygoncollisions.integer && (mins[0] != maxs[0] || mins[1] != maxs[1] || mins[2] != maxs[2]))
-               Collision_PolygonClipTrace(&trace, ent, model, ent->v->origin, ent->v->angles, ent->v->mins, ent->v->maxs, start, mins, maxs, end);
+       Matrix4x4_CreateFromQuakeEntity(&matrix, ent->v->origin[0], ent->v->origin[1], ent->v->origin[2], ent->v->angles[0], ent->v->angles[1], ent->v->angles[2], 1);
+       Matrix4x4_Invert_Simple(&imatrix, &matrix);
+       Matrix4x4_Transform(&imatrix, start, starttransformed);
+       Matrix4x4_Transform(&imatrix, end, endtransformed);
+       VectorAdd(starttransformed, maxs, starttransformedmaxs);
+       VectorAdd(endtransformed, maxs, endtransformedmaxs);
+       VectorAdd(starttransformed, mins, starttransformedmins);
+       VectorAdd(endtransformed, mins, endtransformedmins);
+
+       // FIXME: the PolygonClipTrace should go away (should all be done in model code)
+       if (sv_polygoncollisions.integer == 1)
+               Collision_PolygonClipTrace(&trace, ent, model, vec3_origin, vec3_origin, ent->v->mins, ent->v->maxs, starttransformed, mins, maxs, endtransformed);
+       else if (model && model->brush.TraceBox)
+               model->brush.TraceBox(model, &trace, starttransformedmins, starttransformedmaxs, endtransformedmins, endtransformedmaxs);
        else
-               Collision_ClipTrace(&trace, ent, model, ent->v->origin, ent->v->angles, ent->v->mins, ent->v->maxs, start, mins, maxs, end);
+               Collision_ClipTrace_Box(&trace, ent->v->mins, ent->v->maxs, starttransformed, mins, maxs, endtransformed);
+
+       if (trace.fraction < 1 || trace.startsolid)
+               trace.ent = ent;
+       VectorLerp(start, trace.fraction, end, trace.endpos);
+       VectorCopy(trace.plane.normal, tempnormal);
+       Matrix4x4_Transform3x3(&matrix, tempnormal, trace.plane.normal);
+       // FIXME: should recalc trace.plane.dist
 
        return trace;
 }
@@ -524,7 +543,7 @@ void SV_ClipToNode(moveclip_t *clip, link_t *list)
 
                if (clip->passedict)
                {
-                       if (clip->passedict->v->size[0] && !touch->v->size[0])
+                       if (!clip->passedict->v->size[0] && !touch->v->size[0])
                                continue;       // points never interact
                        if (PROG_TO_EDICT(touch->v->owner) == clip->passedict)
                                continue;       // don't clip against own missiles
@@ -570,8 +589,16 @@ void SV_ClipToNode(moveclip_t *clip, link_t *list)
                        clip->trace.fraction = trace.fraction;
                        VectorCopy(trace.endpos, clip->trace.endpos);
                        clip->trace.plane = trace.plane;
+                       //clip->trace.endcontents = trace.endcontents;
+                       clip->trace.ent = touch;
+               }
+               // FIXME: the handling of endcontents is really broken but works well enough for point checks
+               if (trace.endcontents < clip->trace.endcontents || trace.endcontents == CONTENTS_SOLID)
+               {
+                       // lower numbered (lava is lower than water, for example)
+                       // contents override higher numbered contents, except for
+                       // CONTENTS_SOLID which overrides everything
                        clip->trace.endcontents = trace.endcontents;
-                       clip->trace.ent = trace.ent;
                }
                if (clip->trace.allsolid)
                        return;
@@ -579,90 +606,18 @@ void SV_ClipToNode(moveclip_t *clip, link_t *list)
 }
 
 /*
-====================
-SV_ClipToAreaGrid
-
-Mins and maxs enclose the entire area swept by the move
-====================
-*/
-void SV_ClipToAreaGrid(moveclip_t *clip)
-{
-       areagrid_t *grid;
-       int igrid[3], igridmins[3], igridmaxs[3];
-
-       if (clip->trace.allsolid)
-               return;
-
-       sv_areagrid_stats_calls++;
-       sv_areagrid_marknumber++;
-       igridmins[0] = (int) ((clip->boxmins[0] + sv_areagrid_bias[0]) * sv_areagrid_scale[0]);
-       igridmins[1] = (int) ((clip->boxmins[1] + sv_areagrid_bias[1]) * sv_areagrid_scale[1]);
-       //igridmins[2] = (int) ((clip->boxmins[2] + sv_areagrid_bias[2]) * sv_areagrid_scale[2]);
-       igridmaxs[0] = (int) ((clip->boxmaxs[0] + sv_areagrid_bias[0]) * sv_areagrid_scale[0]) + 1;
-       igridmaxs[1] = (int) ((clip->boxmaxs[1] + sv_areagrid_bias[1]) * sv_areagrid_scale[1]) + 1;
-       //igridmaxs[2] = (int) ((clip->boxmaxs[2] + sv_areagrid_bias[2]) * sv_areagrid_scale[2]) + 1;
-       igridmins[0] = max(0, igridmins[0]);
-       igridmins[1] = max(0, igridmins[1]);
-       //igridmins[2] = max(0, igridmins[2]);
-       igridmaxs[0] = min(AREA_GRID, igridmaxs[0]);
-       igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
-       //igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
-
-       if (sv_areagrid_outside.solid_edicts.next != &sv_areagrid_outside.solid_edicts)
-               SV_ClipToNode(clip, &sv_areagrid_outside.solid_edicts);
-
-       for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
-               for (grid = sv_areagrid + igrid[1] * AREA_GRID + igridmins[0], igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
-                       if (grid->solid_edicts.next != &grid->solid_edicts)
-                               SV_ClipToNode(clip, &grid->solid_edicts);
-}
-
-
-/*
-==================
-SV_MoveBounds
-==================
-*/
-void SV_MoveBounds (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, vec3_t boxmins, vec3_t boxmaxs)
-{
-       if (!sv_debugmove.integer)
-       {
-               int i;
-
-               for (i=0 ; i<3 ; i++)
-               {
-                       if (end[i] > start[i])
-                       {
-                               boxmins[i] = start[i] + mins[i] - 1;
-                               boxmaxs[i] = end[i] + maxs[i] + 1;
-                       }
-                       else
-                       {
-                               boxmins[i] = end[i] + mins[i] - 1;
-                               boxmaxs[i] = start[i] + maxs[i] + 1;
-                       }
-               }
-       }
-       else
-       {
-               // debug to test against everything
-               boxmins[0] = boxmins[1] = boxmins[2] = -999999999;
-               boxmaxs[0] = boxmaxs[1] = boxmaxs[2] =  999999999;
-       }
-}
-
-/*
 ==================
 SV_Move
 ==================
 */
-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(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, edict_t *passedict)
 {
-       moveclip_t      clip;
-       vec3_t          bigmins, bigmaxs;
-       int                     i;
+       moveclip_t clip;
+       vec3_t bigmins, bigmaxs;
+       areagrid_t *grid;
+       int i, igrid[3], igridmins[3], igridmaxs[3];
 
-       memset ( &clip, 0, sizeof ( moveclip_t ) );
+       memset(&clip, 0, sizeof(moveclip_t));
 
        VectorCopy(start, clip.start);
        VectorCopy(end, clip.end);
@@ -673,7 +628,12 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e
 
        Collision_RoundUpToHullSize(sv.worldmodel, clip.mins, clip.maxs, clip.hullmins, clip.hullmaxs);
 
-       if (type == MOVE_MISSILE)
+       // clip to world
+       clip.trace = SV_ClipMoveToEntity(sv.edicts, clip.start, clip.hullmins, clip.hullmaxs, clip.end);
+       //if (clip.trace.allsolid)
+       //      return clip.trace;
+
+       if (clip.type == MOVE_MISSILE)
        {
                // LordHavoc: modified this, was = -15, now = clip.mins[i] - 15
                for (i=0 ; i<3 ; i++)
@@ -695,22 +655,67 @@ trace_t SV_Move (vec3_t start, vec3_t mins, vec3_t maxs, vec3_t end, int type, e
        bigmins[2] = min(clip.mins2[2], clip.hullmins[2]);
        bigmaxs[2] = max(clip.maxs2[2], clip.hullmaxs[2]);
 
-       // clip to world
-       clip.trace = SV_ClipMoveToEntity (sv.edicts, start, mins, maxs, end);
-
-       // clip to entities
        // create the bounding box of the entire move
-       SV_MoveBounds ( start, bigmins, bigmaxs, end, clip.boxmins, clip.boxmaxs );
+       if (!sv_debugmove.integer)
+       {
+               int i;
+
+               for (i=0 ; i<3 ; i++)
+               {
+                       if (clip.trace.endpos[i] > clip.start[i])
+                       {
+                               clip.boxmins[i] = clip.start[i] + bigmins[i] - 1;
+                               clip.boxmaxs[i] = clip.trace.endpos[i] + bigmaxs[i] + 1;
+                       }
+                       else
+                       {
+                               clip.boxmins[i] = clip.trace.endpos[i] + bigmins[i] - 1;
+                               clip.boxmaxs[i] = clip.start[i] + bigmaxs[i] + 1;
+                       }
+               }
+       }
+       else
+       {
+               // debug to test against everything
+               clip.boxmins[0] = clip.boxmins[1] = clip.boxmins[2] = -999999999;
+               clip.boxmaxs[0] = clip.boxmaxs[1] = clip.boxmaxs[2] =  999999999;
+       }
 
-       SV_ClipToAreaGrid(&clip);
+       // clip to enttiies
+       sv_areagrid_stats_calls++;
+       sv_areagrid_marknumber++;
+       igridmins[0] = (int) ((clip.boxmins[0] + sv_areagrid_bias[0]) * sv_areagrid_scale[0]);
+       igridmins[1] = (int) ((clip.boxmins[1] + sv_areagrid_bias[1]) * sv_areagrid_scale[1]);
+       //igridmins[2] = (int) ((clip->boxmins[2] + sv_areagrid_bias[2]) * sv_areagrid_scale[2]);
+       igridmaxs[0] = (int) ((clip.boxmaxs[0] + sv_areagrid_bias[0]) * sv_areagrid_scale[0]) + 1;
+       igridmaxs[1] = (int) ((clip.boxmaxs[1] + sv_areagrid_bias[1]) * sv_areagrid_scale[1]) + 1;
+       //igridmaxs[2] = (int) ((clip->boxmaxs[2] + sv_areagrid_bias[2]) * sv_areagrid_scale[2]) + 1;
+       igridmins[0] = max(0, igridmins[0]);
+       igridmins[1] = max(0, igridmins[1]);
+       //igridmins[2] = max(0, igridmins[2]);
+       igridmaxs[0] = min(AREA_GRID, igridmaxs[0]);
+       igridmaxs[1] = min(AREA_GRID, igridmaxs[1]);
+       //igridmaxs[2] = min(AREA_GRID, igridmaxs[2]);
+
+       if (sv_areagrid_outside.solid_edicts.next != &sv_areagrid_outside.solid_edicts)
+               SV_ClipToNode(&clip, &sv_areagrid_outside.solid_edicts);
+
+       for (igrid[1] = igridmins[1];igrid[1] < igridmaxs[1];igrid[1]++)
+               for (grid = sv_areagrid + igrid[1] * AREA_GRID + igridmins[0], igrid[0] = igridmins[0];igrid[0] < igridmaxs[0];igrid[0]++, grid++)
+                       if (grid->solid_edicts.next != &grid->solid_edicts)
+                               SV_ClipToNode(&clip, &grid->solid_edicts);
 
        return clip.trace;
 }
 
 int SV_PointContents(const vec3_t point)
 {
+#if 1
+       return SV_Move(point, vec3_origin, vec3_origin, point, MOVE_NOMONSTERS, NULL).endcontents;
+#else
        if (sv.worldmodel && sv.worldmodel->brush.PointContents)
                return sv.worldmodel->brush.PointContents(sv.worldmodel, point);
        return CONTENTS_SOLID;
+#endif
 }
 
diff --git a/world.h b/world.h
index 10419be..f41cd2e 100644 (file)
--- a/world.h
+++ b/world.h
@@ -54,7 +54,7 @@ int SV_TestEntityPosition (edict_t *ent);
 // shouldn't be considered solid objects
 
 // passedict is explicitly excluded from clipping checks (normally NULL)
-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(const vec3_t start, const vec3_t mins, const vec3_t maxs, const vec3_t end, int type, edict_t *passedict);
 
 int SV_PointContents(const vec3_t point);