diff --git a/src/cxxutil.hpp b/src/cxxutil.hpp index 74349a0ff..fa4e88e25 100644 --- a/src/cxxutil.hpp +++ b/src/cxxutil.hpp @@ -147,6 +147,73 @@ public: template NotNull(T) -> NotNull; +// does a super safe cast from floating point to interger types +// this prob could be better since i suck at ceepeepee +// but atleast we can just template shit to our desired types +template +static inline IntT floattoint(FloatT val) +{ + // :chaosleep: + static_assert(std::is_floating_point_v, "Input must be a floating-point type"); + static_assert(std::is_integral_v, "Output must be a integer type"); + + if (std::fpclassify(val) == FP_NAN) + return 0; // if stuffs not a number we sure screwed up lmao + + // treat inifinity as "int min/max" + if (std::fpclassify(val) == FP_INFINITE) + { + // yes infinity can be signed kek + if (std::signbit(val)) + return std::numeric_limits::min(); // negative infinity, so return min + else + return std::numeric_limits::max(); + } + + // make sure we fit into our targettype uwu + if (val > static_cast(std::numeric_limits::max())) + return std::numeric_limits::max(); + else if (val < static_cast(std::numeric_limits::min())) + return std::numeric_limits::min(); + + return static_cast(val); +} + +// safe float to fixed +// which handles nan and inf +// pretty much the same stuff as the above, but uh, idk how id use the above with this +template // can use both float and doubles yay +static inline int32_t floattofixed(FloatT val) +{ + // :chaosleep: + static_assert(std::is_floating_point_v, "Input must be a floating-point type"); + + // fixed_t is just an int32_t, i dont wanna include doomtype here if it can be avoided + + if (std::fpclassify(val) == FP_NAN) + return 0; // if stuffs not a number we sure screwed up lmao + + // treat inifinity as "int min/max" + if (std::fpclassify(val) == FP_INFINITE) + { + // yes infinity can be signed kek + if (std::signbit(val)) + return std::numeric_limits::min(); // negative infinity, so return min + else + return std::numeric_limits::max(); + } + + const FloatT ret = (val * 65536.0); + + // make sure we fit into our targettype uwu + if (ret > static_cast(std::numeric_limits::max())) + return std::numeric_limits::max(); + else if (ret < static_cast(std::numeric_limits::min())) + return std::numeric_limits::min(); + + return static_cast(ret); +} + } // namespace srb2 #endif // __SRB2_CXXUTIL_HPP__ diff --git a/src/r_draw_span.cpp b/src/r_draw_span.cpp index ae9baec94..392ec4e5e 100644 --- a/src/r_draw_span.cpp +++ b/src/r_draw_span.cpp @@ -18,6 +18,8 @@ using namespace libdivide; +#include "cxxutil.hpp" + // ========================================================================== // SPANS // ========================================================================== @@ -358,10 +360,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) endz = 1.f/iz; endu = uz*endz; endv = vz*endz; - stepu = (INT64)((endu - startu) * INVSPAN); - stepv = (INT64)((endv - startv) * INVSPAN); - u = (INT64)(startu); - v = (INT64)(startv); + stepu = srb2::floattoint((endu - startu) * INVSPAN); + stepv = srb2::floattoint((endv - startv) * INVSPAN); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); x1 = ds->x1; @@ -393,8 +395,8 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) { if (width == 1) { - u = (INT64)(startu); - v = (INT64)(startv); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); bit = ((v >> nflatyshift) & nflatmask) | (u >> nflatxshift); if constexpr (!(Type & DS_SPRITE)) { @@ -418,10 +420,10 @@ static void R_DrawTiltedSpanTemplate(drawspandata_t* ds) endu = uz*endz; endv = vz*endz; left = 1.f/left; - stepu = (INT64)((endu - startu) * left); - stepv = (INT64)((endv - startv) * left); - u = (INT64)(startu); - v = (INT64)(startv); + stepu = srb2::floattoint((endu - startu) * left); + stepv = srb2::floattoint((endv - startv) * left); + u = srb2::floattoint(startu); + v = srb2::floattoint(startv); for (; width != 0; width--) { diff --git a/src/r_segs.cpp b/src/r_segs.cpp index 0c3ac43ef..1b1f91f77 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -39,6 +39,8 @@ extern "C" consvar_t cv_debugfinishline; +#include "cxxutil.hpp" + #define HEIGHTBITS 12 #define HEIGHTUNIT (1<v2->y-curline->v1->y); - b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); + a1 = FixedToDouble(curline->v2->y-curline->v1->y); + b1 = FixedToDouble(curline->v1->x-curline->v2->x); + c1 = a1*FixedToDouble(curline->v1->x) + b1*FixedToDouble(curline->v1->y); - a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); + a2 = -FixedToDouble(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FixedToDouble(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FixedToDouble(viewx) + b2*FixedToDouble(viewy); det = a1*b2 - a2*b1; - ds_p->leftpos.x = segleft.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->leftpos.y = segleft.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); + ds_p->leftpos.x = segleft.x = srb2::floattofixed((b2*c1 - b1*c2)/det); + ds_p->leftpos.y = segleft.y = srb2::floattofixed((a1*c2 - a2*c1)/det); } // right @@ -1968,23 +1967,19 @@ void R_StoreWallRange(INT32 start, INT32 stop) double a1, b1, c1, a2, b2, c2, det; // 1 is the seg, 2 is the view angle vector... ///TODO: convert to fixed point - a1 = FIXED_TO_DOUBLE(curline->v2->y-curline->v1->y); - b1 = FIXED_TO_DOUBLE(curline->v1->x-curline->v2->x); - c1 = a1*FIXED_TO_DOUBLE(curline->v1->x) + b1*FIXED_TO_DOUBLE(curline->v1->y); + a1 = FixedToDouble(curline->v2->y-curline->v1->y); + b1 = FixedToDouble(curline->v1->x-curline->v2->x); + c1 = a1*FixedToDouble(curline->v1->x) + b1*FixedToDouble(curline->v1->y); - a2 = -FIXED_TO_DOUBLE(FINESINE(temp>>ANGLETOFINESHIFT)); - b2 = FIXED_TO_DOUBLE(FINECOSINE(temp>>ANGLETOFINESHIFT)); - c2 = a2*FIXED_TO_DOUBLE(viewx) + b2*FIXED_TO_DOUBLE(viewy); + a2 = -FixedToDouble(FINESINE(temp>>ANGLETOFINESHIFT)); + b2 = FixedToDouble(FINECOSINE(temp>>ANGLETOFINESHIFT)); + c2 = a2*FixedToDouble(viewx) + b2*FixedToDouble(viewy); det = a1*b2 - a2*b1; - ds_p->rightpos.x = segright.x = DOUBLE_TO_FIXED((b2*c1 - b1*c2)/det); - ds_p->rightpos.y = segright.y = DOUBLE_TO_FIXED((a1*c2 - a2*c1)/det); + ds_p->rightpos.x = segright.x = srb2::floattofixed((b2*c1 - b1*c2)/det); + ds_p->rightpos.y = segright.y = srb2::floattofixed((a1*c2 - a2*c1)/det); } - -#undef FIXED_TO_DOUBLE -#undef DOUBLE_TO_FIXED - }