X-Git-Url: http://git.xonotic.org/?a=blobdiff_plain;f=collision.c;h=30f4d7662acdae19488a51c9d22811a30c4c901f;hb=8269574f33908230c65305a5683d5362cb3ffbf2;hp=2306aded1529a7164634408b482c09a9888776e0;hpb=5fe25e4d5947e5f1c6f5a5d802bd26c7232c6aa8;p=xonotic%2Fdarkplaces.git diff --git a/collision.c b/collision.c index 2306aded..30f4d766 100644 --- a/collision.c +++ b/collision.c @@ -2,7 +2,7 @@ #include "quakedef.h" #include "polygon.h" -#define COLLISION_SNAPSCALE (32.0f) +#define COLLISION_SNAPSCALE (8.0f) #define COLLISION_SNAP (1.0f / COLLISION_SNAPSCALE) cvar_t collision_impactnudge = {0, "collision_impactnudge", "0.03125"}; @@ -11,287 +11,6 @@ cvar_t collision_endnudge = {0, "collision_endnudge", "0"}; cvar_t collision_enternudge = {0, "collision_enternudge", "0"}; cvar_t collision_leavenudge = {0, "collision_leavenudge", "0"}; -#if 0 -typedef struct -{ - // the hull we're tracing through - const hull_t *hull; - - // the trace structure to fill in - trace_t *trace; - - // start and end of the trace (in model space) - double start[3]; - double end[3]; - - // end - start - double dist[3]; - - // overrides the CONTENTS_SOLID in the box bsp tree - int boxsupercontents; -} -RecursiveHullCheckTraceInfo_t; - -#define HULLCHECKSTATE_EMPTY 0 -#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]) -{ - // 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) - { - num = Mod_Q1BSP_SuperContentsFromNativeContents(NULL, num); - if (!t->trace->startfound) - { - t->trace->startfound = true; - t->trace->startsupercontents |= num; - } - if (num & SUPERCONTENTS_LIQUIDSMASK) - t->trace->inwater = true; - if (num == 0) - t->trace->inopen = true; - if (num & t->trace->hitsupercontentsmask) - { - // if the first leaf is solid, set startsolid - if (t->trace->allsolid) - t->trace->startsolid = true; -#if COLLISIONPARANOID >= 3 - Con_Print("S"); -#endif - return HULLCHECKSTATE_SOLID; - } - else - { - t->trace->allsolid = false; -#if COLLISIONPARANOID >= 3 - Con_Print("E"); -#endif - 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) - { -#if COLLISIONPARANOID >= 3 - Con_Print("<"); -#endif - num = node->children[1]; - goto loc0; - } - side = 1; - } - else - { - if (t2 >= 0) - { -#if COLLISIONPARANOID >= 3 - Con_Print(">"); -#endif - num = node->children[0]; - goto loc0; - } - side = 0; - } - - // the line intersects, find intersection point - // LordHavoc: this uses the original trace for maximum accuracy -#if COLLISIONPARANOID >= 3 - Con_Print("M"); -#endif - 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 = 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 = 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); - } - - // calculate the true fraction - t1 = DotProduct(t->trace->plane.normal, t->start) - t->trace->plane.dist - collision_startnudge.value; - t2 = DotProduct(t->trace->plane.normal, t->end) - t->trace->plane.dist - collision_endnudge.value; - midf = t1 / (t1 - t2); - t->trace->realfraction = bound(0, midf, 1); - - // calculate the return fraction which is nudged off the surface a bit - midf = (t1 - collision_impactnudge.value) / (t1 - t2); - t->trace->fraction = bound(0, midf, 1); - -#if COLLISIONPARANOID >= 3 - Con_Print("D"); -#endif - return HULLCHECKSTATE_DONE; -} - -#if 0 -// used if start and end are the same -static void RecursiveHullCheckPoint (RecursiveHullCheckTraceInfo_t *t, int num) -{ - // If you can read this, you understand BSP trees - while (num >= 0) - num = t->hull->clipnodes[num].children[((t->hull->planes[t->hull->clipnodes[num].planenum].type < 3) ? (t->start[t->hull->planes[t->hull->clipnodes[num].planenum].type]) : (DotProduct(t->hull->planes[t->hull->clipnodes[num].planenum].normal, t->start))) < t->hull->planes[t->hull->clipnodes[num].planenum].dist]; - - // check for empty - 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; - } - } - 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; - } - } -} -#endif - -static hull_t box_hull; -static dclipnode_t box_clipnodes[6]; -static mplane_t box_planes[6]; - -void Mod_Q1BSP_Collision_Init (void) -{ - int i; - int side; - - //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. - - box_hull.clipnodes = box_clipnodes; - box_hull.planes = box_planes; - box_hull.firstclipnode = 0; - box_hull.lastclipnode = 5; - - for (i = 0;i < 6;i++) - { - box_clipnodes[i].planenum = i; - - side = i&1; - - box_clipnodes[i].children[side] = CONTENTS_EMPTY; - if (i != 5) - box_clipnodes[i].children[side^1] = i + 1; - else - box_clipnodes[i].children[side^1] = CONTENTS_SOLID; - - box_planes[i].type = i>>1; - box_planes[i].normal[i>>1] = 1; - } -} - -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, int hitsupercontentsmask, int boxsupercontents) -{ - RecursiveHullCheckTraceInfo_t rhc; - // fill in a default trace - 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.boxsupercontents = boxsupercontents; - rhc.hull = &box_hull; - rhc.trace = trace; - rhc.trace->hitsupercontentsmask = hitsupercontentsmask; - rhc.trace->fraction = 1; - rhc.trace->realfraction = 1; - rhc.trace->allsolid = true; - VectorCopy(start, rhc.start); - VectorCopy(end, rhc.end); - VectorSubtract(rhc.end, rhc.start, rhc.dist); - Mod_Q1BSP_RecursiveHullCheck(&rhc, rhc.hull->firstclipnode, 0, 1, rhc.start, rhc.end); - VectorMA(rhc.start, rhc.trace->fraction, rhc.dist, rhc.trace->endpos); - if (rhc.trace->startsupercontents) - rhc.trace->startsupercontents = boxsupercontents; -} -#endif - void Collision_Init (void) { Cvar_RegisterVariable(&collision_impactnudge); @@ -449,7 +168,7 @@ colbrushf_t *Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalpla // check if there are too many and skip the brush if (numplanesbuf >= maxplanesbuf) { - Con_Print("Mod_Q3BSP_LoadBrushes: failed to build collision brush: too many planes for buffer\n"); + Con_Print("Collision_NewBrushFromPlanes: failed to build collision brush: too many planes for buffer\n"); return NULL; } @@ -620,6 +339,7 @@ void Collision_CalcPlanesForPolygonBrushFloat(colbrushf_t *brush) float edge0[3], edge1[3], edge2[3], normal[3], dist, bestdist; colpointf_t *p, *p2; + // FIXME: these probably don't actually need to be normalized if the collision code does not care if (brush->numpoints == 3) { // optimized triangle case @@ -791,7 +511,7 @@ colbrushf_t *Collision_AllocBrushFromPermanentPolygonFloat(mempool_t *mempool, i brush->numplanes = numpoints + 2; brush->planes = (void *)(brush + 1); brush->points = (colpointf_t *)points; - Host_Error("Collision_AllocBrushFromPermanentPolygonFloat: FIXME: this code needs to be updated to generate a mesh...\n"); + Sys_Error("Collision_AllocBrushFromPermanentPolygonFloat: FIXME: this code needs to be updated to generate a mesh...\n"); return brush; } @@ -799,7 +519,7 @@ colbrushf_t *Collision_AllocBrushFromPermanentPolygonFloat(mempool_t *mempool, i void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush_start, const colbrushf_t *thisbrush_end, const colbrushf_t *thatbrush_start, const colbrushf_t *thatbrush_end) { int nplane, nplane2, fstartsolid, fendsolid, brushsolid; - float enterfrac, leavefrac, d1, d2, f, move, imove, newimpactnormal[3], enterfrac2; + float enterfrac, leavefrac, d1, d2, f, imove, newimpactnormal[3], enterfrac2; const colplanef_t *startplane, *endplane; enterfrac = -1; @@ -825,7 +545,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush return; } f = furthestplanedist_float(startplane->normal, thisbrush_start->points, thisbrush_start->numpoints); - if (fabs(f - startplane->dist) > 0.01f) + if (fabs(f - startplane->dist) > 0.125f) Con_Printf("startplane->dist %f != calculated %f (thisbrush_start)\n", startplane->dist, f); } d1 = nearestplanedist_float(startplane->normal, thisbrush_start->points, thisbrush_start->numpoints) - furthestplanedist_float(startplane->normal, thatbrush_start->points, thatbrush_start->numpoints) - collision_startnudge.value; @@ -844,7 +564,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush return; } f = furthestplanedist_float(startplane->normal, thatbrush_start->points, thatbrush_start->numpoints); - if (fabs(f - startplane->dist) > 0.01f) + if (fabs(f - startplane->dist) > 0.125f) Con_Printf("startplane->dist %f != calculated %f (thatbrush_start)\n", startplane->dist, f); } d1 = nearestplanedist_float(startplane->normal, thisbrush_start->points, thisbrush_start->numpoints) - startplane->dist - collision_startnudge.value; @@ -852,46 +572,38 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush } //Con_Printf("%c%i: d1 = %f, d2 = %f, d1 / (d1 - d2) = %f\n", nplane2 != nplane ? 'b' : 'a', nplane2, d1, d2, d1 / (d1 - d2)); - move = d1 - d2; - if (move > 0) + if(d1 > d2) { // moving into brush - if (d2 > collision_enternudge.value) + if(d2 > 0) return; - if (d1 < 0) - continue; - // enter - fstartsolid = false; - imove = 1 / move; - f = (d1 - collision_enternudge.value) * imove; - f = bound(0, f, 1); - if (enterfrac < f) + if(d1 > 0) { - enterfrac = f; - enterfrac2 = f - collision_impactnudge.value * imove; - enterfrac2 = bound(0, enterfrac2, 1); - VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal); + // enter + fstartsolid = false; + imove = 1 / (d1 - d2); + f = (d1 - collision_enternudge.value) * imove; + if (enterfrac < f) + { + enterfrac = f; + enterfrac2 = f - collision_impactnudge.value * imove; + VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal); + } } } - else if (move < 0) - { - // moving out of brush - if (d1 > collision_leavenudge.value) - return; - if (d2 < 0) - continue; - // leave - fendsolid = false; - f = (d1 + collision_leavenudge.value) / move; - f = bound(0, f, 1); - if (leavefrac > f) - leavefrac = f; - } else { - // sliding along plane - if (d1 > 0) + // moving out of brush + if(d1 > 0) return; + if(d2 > 0) + { + // leave + fendsolid = false; + f = (d1 + collision_leavenudge.value) / (d1 - d2); + if (leavefrac > f) + leavefrac = f; + } } } @@ -947,7 +659,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const colbrushf_t *thatbrush_start, const colbrushf_t *thatbrush_end) { int nplane, fstartsolid, fendsolid, brushsolid; - float enterfrac, leavefrac, d1, d2, f, move, imove, newimpactnormal[3], enterfrac2; + float enterfrac, leavefrac, d1, d2, f, imove, newimpactnormal[3], enterfrac2; const colplanef_t *startplane, *endplane; enterfrac = -1; @@ -973,42 +685,43 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const if (thatbrush_start->numpoints) { f = furthestplanedist_float(startplane->normal, thatbrush_start->points, thatbrush_start->numpoints); - if (fabs(f - startplane->dist) > 0.01f) + if (fabs(f - startplane->dist) > 0.125f) Con_Printf("startplane->dist %f != calculated %f\n", startplane->dist, f); } } - move = d1 - d2; - if (move > 0) + if (d1 > d2) { // moving into brush - if (d2 >= 0) + if (d2 > 0) return; - if (d1 <= 0) - continue; - // enter - fstartsolid = false; - imove = 1 / move; - f = (d1 - collision_enternudge.value) * imove; - if (enterfrac < f) + if (d1 > 0) { - enterfrac = f; - enterfrac2 = f - collision_impactnudge.value * imove; - VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal); + // enter + fstartsolid = false; + imove = 1 / (d1 - d2); + f = (d1 - collision_enternudge.value) * imove; + if (enterfrac < f) + { + enterfrac = f; + enterfrac2 = f - collision_impactnudge.value * imove; + VectorLerp(startplane->normal, enterfrac, endplane->normal, newimpactnormal); + } } } else { // moving out of brush - if (d1 >= 0) + if (d1 > 0) return; - if (d2 <= 0) - continue; - // leave - fendsolid = false; - f = (d1 - collision_leavenudge.value) / move; - if (leavefrac > f) - leavefrac = f; + if (d2 > 0) + { + // leave + fendsolid = false; + f = (d1 + collision_leavenudge.value) / (d1 - d2); + if (leavefrac > f) + leavefrac = f; + } } } @@ -1267,6 +980,7 @@ colbrushf_t *Collision_BrushForBox(const matrix4x4_t *matrix, const vec3_t mins, colbrushf_t *brush; if (brushforbox_brush[0].numpoints == 0) Collision_InitBrushForBox(); + // FIXME: these probably don't actually need to be normalized if the collision code does not care if (VectorCompare(mins, maxs)) { // point brush @@ -1411,7 +1125,18 @@ float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, const vec3_t lineend, const float *point0, const float *point1, const float *point2) { - float d1, d2, d, f, fnudged, impact[3], edgenormal[3], faceplanenormal[3], faceplanedist, edge[3]; +#if 1 + // more optimized + float d1, d2, d, f, impact[3], edgenormal[3], faceplanenormal[3], faceplanedist, faceplanenormallength2, edge01[3], edge21[3], edge02[3]; + + // this function executes: + // 32 ops when line starts behind triangle + // 38 ops when line ends infront of triangle + // 43 ops when line fraction is already closer than this triangle + // 72 ops when line is outside edge 01 + // 92 ops when line is outside edge 21 + // 115 ops when line is outside edge 02 + // 123 ops when line impacts triangle and updates trace results // this code is designed for clockwise triangles, conversion to // counterclockwise would require swapping some things around... @@ -1419,23 +1144,122 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co // function when calling it than it is to rewire the internals. // calculate the faceplanenormal of the triangle, this represents the front side - TriangleNormal(point0, point1, point2, faceplanenormal); + // 15 ops + VectorSubtract(point0, point1, edge01); + VectorSubtract(point2, point1, edge21); + CrossProduct(edge01, edge21, faceplanenormal); // there's no point in processing a degenerate triangle (GIGO - Garbage In, Garbage Out) - if (DotProduct(faceplanenormal, faceplanenormal) < 0.0001f) + // 6 ops + faceplanenormallength2 = DotProduct(faceplanenormal, faceplanenormal); + if (faceplanenormallength2 < 0.0001f) return; - // normalize the normal - VectorNormalize(faceplanenormal); // calculate the distance + // 5 ops faceplanedist = DotProduct(point0, faceplanenormal); + // if start point is on the back side there is no collision + // (we don't care about traces going through the triangle the wrong way) + // calculate the start distance + // 6 ops + d1 = DotProduct(faceplanenormal, linestart); + if (d1 <= faceplanedist) + return; + + // calculate the end distance + // 6 ops + d2 = DotProduct(faceplanenormal, lineend); + // if both are in front, there is no collision + if (d2 >= faceplanedist) + return; + + // from here on we know d1 is >= 0 and d2 is < 0 + // this means the line starts infront and ends behind, passing through it + + // calculate the recipricol of the distance delta, + // so we can use it multiple times cheaply (instead of division) + // 2 ops + d = 1.0f / (d1 - d2); + // calculate the impact fraction by taking the start distance (> 0) + // and subtracting the face plane distance (this is the distance of the + // triangle along that same normal) + // then multiply by the recipricol distance delta + // 2 ops + f = (d1 - faceplanedist) * d; + // skip out if this impact is further away than previous ones + // 1 ops + if (f > trace->realfraction) + return; + // calculate the perfect impact point for classification of insidedness + // 9 ops + impact[0] = linestart[0] + f * (lineend[0] - linestart[0]); + impact[1] = linestart[1] + f * (lineend[1] - linestart[1]); + impact[2] = linestart[2] + f * (lineend[2] - linestart[2]); + + // calculate the edge normal and reject if impact is outside triangle + // (an edge normal faces away from the triangle, to get the desired normal + // a crossproduct with the faceplanenormal is used, and because of the way + // the insidedness comparison is written it does not need to be normalized) + + // first use the two edges from the triangle plane math + // the other edge only gets calculated if the point survives that long + + // 20 ops + CrossProduct(edge01, faceplanenormal, edgenormal); + if (DotProduct(impact, edgenormal) > DotProduct(point1, edgenormal)) + return; + + // 20 ops + CrossProduct(faceplanenormal, edge21, edgenormal); + if (DotProduct(impact, edgenormal) > DotProduct(point2, edgenormal)) + return; + + // 23 ops + VectorSubtract(point0, point2, edge02); + CrossProduct(faceplanenormal, edge02, edgenormal); + if (DotProduct(impact, edgenormal) > DotProduct(point0, edgenormal)) + return; + + // 8 ops (rare) + + // store the new trace fraction + trace->realfraction = f; + + // calculate a nudged fraction to keep it out of the surface + // (the main fraction remains perfect) + trace->fraction = f - collision_impactnudge.value * d; + + // store the new trace plane (because collisions only happen from + // the front this is always simply the triangle normal, never flipped) + d = 1.0 / sqrt(faceplanenormallength2); + VectorScale(faceplanenormal, d, trace->plane.normal); + trace->plane.dist = faceplanedist * d; +#else + float d1, d2, d, f, fnudged, impact[3], edgenormal[3], faceplanenormal[3], faceplanedist, edge[3]; + + // this code is designed for clockwise triangles, conversion to + // counterclockwise would require swapping some things around... + // it is easier to simply swap the point0 and point2 parameters to this + // function when calling it than it is to rewire the internals. + + // calculate the unnormalized faceplanenormal of the triangle, + // this represents the front side + TriangleNormal(point0, point1, point2, faceplanenormal); + // there's no point in processing a degenerate triangle + // (GIGO - Garbage In, Garbage Out) + if (DotProduct(faceplanenormal, faceplanenormal) < 0.0001f) + return; + // calculate the unnormalized distance + faceplanedist = DotProduct(point0, faceplanenormal); + + // calculate the unnormalized start distance d1 = DotProduct(faceplanenormal, linestart) - faceplanedist; // if start point is on the back side there is no collision // (we don't care about traces going through the triangle the wrong way) - if (d1 < 0) + if (d1 <= 0) return; - // calculate the end distance + // calculate the unnormalized end distance d2 = DotProduct(faceplanenormal, lineend) - faceplanedist; // if both are in front, there is no collision if (d2 >= 0) @@ -1464,7 +1288,7 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co // (an edge normal faces away from the triangle, to get the desired normal // a crossproduct with the faceplanenormal is used, and because of the way // the insidedness comparison is written it does not need to be normalized) - + VectorSubtract(point2, point0, edge); CrossProduct(edge, faceplanenormal, edgenormal); if (DotProduct(impact, edgenormal) > DotProduct(point0, edgenormal)) @@ -1483,9 +1307,19 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co // store the new trace fraction trace->realfraction = bound(0, f, 1); + // store the new trace plane (because collisions only happen from + // the front this is always simply the triangle normal, never flipped) + VectorNormalize(faceplanenormal); + VectorCopy(faceplanenormal, trace->plane.normal); + trace->plane.dist = DotProduct(point0, faceplanenormal); + + // calculate the normalized start and end distances + d1 = DotProduct(trace->plane.normal, linestart) - trace->plane.dist; + d2 = DotProduct(trace->plane.normal, lineend) - trace->plane.dist; + // calculate a nudged fraction to keep it out of the surface // (the main fraction remains perfect) - fnudged = (d1 - collision_impactnudge.value) * d; + fnudged = (d1 - collision_impactnudge.value) / (d1 - d2); trace->fraction = bound(0, fnudged, 1); // store the new trace endpos @@ -1493,11 +1327,7 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co //trace->endpos[0] = linestart[0] + fnudged * (lineend[0] - linestart[0]); //trace->endpos[1] = linestart[1] + fnudged * (lineend[1] - linestart[1]); //trace->endpos[2] = linestart[2] + fnudged * (lineend[2] - linestart[2]); - - // store the new trace plane (because collisions only happen from - // the front this is always simply the triangle normal, never flipped) - VectorCopy(faceplanenormal, trace->plane.normal); - trace->plane.dist = faceplanedist; +#endif } typedef struct colbspnode_s