X-Git-Url: https://de.git.xonotic.org/?a=blobdiff_plain;f=collision.c;h=e132341bd356ec9ac345ac4f572e31f4156dd502;hb=b8d63f8b1a4a6d8cc880be5ff8ea83aa6fbba365;hp=88a479513beb7777e2d2d5348b8377755d2f352d;hpb=341b16da302f73ad1a5698bd590e262930f90f14;p=xonotic%2Fdarkplaces.git diff --git a/collision.c b/collision.c index 88a47951..e132341b 100644 --- a/collision.c +++ b/collision.c @@ -5,11 +5,11 @@ #define COLLISION_SNAPSCALE (8.0f) #define COLLISION_SNAP (1.0f / COLLISION_SNAPSCALE) -cvar_t collision_impactnudge = {0, "collision_impactnudge", "0.03125"}; -cvar_t collision_startnudge = {0, "collision_startnudge", "0"}; -cvar_t collision_endnudge = {0, "collision_endnudge", "0"}; -cvar_t collision_enternudge = {0, "collision_enternudge", "0"}; -cvar_t collision_leavenudge = {0, "collision_leavenudge", "0"}; +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"}; void Collision_Init (void) { @@ -183,7 +183,7 @@ colbrushf_t *Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalpla { // we want to keep the inside of the brush plane so we flip // the cutting plane - PolygonD_Divide(pnumpoints, p[w], -originalplanes[k].normal[0], -originalplanes[k].normal[1], -originalplanes[k].normal[2], -originalplanes[k].dist, 1.0/32.0, pmaxpoints, p[!w], &pnumpoints, 0, NULL, NULL); + PolygonD_Divide(pnumpoints, p[w], -originalplanes[k].normal[0], -originalplanes[k].normal[1], -originalplanes[k].normal[2], -originalplanes[k].dist, 1.0/32.0, pmaxpoints, p[!w], &pnumpoints, 0, NULL, NULL, NULL); w = !w; } } @@ -322,14 +322,14 @@ colbrushf_t *Collision_NewBrushFromPlanes(mempool_t *mempool, int numoriginalpla colbrushf_t *Collision_AllocBrushFloat(mempool_t *mempool, int numpoints, int numplanes, int numtriangles, int supercontents) { colbrushf_t *brush; - brush = Mem_Alloc(mempool, sizeof(colbrushf_t) + sizeof(colpointf_t) * numpoints + sizeof(colplanef_t) * numplanes + sizeof(int[3]) * numtriangles); + brush = (colbrushf_t *)Mem_Alloc(mempool, sizeof(colbrushf_t) + sizeof(colpointf_t) * numpoints + sizeof(colplanef_t) * numplanes + sizeof(int[3]) * numtriangles); brush->supercontents = supercontents; brush->numplanes = numplanes; brush->numpoints = numpoints; brush->numtriangles = numtriangles; - brush->planes = (void *)(brush + 1); - brush->points = (void *)(brush->planes + brush->numplanes); - brush->elements = (void *)(brush->points + brush->numpoints); + brush->planes = (colplanef_t *)(brush + 1); + brush->points = (colpointf_t *)(brush->planes + brush->numplanes); + brush->elements = (int *)(brush->points + brush->numpoints); return brush; } @@ -505,13 +505,13 @@ void Collision_CalcPlanesForPolygonBrushFloat(colbrushf_t *brush) colbrushf_t *Collision_AllocBrushFromPermanentPolygonFloat(mempool_t *mempool, int numpoints, float *points, int supercontents) { colbrushf_t *brush; - brush = Mem_Alloc(mempool, sizeof(colbrushf_t) + sizeof(colplanef_t) * (numpoints + 2)); + brush = (colbrushf_t *)Mem_Alloc(mempool, sizeof(colbrushf_t) + sizeof(colplanef_t) * (numpoints + 2)); brush->supercontents = supercontents; brush->numpoints = numpoints; brush->numplanes = numpoints + 2; - brush->planes = (void *)(brush + 1); + brush->planes = (colplanef_t *)(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..."); return brush; } @@ -522,6 +522,7 @@ void Collision_TraceBrushBrushFloat(trace_t *trace, const colbrushf_t *thisbrush float enterfrac, leavefrac, d1, d2, f, imove, newimpactnormal[3], enterfrac2; const colplanef_t *startplane, *endplane; + VectorClear(newimpactnormal); enterfrac = -1; enterfrac2 = -1; leavefrac = 1; @@ -662,6 +663,7 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const float enterfrac, leavefrac, d1, d2, f, imove, newimpactnormal[3], enterfrac2; const colplanef_t *startplane, *endplane; + VectorClear(newimpactnormal); enterfrac = -1; enterfrac2 = -1; leavefrac = 1; @@ -741,7 +743,7 @@ void Collision_TraceLineBrushFloat(trace_t *trace, const vec3_t linestart, const // penetrating line segment is normally zero length if this brush was // generated from a polygon (infinitely thin), and could even be slightly // positive or negative due to rounding errors in that case. - if (brushsolid && enterfrac > -1 && enterfrac < trace->realfraction && enterfrac - (1.0f / 1024.0f) <= leavefrac) + if (brushsolid && enterfrac > -1 && enterfrac < trace->realfraction && enterfrac <= leavefrac) { #if 0 // broken @@ -838,12 +840,12 @@ void Collision_TraceBrushTriangleMeshFloat(trace_t *trace, const colbrushf_t *th VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v); VectorCopy(vertex3f + element3i[2] * 3, polyf_points[2].v); Collision_SnapCopyPoints(3, polyf_points, polyf_points, COLLISION_SNAPSCALE, COLLISION_SNAP); - facemins[0] = min(polyf_points[0].v[0], min(polyf_points[1].v[0], polyf_points[2].v[0])) - 1; - facemins[1] = min(polyf_points[0].v[1], min(polyf_points[1].v[1], polyf_points[2].v[1])) - 1; - facemins[2] = min(polyf_points[0].v[2], min(polyf_points[1].v[2], polyf_points[2].v[2])) - 1; - facemaxs[0] = max(polyf_points[0].v[0], max(polyf_points[1].v[0], polyf_points[2].v[0])) + 1; - facemaxs[1] = max(polyf_points[0].v[1], max(polyf_points[1].v[1], polyf_points[2].v[1])) + 1; - facemaxs[2] = max(polyf_points[0].v[2], max(polyf_points[1].v[2], polyf_points[2].v[2])) + 1; + facemins[0] = min(polyf_points[0].v[0], min(polyf_points[1].v[0], polyf_points[2].v[0])); + facemins[1] = min(polyf_points[0].v[1], min(polyf_points[1].v[1], polyf_points[2].v[1])); + facemins[2] = min(polyf_points[0].v[2], min(polyf_points[1].v[2], polyf_points[2].v[2])); + facemaxs[0] = max(polyf_points[0].v[0], max(polyf_points[1].v[0], polyf_points[2].v[0])); + facemaxs[1] = max(polyf_points[0].v[1], max(polyf_points[1].v[1], polyf_points[2].v[1])); + facemaxs[2] = max(polyf_points[0].v[2], max(polyf_points[1].v[2], polyf_points[2].v[2])); if (BoxesOverlap(segmentmins, segmentmaxs, facemins, facemaxs)) { Collision_CalcPlanesForPolygonBrushFloat(&polyf_brush); @@ -892,12 +894,12 @@ void Collision_TraceLineTriangleMeshFloat(trace_t *trace, const vec3_t linestart VectorCopy(vertex3f + element3i[1] * 3, polyf_points[1].v); VectorCopy(vertex3f + element3i[2] * 3, polyf_points[2].v); Collision_SnapCopyPoints(numpoints, polyf_points, polyf_points, COLLISION_SNAPSCALE, COLLISION_SNAP); - facemins[0] = min(polyf_points[0].v[0], min(polyf_points[1].v[0], polyf_points[2].v[0])) - 1; - facemins[1] = min(polyf_points[0].v[1], min(polyf_points[1].v[1], polyf_points[2].v[1])) - 1; - facemins[2] = min(polyf_points[0].v[2], min(polyf_points[1].v[2], polyf_points[2].v[2])) - 1; - facemaxs[0] = max(polyf_points[0].v[0], max(polyf_points[1].v[0], polyf_points[2].v[0])) + 1; - facemaxs[1] = max(polyf_points[0].v[1], max(polyf_points[1].v[1], polyf_points[2].v[1])) + 1; - facemaxs[2] = max(polyf_points[0].v[2], max(polyf_points[1].v[2], polyf_points[2].v[2])) + 1; + facemins[0] = min(polyf_points[0].v[0], min(polyf_points[1].v[0], polyf_points[2].v[0])); + facemins[1] = min(polyf_points[0].v[1], min(polyf_points[1].v[1], polyf_points[2].v[1])); + facemins[2] = min(polyf_points[0].v[2], min(polyf_points[1].v[2], polyf_points[2].v[2])); + facemaxs[0] = max(polyf_points[0].v[0], max(polyf_points[1].v[0], polyf_points[2].v[0])); + facemaxs[1] = max(polyf_points[0].v[1], max(polyf_points[1].v[1], polyf_points[2].v[1])); + facemaxs[2] = max(polyf_points[0].v[2], max(polyf_points[1].v[2], polyf_points[2].v[2])); if (BoxesOverlap(segmentmins, segmentmaxs, facemins, facemaxs)) { Collision_CalcPlanesForPolygonBrushFloat(&polyf_brush); @@ -1033,7 +1035,6 @@ colbrushf_t *Collision_BrushForBox(const matrix4x4_t *matrix, const vec3_t mins, void Collision_ClipTrace_BrushBox(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) { colbrushf_t *boxbrush, *thisbrush_start, *thisbrush_end; - matrix4x4_t identitymatrix; vec3_t startmins, startmaxs, endmins, endmaxs; // create brushes for the collision @@ -1041,7 +1042,6 @@ void Collision_ClipTrace_BrushBox(trace_t *trace, const vec3_t cmins, const vec3 VectorAdd(start, maxs, startmaxs); VectorAdd(end, mins, endmins); VectorAdd(end, maxs, endmaxs); - Matrix4x4_CreateIdentity(&identitymatrix); boxbrush = Collision_BrushForBox(&identitymatrix, cmins, cmaxs); thisbrush_start = Collision_BrushForBox(&identitymatrix, startmins, startmaxs); thisbrush_end = Collision_BrushForBox(&identitymatrix, endmins, endmaxs); @@ -1054,7 +1054,10 @@ void Collision_ClipTrace_BrushBox(trace_t *trace, const vec3_t cmins, const vec3 Collision_TraceBrushBrushFloat(trace, thisbrush_start, thisbrush_end, boxbrush, boxbrush); } -// LordHavoc: currently unused and not yet tested +//pseudocode for detecting line/sphere overlap without calculating an impact point +//linesphereorigin = sphereorigin - linestart;linediff = lineend - linestart;linespherefrac = DotProduct(linesphereorigin, linediff) / DotProduct(linediff, linediff);return VectorLength2(linesphereorigin - bound(0, linespherefrac, 1) * linediff) >= sphereradius*sphereradius; + +// LordHavoc: currently unused, but 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) @@ -1063,62 +1066,42 @@ float Collision_ClipTrace_Line_Sphere(double *linestart, double *lineend, double 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; + VectorCopy(lineend, impactpoint); + VectorClear(impactnormal); // calculate line direction - dir[0] = lineend[0] - linestart[0]; - dir[1] = lineend[1] - linestart[1]; - dir[2] = lineend[2] - linestart[2]; + VectorSubtract(lineend, linestart, dir); // normalize direction - linelength = sqrt(dir[0] * dir[0] + dir[1] * dir[1] + dir[2] * dir[2]); + linelength = VectorLength(dir); if (linelength) { scale = 1.0 / linelength; - dir[0] *= scale; - dir[1] *= scale; - dir[2] *= scale; + VectorScale(dir, scale, dir); } // 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]); + impactdist = DotProduct(sphereorigin, dir) - DotProduct(linestart, dir); // 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]; + VectorMA(linestart, impactdist, dir, v); + VectorSubtract(v, sphereorigin, v); + deviationdist = VectorLength2(v); // 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); + impactdist += 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]; + VectorMA(linestart, impactdist, dir, impactpoint); // 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]; + VectorSubtract(impactpoint, sphereorigin, impactnormal); // 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; - } + VectorNormalize(impactnormal); // return fraction of movement distance return impactdist / linelength; } @@ -1354,9 +1337,9 @@ colbsp_t; colbsp_t *Collision_CreateCollisionBSP(mempool_t *mempool) { colbsp_t *bsp; - bsp = Mem_Alloc(mempool, sizeof(colbsp_t)); + bsp = (colbsp_t *)Mem_Alloc(mempool, sizeof(colbsp_t)); bsp->mempool = mempool; - bsp->nodes = Mem_Alloc(bsp->mempool, sizeof(colbspnode_t)); + bsp->nodes = (colbspnode_t *)Mem_Alloc(bsp->mempool, sizeof(colbspnode_t)); return bsp; }