]> de.git.xonotic.org Git - xonotic/darkplaces.git/blobdiff - collision.c
implemented PointSuperContents model function as a lower-overhead
[xonotic/darkplaces.git] / collision.c
index 0ccc1d1f992f5511ab108501665625ceae58491b..fbe340f088c5f883dcf7a4cec593fd9490d10ca6 100644 (file)
@@ -614,13 +614,15 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush
                if (d1 > d2)
                {
                        // moving into brush
-                       if (d2 > 0)
+                       if (d2 >= collision_enternudge.value)
                                return;
                        if (d1 > 0)
                        {
                                // enter
                                imove = 1 / (d1 - d2);
                                f = (d1 - collision_enternudge.value) * imove;
+                               if (f < 0)
+                                       f = 0;
                                // check if this will reduce the collision time range
                                if (enterfrac < f)
                                {
@@ -636,7 +638,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush
                                                return;
                                        // calculate the nudged fraction and impact normal we'll
                                        // need if we accept this collision later
-                                       enterfrac2 = f - collision_impactnudge.value * imove;
+                                       enterfrac2 = (d1 - collision_impactnudge.value) * imove;
                                        VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal);
                                        hitq3surfaceflags = startplane->q3surfaceflags;
                                        hittexture = startplane->texture;
@@ -652,6 +654,8 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush
                        {
                                // leave
                                f = (d1 + collision_leavenudge.value) / (d1 - d2);
+                               if (f > 1)
+                                       f = 1;
                                // check if this will reduce the collision time range
                                if (leavefrac > f)
                                {
@@ -733,13 +737,15 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const
                if (d1 > d2)
                {
                        // moving into brush
-                       if (d2 > 0)
+                       if (d2 >= collision_enternudge.value)
                                return;
                        if (d1 > 0)
                        {
                                // enter
                                imove = 1 / (d1 - d2);
                                f = (d1 - collision_enternudge.value) * imove;
+                               if (f < 0)
+                                       f = 0;
                                // check if this will reduce the collision time range
                                if (enterfrac < f)
                                {
@@ -755,7 +761,7 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const
                                                return;
                                        // calculate the nudged fraction and impact normal we'll
                                        // need if we accept this collision later
-                                       enterfrac2 = f - collision_impactnudge.value * imove;
+                                       enterfrac2 = (d1 - collision_impactnudge.value) * imove;
                                        VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal);
                                        hitq3surfaceflags = startplane->q3surfaceflags;
                                        hittexture = startplane->texture;
@@ -817,14 +823,23 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const
        }
 }
 
-void Collision_TracePointBrushFloat(trace_t *trace, const vec3_t point, const colbrushf_t *thatbrush)
+qboolean Collision_PointInsideBrushFloat(const vec3_t point, const colbrushf_t *brush)
 {
        int nplane;
        const colplanef_t *plane;
 
-       for (nplane = 0, plane = thatbrush->planes;nplane < thatbrush->numplanes;nplane++, plane++)
+       if (!BoxesOverlap(point, point, brush->mins, brush->maxs))
+               return false;
+       for (nplane = 0, plane = brush->planes;nplane < brush->numplanes;nplane++, plane++)
                if (DotProduct(plane->normal, point) > plane->dist)
-                       return;
+                       return false;
+       return true;
+}
+
+void Collision_TracePointBrushFloat(trace_t *trace, const vec3_t point, const colbrushf_t *thatbrush)
+{
+       if (!Collision_PointInsideBrushFloat(point, thatbrush))
+               return;
 
        trace->startsupercontents |= thatbrush->supercontents;
        if (trace->hitsupercontentsmask & thatbrush->supercontents)
@@ -883,12 +898,7 @@ void Collision_TraceBrushTriangleMeshFloat(trace_t *trace, const colbrushf_t *th
        }
        for (i = 0;i < numtriangles;i++, element3i += 3)
        {
-               if (segmentmaxs[0] >= min(vertex3f[element3i[0]*3+0], min(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
-                && segmentmins[0] <= max(vertex3f[element3i[0]*3+0], max(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
-                && segmentmaxs[1] >= min(vertex3f[element3i[0]*3+1], min(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
-                && segmentmins[1] <= max(vertex3f[element3i[0]*3+1], max(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
-                && segmentmaxs[2] >= min(vertex3f[element3i[0]*3+2], min(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2]))
-                && segmentmins[2] <= max(vertex3f[element3i[0]*3+2], max(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2])))
+               if (TriangleOverlapsBox(vertex3f + element3i[0]*3, vertex3f + element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
                {
                        VectorCopy(vertex3f + element3i[0] * 3, polyf_points[0].v);
                        VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v);
@@ -941,12 +951,7 @@ void Collision_TraceLineTriangleMeshFloat(trace_t *trace, const vec3_t linestart
        }
        for (i = 0;i < numtriangles;i++, element3i += 3)
        {
-               if (segmentmaxs[0] >= min(vertex3f[element3i[0]*3+0], min(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
-                && segmentmins[0] <= max(vertex3f[element3i[0]*3+0], max(vertex3f[element3i[1]*3+0], vertex3f[element3i[2]*3+0]))
-                && segmentmaxs[1] >= min(vertex3f[element3i[0]*3+1], min(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
-                && segmentmins[1] <= max(vertex3f[element3i[0]*3+1], max(vertex3f[element3i[1]*3+1], vertex3f[element3i[2]*3+1]))
-                && segmentmaxs[2] >= min(vertex3f[element3i[0]*3+2], min(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2]))
-                && segmentmins[2] <= max(vertex3f[element3i[0]*3+2], max(vertex3f[element3i[1]*3+2], vertex3f[element3i[2]*3+2])))
+               if (TriangleOverlapsBox(vertex3f + element3i[0]*3, vertex3 + [element3i[1]*3, vertex3f + element3i[2]*3, segmentmins, segmentmaxs))
                {
                        VectorCopy(vertex3f + element3i[0] * 3, polyf_points[0].v);
                        VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v);
@@ -1006,7 +1011,9 @@ void Collision_TraceBrushPolygonTransformFloat(trace_t *trace, const colbrushf_t
 
 
 #define MAX_BRUSHFORBOX 16
-static int brushforbox_index = 0;
+static unsigned int brushforbox_index = 0;
+// note: this relies on integer overflow to be consistent with modulo
+// MAX_BRUSHFORBOX, or in other words, MAX_BRUSHFORBOX must be a power of two!
 static colpointf_t brushforbox_point[MAX_BRUSHFORBOX*8];
 static colplanef_t brushforbox_plane[MAX_BRUSHFORBOX*6];
 static colbrushf_t brushforbox_brush[MAX_BRUSHFORBOX];
@@ -1149,7 +1156,7 @@ float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double
        if (deviationdist > sphereradius*sphereradius)
                return 1; // miss (off to the side)
        // nudge back to find the correct impact distance
-       impactdist += deviationdist - sphereradius;
+       impactdist -= sphereradius - deviationdist/sphereradius;
        if (impactdist >= linelength)
                return 1; // miss (not close enough)
        if (impactdist < 0)