X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;ds=sidebyside;f=collision.c;h=2c4cec651844ad87d23684490f826dc951ee9d38;hb=d2dbc6a1b76a558cd29f153c6a8b2a0640ed2b66;hp=0797f26c574618212cb1aed819f8bd5dcfaabfd1;hpb=221857c07ba261e8a9253a88f4c70f15ab5bbc42;p=xonotic%2Fdarkplaces.git diff --git a/collision.c b/collision.c index 0797f26c..2c4cec65 100644 --- a/collision.c +++ b/collision.c @@ -10,14 +10,9 @@ #define COLLISION_PLANE_DIST_EPSILON (2.0f / COLLISION_SNAPSCALE) cvar_t collision_impactnudge = {0, "collision_impactnudge", "0.03125", "how much to back off from the impact"}; -cvar_t collision_startnudge = {0, "collision_startnudge", "0", "how much to bias collision trace start"}; -cvar_t collision_endnudge = {0, "collision_endnudge", "0", "how much to bias collision trace end"}; -cvar_t collision_enternudge = {0, "collision_enternudge", "0", "how much to bias collision entry fraction"}; -cvar_t collision_leavenudge = {0, "collision_leavenudge", "0", "how much to bias collision exit fraction"}; -cvar_t collision_prefernudgedfraction = {0, "collision_prefernudgedfraction", "1", "whether to sort collision events by nudged fraction (1) or real fraction (0)"}; -cvar_t collision_extendmovelength = {0, "collision_extendmovelength", "16", "internal bias on trace length to ensure detection of collisions within the collision_impactnudge/collision_enternudge/collision_leavenudge distance so that short moves do not degrade across frames (this does not alter the final trace length)"}; -cvar_t collision_extendtraceboxlength = {0, "collision_extendtraceboxlength", "1", "internal bias for tracebox() qc builtin to account for collision_impactnudge/collision_enternudge/collision_leavenudge (this does not alter the final trace length)"}; -cvar_t collision_extendtracelinelength = {0, "collision_extendtracelinelength", "1", "internal bias for traceline() qc builtin to account for collision_impactnudge/collision_enternudge/collision_leavenudge (this does not alter the final trace length)"}; +cvar_t collision_extendmovelength = {0, "collision_extendmovelength", "16", "internal bias on trace length to ensure detection of collisions within the collision_impactnudge distance so that short moves do not degrade across frames (this does not alter the final trace length)"}; +cvar_t collision_extendtraceboxlength = {0, "collision_extendtraceboxlength", "1", "internal bias for tracebox() qc builtin to account for collision_impactnudge (this does not alter the final trace length)"}; +cvar_t collision_extendtracelinelength = {0, "collision_extendtracelinelength", "1", "internal bias for traceline() qc builtin to account for collision_impactnudge (this does not alter the final trace length)"}; cvar_t collision_debug_tracelineasbox = {0, "collision_debug_tracelineasbox", "0", "workaround for any bugs in Collision_TraceLineBrushFloat by using Collision_TraceBrushBrushFloat"}; cvar_t collision_cache = {0, "collision_cache", "1", "store results of collision traces for next frame to reuse if possible (optimization)"}; //cvar_t collision_triangle_neighborsides = {0, "collision_triangle_neighborsides", "1", "override automatic side generation if triangle has neighbors with face planes that form a convex edge (perfect solution, but can not work for all edges)"}; @@ -29,11 +24,6 @@ mempool_t *collision_mempool; void Collision_Init (void) { Cvar_RegisterVariable(&collision_impactnudge); - Cvar_RegisterVariable(&collision_startnudge); - Cvar_RegisterVariable(&collision_endnudge); - Cvar_RegisterVariable(&collision_enternudge); - Cvar_RegisterVariable(&collision_leavenudge); - Cvar_RegisterVariable(&collision_prefernudgedfraction); Cvar_RegisterVariable(&collision_extendmovelength); Cvar_RegisterVariable(&collision_extendtracelinelength); Cvar_RegisterVariable(&collision_extendtraceboxlength); @@ -654,12 +644,12 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_sta } startplane[3] = furthestplanedist_float(startplane, other_start->points, othernumpoints); endplane[3] = furthestplanedist_float(startplane, other_end->points, othernumpoints); - startdist = nearestplanedist_float(startplane, trace_start->points, tracenumpoints) - startplane[3] - collision_startnudge.value; - enddist = nearestplanedist_float(endplane, trace_end->points, tracenumpoints) - endplane[3] - collision_endnudge.value; + startdist = nearestplanedist_float(startplane, trace_start->points, tracenumpoints) - startplane[3]; + enddist = nearestplanedist_float(endplane, trace_end->points, tracenumpoints) - endplane[3]; //Con_Printf("%c%i: startdist = %f, enddist = %f, startdist / (startdist - enddist) = %f\n", nplane2 != nplane ? 'b' : 'a', nplane2, startdist, enddist, startdist / (startdist - enddist)); // aside from collisions, this is also used for error correction - if (startdist <= collision_impactnudge.value && nplane < numplanes1 && (startdepth < startdist || startdepth == 1)) + if (startdist <= 0.0f && nplane < numplanes1 && (startdepth < startdist || startdepth == 1)) { startdepth = startdist; VectorCopy(startplane, startdepthnormal); @@ -668,15 +658,13 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_sta if (startdist > enddist) { // moving into brush - if (enddist >= collision_enternudge.value) + if (enddist > 0.0f) return; if (startdist >= 0) { // enter imove = 1 / (startdist - enddist); - f = (startdist - collision_enternudge.value) * imove; - if (f < 0) - f = 0; + f = startdist * imove; // check if this will reduce the collision time range if (enterfrac < f) { @@ -685,14 +673,14 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_sta // if the collision time range is now empty, no collision if (enterfrac > leavefrac) return; + // calculate the nudged fraction and impact normal we'll + // need if we accept this collision later + enterfrac2 = (startdist - collision_impactnudge.value) * imove; // if the collision would be further away than the trace's // existing collision data, we don't care about this // collision - if (enterfrac > trace->realfraction) + if (enterfrac2 >= trace->fraction) return; - // calculate the nudged fraction and impact normal we'll - // need if we accept this collision later - enterfrac2 = (startdist - collision_impactnudge.value) * imove; ie = 1.0f - enterfrac; newimpactplane[0] = startplane[0] * ie + endplane[0] * enterfrac; newimpactplane[1] = startplane[1] * ie + endplane[1] * enterfrac; @@ -728,9 +716,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_sta if (enddist > 0) { // leave - f = (startdist + collision_leavenudge.value) / (startdist - enddist); - if (f > 1) - f = 1; + f = startdist / (startdist - enddist); // check if this will reduce the collision time range if (leavefrac > f) { @@ -757,10 +743,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *trace_sta trace->hitsupercontents = other_start->supercontents; trace->hitq3surfaceflags = hitq3surfaceflags; trace->hittexture = hittexture; - trace->realfraction = bound(0, enterfrac, 1); trace->fraction = bound(0, enterfrac2, 1); - if (collision_prefernudgedfraction.integer) - trace->realfraction = trace->fraction; VectorCopy(newimpactplane, trace->plane.normal); trace->plane.dist = newimpactplane[3]; } @@ -826,12 +809,12 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const startplane[3] = other_start->planes[nplane].dist; VectorCopy(other_end->planes[nplane].normal, endplane); endplane[3] = other_end->planes[nplane].dist; - startdist = DotProduct(linestart, startplane) - startplane[3] - collision_startnudge.value; - enddist = DotProduct(lineend, endplane) - endplane[3] - collision_endnudge.value; + startdist = DotProduct(linestart, startplane) - startplane[3]; + enddist = DotProduct(lineend, endplane) - endplane[3]; //Con_Printf("%c%i: startdist = %f, enddist = %f, startdist / (startdist - enddist) = %f\n", nplane2 != nplane ? 'b' : 'a', nplane2, startdist, enddist, startdist / (startdist - enddist)); // aside from collisions, this is also used for error correction - if (startdist < collision_impactnudge.value && (startdepth < startdist || startdepth == 1)) + if (startdist <= 0.0f && (startdepth < startdist || startdepth == 1)) { startdepth = startdist; VectorCopy(startplane, startdepthnormal); @@ -840,15 +823,13 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const if (startdist > enddist) { // moving into brush - if (enddist >= collision_enternudge.value) + if (enddist > 0.0f) return; if (startdist > 0) { // enter imove = 1 / (startdist - enddist); - f = (startdist - collision_enternudge.value) * imove; - if (f < 0) - f = 0; + f = startdist * imove; // check if this will reduce the collision time range if (enterfrac < f) { @@ -857,14 +838,14 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const // if the collision time range is now empty, no collision if (enterfrac > leavefrac) return; + // calculate the nudged fraction and impact normal we'll + // need if we accept this collision later + enterfrac2 = (startdist - collision_impactnudge.value) * imove; // if the collision would be further away than the trace's // existing collision data, we don't care about this // collision - if (enterfrac > trace->realfraction) + if (enterfrac2 >= trace->fraction) return; - // calculate the nudged fraction and impact normal we'll - // need if we accept this collision later - enterfrac2 = (startdist - collision_impactnudge.value) * imove; ie = 1.0f - enterfrac; newimpactplane[0] = startplane[0] * ie + endplane[0] * enterfrac; newimpactplane[1] = startplane[1] * ie + endplane[1] * enterfrac; @@ -883,9 +864,7 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const if (enddist > 0) { // leave - f = (startdist + collision_leavenudge.value) / (startdist - enddist); - if (f > 1) - f = 1; + f = startdist / (startdist - enddist); // check if this will reduce the collision time range if (leavefrac > f) { @@ -912,10 +891,7 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const trace->hitsupercontents = other_start->supercontents; trace->hitq3surfaceflags = hitq3surfaceflags; trace->hittexture = hittexture; - trace->realfraction = bound(0, enterfrac, 1); trace->fraction = bound(0, enterfrac2, 1); - if (collision_prefernudgedfraction.integer) - trace->realfraction = trace->fraction; VectorCopy(newimpactplane, trace->plane.normal); trace->plane.dist = newimpactplane[3]; } @@ -1234,9 +1210,7 @@ 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, int supercontents, int q3surfaceflags, const texture_t *texture) { -#if 1 - // more optimized - float d1, d2, d, f, impact[3], edgenormal[3], faceplanenormal[3], faceplanedist, faceplanenormallength2, edge01[3], edge21[3], edge02[3]; + float d1, d2, d, f, f2, impact[3], edgenormal[3], faceplanenormal[3], faceplanedist, faceplanenormallength2, edge01[3], edge21[3], edge02[3]; // this function executes: // 32 ops when line starts behind triangle @@ -1293,11 +1267,12 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co // 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 + // 4 ops f = (d1 - faceplanedist) * d; + f2 = f - collision_impactnudge.value * d; // skip out if this impact is further away than previous ones // 1 ops - if (f > trace->realfraction) + if (f2 >= trace->fraction) return; // calculate the perfect impact point for classification of insidedness // 9 ops @@ -1332,14 +1307,7 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co // 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; - - if (collision_prefernudgedfraction.integer) - trace->realfraction = trace->fraction; + trace->fraction = f2; // store the new trace plane (because collisions only happen from // the front this is always simply the triangle normal, never flipped) @@ -1350,103 +1318,6 @@ void Collision_TraceLineTriangleFloat(trace_t *trace, const vec3_t linestart, co trace->hitsupercontents = supercontents; trace->hitq3surfaceflags = q3surfaceflags; trace->hittexture = texture; -#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) - return; - - // calculate the unnormalized end distance - d2 = DotProduct(faceplanenormal, lineend) - faceplanedist; - // if both are in front, there is no collision - if (d2 >= 0) - 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) - 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 - f = d1 * d; - // skip out if this impact is further away than previous ones - if (f > trace->realfraction) - return; - // calculate the perfect impact point for classification of insidedness - 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) - - VectorSubtract(point2, point0, edge); - CrossProduct(edge, faceplanenormal, edgenormal); - if (DotProduct(impact, edgenormal) > DotProduct(point0, edgenormal)) - return; - - VectorSubtract(point0, point1, edge); - CrossProduct(edge, faceplanenormal, edgenormal); - if (DotProduct(impact, edgenormal) > DotProduct(point1, edgenormal)) - return; - - VectorSubtract(point1, point2, edge); - CrossProduct(edge, faceplanenormal, edgenormal); - if (DotProduct(impact, edgenormal) > DotProduct(point2, edgenormal)) - return; - - // 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) / (d1 - d2); - trace->fraction = bound(0, fnudged, 1); - - // store the new trace endpos - // not needed, it's calculated later when the trace is finished - //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]); - trace->hitsupercontents = supercontents; - trace->hitq3surfaceflags = q3surfaceflags; - trace->hittexture = texture; -#endif } void Collision_BoundingBoxOfBrushTraceSegment(const colbrushf_t *start, const colbrushf_t *end, vec3_t mins, vec3_t maxs, float startfrac, float endfrac) @@ -1814,7 +1685,7 @@ extendtraceinfo_t; static void Collision_ClipExtendPrepare(extendtraceinfo_t *extendtraceinfo, trace_t *trace, const vec3_t tstart, const vec3_t tend, float textend) { memset(trace, 0, sizeof(*trace)); - trace->fraction = trace->realfraction = 1; + trace->fraction = 1; extendtraceinfo->trace = trace; VectorCopy(tstart, extendtraceinfo->realstart); @@ -1846,7 +1717,6 @@ static void Collision_ClipExtendFinish(extendtraceinfo_t *extendtraceinfo) { // undo the extended trace length trace->fraction *= extendtraceinfo->scaletoextend; - trace->realfraction *= extendtraceinfo->scaletoextend; // if the extended trace hit something that the unextended trace did not hit (even considering the collision_impactnudge), then we have to clear the hit information if (trace->fraction > 1.0f) @@ -1863,7 +1733,6 @@ static void Collision_ClipExtendFinish(extendtraceinfo_t *extendtraceinfo) // clamp things trace->fraction = bound(0, trace->fraction, 1); - trace->realfraction = bound(0, trace->realfraction, 1); // calculate the end position VectorMA(extendtraceinfo->realstart, trace->fraction, extendtraceinfo->realdelta, trace->endpos); @@ -1965,7 +1834,7 @@ void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, const { float starttransformed[3]; memset(trace, 0, sizeof(*trace)); - trace->fraction = trace->realfraction = 1; + trace->fraction = 1; Matrix4x4_Transform(inversematrix, start, starttransformed); #if COLLISIONPARANOID >= 3 @@ -1986,7 +1855,7 @@ void Collision_ClipPointToGenericEntity(trace_t *trace, dp_model_t *model, const void Collision_ClipPointToWorld(trace_t *trace, dp_model_t *model, const vec3_t start, int hitsupercontents) { memset(trace, 0, sizeof(*trace)); - trace->fraction = trace->realfraction = 1; + trace->fraction = 1; if (model && model->TracePoint) model->TracePoint(model, NULL, NULL, trace, start, hitsupercontents); VectorCopy(start, trace->endpos); @@ -2002,7 +1871,7 @@ void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *tou if (isbmodel) cliptrace->bmodelstartsolid = true; cliptrace->startsolid = true; - if (cliptrace->realfraction == 1) + if (cliptrace->fraction == 1) cliptrace->ent = touch; if (cliptrace->startdepth > trace->startdepth) { @@ -2017,10 +1886,9 @@ void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *tou // cliptrace->inopen = true; if (trace->inwater) cliptrace->inwater = true; - if ((trace->realfraction < cliptrace->realfraction) && (VectorLength2(trace->plane.normal) > 0)) + if ((trace->fraction < cliptrace->fraction) && (VectorLength2(trace->plane.normal) > 0)) { cliptrace->fraction = trace->fraction; - cliptrace->realfraction = trace->realfraction; VectorCopy(trace->endpos, cliptrace->endpos); cliptrace->plane = trace->plane; cliptrace->ent = touch; @@ -2030,22 +1898,3 @@ void Collision_CombineTraces(trace_t *cliptrace, const trace_t *trace, void *tou } cliptrace->startsupercontents |= trace->startsupercontents; } - -void Collision_ShortenTrace(trace_t *trace, float shorten_factor, const vec3_t end) -{ - // now undo our moving end 1 qu farther... - trace->fraction = bound(trace->fraction, trace->fraction / shorten_factor - 1e-6, 1); // we subtract 1e-6 to guard for roundoff errors - trace->realfraction = bound(trace->realfraction, trace->realfraction / shorten_factor - 1e-6, 1); // we subtract 1e-6 to guard for roundoff errors - if(trace->fraction >= 1) // trace would NOT hit if not expanded! - { - trace->fraction = 1; - trace->realfraction = 1; - VectorCopy(end, trace->endpos); - memset(&trace->plane, 0, sizeof(trace->plane)); - trace->ent = NULL; - trace->hitsupercontentsmask = 0; - trace->hitsupercontents = 0; - trace->hitq3surfaceflags = 0; - trace->hittexture = NULL; - } -}