diff --git a/rehlds/build.gradle b/rehlds/build.gradle index 0e4cb2d..8832602 100644 --- a/rehlds/build.gradle +++ b/rehlds/build.gradle @@ -122,7 +122,7 @@ void setupToolchain(NativeBinarySpec b) { } b.lib LazyNativeDepSet.create(dep_bzip2, 'bzip2', b.buildType.name, true) - cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'DEDICATED', 'SWDS', 'REHLDS_SELF' + cfg.singleDefines 'USE_BREAKPAD_HANDLER', 'DEDICATED', 'SWDS', 'REHLDS_SELF', 'REHLDS_OPT_PEDANTIC' if (cfg instanceof MsvcToolchainConfig) { cfg.compilerOptions.pchConfig = new MsvcToolchainConfig.PrecompiledHeadersConfig( diff --git a/rehlds/engine/pmovetst.cpp b/rehlds/engine/pmovetst.cpp index 6cba04d..eb20404 100644 --- a/rehlds/engine/pmovetst.cpp +++ b/rehlds/engine/pmovetst.cpp @@ -28,6 +28,9 @@ #include "precompiled.h" +// 1/32 epsilon to keep floating point happy +#define DIST_EPSILON (0.03125f) + int g_contentsresult; hull_t box_hull_0; box_clipnodes_t box_clipnodes_0; @@ -638,8 +641,9 @@ struct pmtrace_s *PM_TraceLineEx(float *start, float *end, int flags, int usehul return &tr; } +#ifndef REHLDS_OPT_PEDANTIC /* <6ef4a> ../engine/pmovetst.c:844 */ -qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_t *p1, vec_t *p2, pmtrace_t *trace) +qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, const vec_t *p1, const vec_t *p2, pmtrace_t *trace) { qboolean retval; dclipnode_t *node; @@ -653,33 +657,30 @@ qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_ if (num < 0) { - if (num == -2) + if (num == CONTENTS_SOLID) { - trace->startsolid = 1; - retval = 1; + trace->startsolid = TRUE; } else { - trace->allsolid = 0; - if (num == -1) + trace->allsolid = FALSE; + if (num == CONTENTS_EMPTY) { - trace->inopen = 1; - retval = 1; + trace->inopen = TRUE; } else { - trace->inwater = 1; - retval = 1; + trace->inwater = TRUE; } } - return retval; + return TRUE; } if (hull->firstclipnode >= hull->lastclipnode) { - trace->allsolid = 0; - trace->inopen = 1; - return 1; + trace->allsolid = FALSE; + trace->inopen = TRUE; + return TRUE; } node = &hull->clipnodes[num]; @@ -787,3 +788,171 @@ qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_ Con_DPrintf("Trace backed up past 0.0.\n"); return 0; } +#else // REHLDS_OPT_PEDANTIC +// version with unrolled tail recursion +qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, const vec_t *p1, const vec_t *p2, pmtrace_t *trace) +{ + dclipnode_t *node; + mplane_t *plane; + vec3_t mid; + float pdif; + float frac; + float t1; + float t2; + float midf; + vec3_t custom_p1; // for holding custom p1 value + + while (1) + { + if (num < 0) + { + if (num == CONTENTS_SOLID) + { + trace->startsolid = TRUE; + } + else + { + trace->allsolid = FALSE; + if (num == CONTENTS_EMPTY) + { + trace->inopen = TRUE; + } + else + { + trace->inwater = TRUE; + } + } + return TRUE; + } + + if (hull->firstclipnode >= hull->lastclipnode) + { + trace->allsolid = FALSE; + trace->inopen = TRUE; + return TRUE; + } + + // find the point distances + node = &hull->clipnodes[num]; + plane = &hull->planes[node->planenum]; + if (plane->type >= 3u) + { + t1 = p1[1] * plane->normal[1] + p1[2] * plane->normal[2] + p1[0] * plane->normal[0] - plane->dist; + t2 = p2[1] * plane->normal[1] + p2[2] * plane->normal[2] + plane->normal[0] * p2[0] - plane->dist; + } + else + { + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; + } + if (t1 >= 0.0 && t2 >= 0.0) + { + num = node->children[0]; // only 1 arg changed + continue; + } + + if (t1 >= 0.0) + { + midf = t1 - DIST_EPSILON; + } + else + { + if (t2 < 0.0) + { + num = node->children[1]; + continue; + } + + midf = t1 + DIST_EPSILON; + } + midf = midf / (t1 - t2); + if (midf >= 0.0) + { + if (midf > 1.0) + midf = 1.0; + } + else + { + midf = 0.0; + } + + pdif = p2f - p1f; + frac = pdif * midf + p1f; + mid[0] = (p2[0] - p1[0]) * midf + p1[0]; + mid[1] = (p2[1] - p1[1]) * midf + p1[1]; + mid[2] = (p2[2] - p1[2]) * midf + p1[2]; + + int side = (t1 >= 0.0) ? 0 : 1; + + if (!PM_RecursiveHullCheck(hull, node->children[side], p1f, frac, p1, mid, trace)) + return 0; + + if (PM_HullPointContents(hull, node->children[side ^ 1], mid) != -2) + { + num = node->children[side ^ 1]; + p1f = frac; + p1 = custom_p1; + custom_p1[0] = mid[0]; + custom_p1[1] = mid[1]; + custom_p1[2] = mid[2]; + continue; + } + + if (trace->allsolid) + return 0; + + if (side) + { + trace->plane.normal[0] = vec3_origin[0] - plane->normal[0]; + trace->plane.normal[1] = vec3_origin[1] - plane->normal[1]; + trace->plane.normal[2] = vec3_origin[2] - plane->normal[2]; + trace->plane.dist = -plane->dist; + } + else + { + trace->plane.normal[0] = plane->normal[0]; + trace->plane.normal[1] = plane->normal[1]; + trace->plane.normal[2] = plane->normal[2]; + trace->plane.dist = plane->dist; + } + + if (PM_HullPointContents(hull, hull->firstclipnode, mid) != -2) + { + trace->fraction = frac; + trace->endpos[0] = mid[0]; + trace->endpos[1] = mid[1]; + trace->endpos[2] = mid[2]; + return 0; + } + + while (1) + { + midf = (float)(midf - 0.05); + if (midf < 0.0) + break; + + frac = pdif * midf + p1f; + mid[0] = (p2[0] - p1[0]) * midf + p1[0]; + mid[1] = (p2[1] - p1[1]) * midf + p1[1]; + mid[2] = (p2[2] - p1[2]) * midf + p1[2]; + if (PM_HullPointContents(hull, hull->firstclipnode, mid) != -2) + { + trace->fraction = frac; + trace->endpos[0] = mid[0]; + trace->endpos[1] = mid[1]; + trace->endpos[2] = mid[2]; + return 0; + } + } + + trace->fraction = frac; + trace->endpos[0] = mid[0]; + trace->endpos[1] = mid[1]; + trace->endpos[2] = mid[2]; + Con_DPrintf("Trace backed up past 0.0.\n"); + return 0; + } + + return 0; +} +#endif // REHLDS_OPT_PEDANTIC diff --git a/rehlds/engine/pmovetst.h b/rehlds/engine/pmovetst.h index a41f271..e48df8e 100644 --- a/rehlds/engine/pmovetst.h +++ b/rehlds/engine/pmovetst.h @@ -72,6 +72,6 @@ pmtrace_t PM_PlayerTrace(vec_t *start, vec_t *end, int traceFlags, int ignore_pe pmtrace_t PM_PlayerTraceEx(vec_t *start, vec_t *end, int traceFlags, int(*pfnIgnore)(physent_t *)); struct pmtrace_s *PM_TraceLine(float *start, float *end, int flags, int usehull, int ignore_pe); struct pmtrace_s *PM_TraceLineEx(float *start, float *end, int flags, int usehull, int(*pfnIgnore)(physent_t *)); -qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_t *p1, vec_t *p2, pmtrace_t *trace); +qboolean PM_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, const vec_t *p1, const vec_t *p2, pmtrace_t *trace); #endif // PMOVETST_H diff --git a/rehlds/engine/world.cpp b/rehlds/engine/world.cpp index 0b402ff..e306a44 100644 --- a/rehlds/engine/world.cpp +++ b/rehlds/engine/world.cpp @@ -28,6 +28,7 @@ #include "precompiled.h" +#define DIST_EPSILON (0.03125f) hull_t box_hull; hull_t beam_hull; @@ -641,6 +642,7 @@ edict_t *SV_TestEntityPosition(edict_t *ent) return NULL; } +#ifndef REHLDS_OPT_PEDANTIC /* ../engine/world.c:804 */ qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_t *p1, vec_t *p2, trace_t *trace) { @@ -775,6 +777,159 @@ qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_ } return TRUE; } +#else // REHLDS_OPT_PEDANTIC +// version with unrolled tail recursion +qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, const vec_t *p1, const vec_t *p2, trace_t *trace) +{ + dclipnode_t *node; + mplane_t *plane; + float t2; + vec3_t mid; + float frac; + float t1; + signed int side; + float midf; + float pdif; + vec3_t custom_p1; // for holding custom p1 value + + while (num >= 0) + { + pdif = p2f - p1f; + + if (num < hull->firstclipnode || num > hull->lastclipnode || !hull->planes) + Sys_Error(__FUNCTION__ ": bad node number"); + + node = &hull->clipnodes[num]; + plane = &hull->planes[hull->clipnodes[num].planenum]; + if (plane->type >= 3) + { + t1 = p1[1] * plane->normal[1] + p1[2] * plane->normal[2] + p1[0] * plane->normal[0] - plane->dist; + t2 = p2[1] * plane->normal[1] + p2[2] * plane->normal[2] + plane->normal[0] * p2[0] - plane->dist; + } + else + { + t1 = p1[plane->type] - plane->dist; + t2 = p2[plane->type] - plane->dist; + } + if (t1 >= 0.0f && t2 >= 0.0f) + { + num = node->children[0]; + continue; + } + + if (t1 >= 0.0f) + { + midf = t1 - DIST_EPSILON; + } + else + { + if (t2 < 0.0f) + { + num = node->children[1]; + continue; + } + + midf = t1 + DIST_EPSILON; + } + + midf = midf / (t1 - t2); + if (midf >= 0.0f) + { + if (midf > 1.0f) + midf = 1.0f; + } + else + { + midf = 0.0f; + } + if (!IS_NAN(midf)) // not a number + { + frac = pdif * midf + p1f; + mid[0] = (p2[0] - p1[0]) * midf + p1[0]; + mid[1] = (p2[1] - p1[1]) * midf + p1[1]; + mid[2] = (p2[2] - p1[2]) * midf + p1[2]; + side = (t1 < 0.0f) ? 1 : 0; + if (SV_RecursiveHullCheck(hull, node->children[side], p1f, frac, p1, mid, trace)) + { + if (SV_HullPointContents(hull, node->children[side ^ 1], mid) != CONTENTS_SOLID) + { + num = node->children[side ^ 1]; + p1f = frac; + p1 = custom_p1; + custom_p1[0] = mid[0]; + custom_p1[1] = mid[1]; + custom_p1[2] = mid[2]; + continue; + } + + if (!trace->allsolid) + { + if (side) + { + trace->plane.normal[0] = vec3_origin[0] - plane->normal[0]; + trace->plane.normal[1] = vec3_origin[1] - plane->normal[1]; + trace->plane.normal[2] = vec3_origin[2] - plane->normal[2]; + trace->plane.dist = -plane->dist; + } + else + { + trace->plane.normal[0] = plane->normal[0]; + trace->plane.normal[1] = plane->normal[1]; + trace->plane.normal[2] = plane->normal[2]; + trace->plane.dist = plane->dist; + } + + while (1) + { + if (SV_HullPointContents(hull, hull->firstclipnode, mid) != CONTENTS_SOLID) + { + trace->fraction = frac; + trace->endpos[0] = mid[0]; + trace->endpos[1] = mid[1]; + trace->endpos[2] = mid[2]; + return FALSE; + } + midf -= 0.1f; + if (midf < 0.0f) + break; + frac = pdif * midf + p1f; + mid[0] = (p2[0] - p1[1]) * midf + p1[0]; + mid[1] = (p2[1] - p1[1]) * midf + p1[1]; + mid[2] = (p2[2] - p1[2]) * midf + p1[2]; + } + trace->fraction = frac; + trace->endpos[0] = mid[0]; + trace->endpos[1] = mid[1]; + trace->endpos[2] = mid[2]; + Con_DPrintf("backup past 0\n"); + return FALSE; + } + } + } + return FALSE; + } + + if (num == CONTENTS_SOLID) + { + trace->startsolid = TRUE; + } + else + { + trace->allsolid = FALSE; + if (num == CONTENTS_EMPTY) + { + trace->inopen = TRUE; + return TRUE; + } + if (num != CONTENTS_TRANSLUCENT) + { + trace->inwater = TRUE; + return TRUE; + } + } + return TRUE; +} +#endif // REHLDS_OPT_PEDANTIC /* ../engine/world.c:948 */ void SV_SingleClipMoveToEntity(edict_t *ent, const vec_t *start, const vec_t *mins, const vec_t *maxs, const vec_t *end, trace_t *trace) diff --git a/rehlds/engine/world.h b/rehlds/engine/world.h index 25c3d3e..57cb8fa 100644 --- a/rehlds/engine/world.h +++ b/rehlds/engine/world.h @@ -115,7 +115,7 @@ int SV_HullPointContents(hull_t *hull, int num, const vec_t *p); int SV_LinkContents(areanode_t *node, const vec_t *pos); int SV_PointContents(const vec_t *p); edict_t *SV_TestEntityPosition(edict_t *ent); -qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, vec_t *p1, vec_t *p2, trace_t *trace); +qboolean SV_RecursiveHullCheck(hull_t *hull, int num, float p1f, float p2f, const vec_t *p1, const vec_t *p2, trace_t *trace); void SV_SingleClipMoveToEntity(edict_t *ent, const vec_t *start, const vec_t *mins, const vec_t *maxs, const vec_t *end, trace_t *trace); trace_t SV_ClipMoveToEntity(edict_t *ent, const vec_t *start, const vec_t *mins, const vec_t *maxs, const vec_t *end); void SV_ClipToLinks(areanode_t *node, moveclip_t *clip);