From 6d0ef7a9da12f640e562133367e1f69afeadc9a4 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Mon, 8 Feb 2016 12:10:53 +0100 Subject: [PATCH] - added conversion macros to convert floating point angles to angle_t, using xs_Float.h, and replaced all occurences in the code with them (let's hope I found everything.) Converting a floating point value that is out of range for a signed integer will result in 0x80000000 with SSE math, which is used exclusively for this purpose on modern Visual C++ compilers, so this cannot be used anywhere. On ARM there's problems with float to unsigned int conversions. xs_Float does not depend on these --- src/c_cmds.cpp | 13 +++++++++++++ src/d_netinfo.cpp | 2 +- src/edata.cpp | 4 ++-- src/fragglescript/t_func.cpp | 6 +++--- src/g_doom/a_doomweaps.cpp | 2 +- src/g_shared/a_camera.cpp | 6 +++--- src/g_shared/a_movingcamera.cpp | 24 ++++++++++++------------ src/m_fixed.h | 8 ++++++++ src/p_enemy.cpp | 4 ++-- src/p_udmf.cpp | 2 +- src/r_data/voxels.cpp | 2 +- src/r_plane.cpp | 8 ++++---- src/r_things.cpp | 2 +- src/s_sound.cpp | 2 +- src/tables.h | 9 --------- src/zscript/vm.h | 4 ++-- src/zscript/vmexec.cpp | 1 + src/zscript/vmexec.h | 5 ++--- 18 files changed, 58 insertions(+), 46 deletions(-) diff --git a/src/c_cmds.cpp b/src/c_cmds.cpp index 05bc66e89..30fbd1e51 100644 --- a/src/c_cmds.cpp +++ b/src/c_cmds.cpp @@ -1236,3 +1236,16 @@ CCMD(secret) } } } + +CCMD(angleconvtest) +{ + Printf("Testing degrees to angle conversion:\n"); + for (double ang = -5 * 180.; ang < 5 * 180.; ang += 45.) + { + angle_t ang1 = FLOAT2ANGLE(ang); + angle_t ang2 = (angle_t)(ang * (ANGLE_90 / 90.)); + angle_t ang3 = (angle_t)(int)(ang * (ANGLE_90 / 90.)); + Printf("Angle = %.5f: xs_RoundToInt = %08x, unsigned cast = %08x, signed cast = %08x\n", + ang, ang1, ang2, ang3); + } +} diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 68dafa5ea..79d6d2aa9 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -894,7 +894,7 @@ void ReadCompatibleUserInfo(FArchive &arc, userinfo_t &info) *static_cast(info[NAME_Name]) = netname; *static_cast(info[NAME_Team]) = team; - *static_cast(info[NAME_Autoaim]) = (float)aimdist / ANGLE_1; + *static_cast(info[NAME_Autoaim]) = ANGLE2FLOAT(aimdist); *static_cast(info[NAME_Skin]) = skin; *static_cast(info[NAME_Gender]) = gender; *static_cast(info[NAME_NeverSwitchOnPickup]) = neverswitch; diff --git a/src/edata.cpp b/src/edata.cpp index 13e986425..1b737532c 100644 --- a/src/edata.cpp +++ b/src/edata.cpp @@ -392,7 +392,7 @@ static void parseSector(FScanner &sc) { sc.CheckString("="); sc.MustGetFloat(); - sec.planexform[sector_t::floor].angle = angle_t(sc.Float * ANGLE_90 / 90.); + sec.planexform[sector_t::floor].angle = FLOAT2ANGLE(sc.Float); } else if (sc.Compare("flooroffsetx")) { @@ -416,7 +416,7 @@ static void parseSector(FScanner &sc) { sc.CheckString("="); sc.MustGetFloat(); - sec.planexform[sector_t::ceiling].angle = angle_t(sc.Float * ANGLE_90 / 90.); + sec.planexform[sector_t::ceiling].angle = FLOAT2ANGLE(sc.Float); } else if (sc.Compare("ceilingoffsetx")) { diff --git a/src/fragglescript/t_func.cpp b/src/fragglescript/t_func.cpp index 158f7b8b8..e5803fb3e 100644 --- a/src/fragglescript/t_func.cpp +++ b/src/fragglescript/t_func.cpp @@ -1473,9 +1473,9 @@ void FParser::SF_SetCamera(void) else { fixed_t pitch = fixedvalue(t_argv[3]); - if(pitch < -50*FRACUNIT) pitch = -50*FRACUNIT; - if(pitch > 50*FRACUNIT) pitch = 50*FRACUNIT; - newcamera->pitch=(angle_t)((pitch/65536.0f)*(ANGLE_45/45.0f)*(20.0f/32.0f)); + if (pitch < -50 * FRACUNIT) pitch = -50 * FRACUNIT; + if (pitch > 50 * FRACUNIT) pitch = 50 * FRACUNIT; + newcamera->pitch = xs_CRoundToUInt((pitch / 65536.0f)*(ANGLE_45 / 45.0f)*(20.0f / 32.0f)); } player->camera=newcamera; } diff --git a/src/g_doom/a_doomweaps.cpp b/src/g_doom/a_doomweaps.cpp index e3a05d0db..cacffd6ca 100644 --- a/src/g_doom/a_doomweaps.cpp +++ b/src/g_doom/a_doomweaps.cpp @@ -124,7 +124,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_Saw) PARAM_CLASS_OPT (pufftype, AActor) { pufftype = NULL; } PARAM_INT_OPT (flags) { flags = 0; } PARAM_FIXED_OPT (range) { range = 0; } - PARAM_ANGLE_OPT (spread_xy) { spread_xy = angle_t(2.8125 * (ANGLE_90 / 90.0)); } + PARAM_ANGLE_OPT(spread_xy) { spread_xy = 33554432; /*angle_t(2.8125 * (ANGLE_90 / 90.0));*/ } // The floating point expression does not get optimized away. PARAM_ANGLE_OPT (spread_z) { spread_z = 0; } PARAM_FIXED_OPT (lifesteal) { lifesteal = 0; } PARAM_INT_OPT (lifestealmax) { lifestealmax = 0; } diff --git a/src/g_shared/a_camera.cpp b/src/g_shared/a_camera.cpp index 37457e7f0..28aa38ea7 100644 --- a/src/g_shared/a_camera.cpp +++ b/src/g_shared/a_camera.cpp @@ -86,7 +86,7 @@ void ASecurityCamera::PostBeginPlay () pitch = -ANGLE_90 + ANGLE_1; else if (pitch >= ANGLE_90) pitch = ANGLE_90 - ANGLE_1; - Range = (angle_t)((float)args[1] * 536870912.f / 45.f); + Range = FLOAT2ANGLE(args[1]); } void ASecurityCamera::Tick () @@ -136,7 +136,7 @@ void AAimingCamera::PostBeginPlay () args[2] = 0; Super::PostBeginPlay (); - MaxPitchChange = (int)((float)changepitch * 536870912.f / 45.f / (float)TICRATE); + MaxPitchChange = FLOAT2ANGLE(changepitch * TICRATE); Range /= TICRATE; TActorIterator iterator (args[3]); @@ -181,7 +181,7 @@ void AAimingCamera::Tick () double dz = Z() - tracer->Z() - tracer->height/2; double dist = vect.Length(); double ang = dist != 0.f ? atan2 (dz, dist) : 0; - int desiredpitch = (angle_t)(ang * 2147483648.f / PI); + int desiredpitch = (int)RAD2ANGLE(ang); if (abs (desiredpitch - pitch) < MaxPitchChange) { pitch = desiredpitch; diff --git a/src/g_shared/a_movingcamera.cpp b/src/g_shared/a_movingcamera.cpp index fe4526e16..c01dea497 100644 --- a/src/g_shared/a_movingcamera.cpp +++ b/src/g_shared/a_movingcamera.cpp @@ -430,12 +430,12 @@ bool APathFollower::Interpolate () } if (args[2] & 4) { // adjust pitch; use floats for precision - float fdx = FIXED2FLOAT(dx); - float fdy = FIXED2FLOAT(dy); - float fdz = FIXED2FLOAT(-dz); - float dist = (float)sqrt (fdx*fdx + fdy*fdy); - float ang = dist != 0.f ? (float)atan2 (fdz, dist) : 0; - pitch = (angle_t)(ang * 2147483648.f / PI); + double fdx = FIXED2DBL(dx); + double fdy = FIXED2DBL(dy); + double fdz = FIXED2DBL(-dz); + double dist = sqrt (fdx*fdx + fdy*fdy); + double ang = dist != 0.f ? atan2 (fdz, dist) : 0; + pitch = (fixed_t)RAD2ANGLE(ang); } } else @@ -449,11 +449,11 @@ bool APathFollower::Interpolate () float lerped = Lerp (angle1, angle2 + 4294967296.f); if (lerped >= 4294967296.f) { - angle = (angle_t)(lerped - 4294967296.f); + angle = xs_CRoundToUInt(lerped - 4294967296.f); } else { - angle = (angle_t)lerped; + angle = xs_CRoundToUInt(lerped); } } else if (angle2 - angle1 >= 2147483648.f) @@ -461,16 +461,16 @@ bool APathFollower::Interpolate () float lerped = Lerp (angle1, angle2 - 4294967296.f); if (lerped < 0.f) { - angle = (angle_t)(lerped + 4294967296.f); + angle = xs_CRoundToUInt(lerped + 4294967296.f); } else { - angle = (angle_t)lerped; + angle = xs_CRoundToUInt(lerped); } } else { - angle = (angle_t)Lerp (angle1, angle2); + angle = xs_CRoundToUInt(Lerp (angle1, angle2)); } } if (args[2] & 1) @@ -677,7 +677,7 @@ bool AMovingCamera::Interpolate () double dz = FIXED2DBL(Z() - tracer->Z() - tracer->height/2); double dist = sqrt (dx*dx + dy*dy); double ang = dist != 0.f ? atan2 (dz, dist) : 0; - pitch = (angle_t)(ang * 2147483648.f / PI); + pitch = RAD2ANGLE(ang); } return true; diff --git a/src/m_fixed.h b/src/m_fixed.h index e7ced58e3..8c1aa7038 100644 --- a/src/m_fixed.h +++ b/src/m_fixed.h @@ -141,4 +141,12 @@ inline SDWORD ModDiv (SDWORD num, SDWORD den, SDWORD *dmval) #define FIXED2FLOAT(f) ((f) / float(65536)) #define FIXED2DBL(f) ((f) / double(65536)) +#define ANGLE2DBL(f) ((f) * (90./ANGLE_90)) +#define ANGLE2FLOAT(f) (float((f) * (90./ANGLE_90))) +#define FLOAT2ANGLE(f) ((angle_t)xs_CRoundToInt((f) * (ANGLE_90/90.))) + +#define ANGLE2RAD(f) ((f) * (M_PI/ANGLE_180)) +#define ANGLE2RADF(f) ((f) * float(M_PI/ANGLE_180)) +#define RAD2ANGLE(f) ((angle_t)xs_CRoundToInt((f) * (ANGLE_180/M_PI))) + #endif diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 1b01c3349..42bb6c7ac 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -1859,7 +1859,7 @@ DEFINE_ACTION_FUNCTION_PARAMS(AActor, A_LookEx) AActor *targ = NULL; // Shuts up gcc fixed_t dist; - angle_t fov = (fov_f == 0) ? ANGLE_180 : angle_t(fov_f * ANGLE_90 / 90); + angle_t fov = (fov_f == 0) ? ANGLE_180 : FLOAT2ANGLE(fov_f); FLookExParams params = { fov, minseedist, maxseedist, maxheardist, flags, seestate }; if (self->flags5 & MF5_INCONVERSATION) @@ -2827,7 +2827,7 @@ void A_Face (AActor *self, AActor *other, angle_t max_turn, angle_t max_pitch, a double dist_z = target_z - source_z; double ddist = sqrt(dist.X*dist.X + dist.Y*dist.Y + dist_z*dist_z); - int other_pitch = (int)rad2bam(asin(dist_z / ddist)); + int other_pitch = (int)RAD2ANGLE(asin(dist_z / ddist)); if (max_pitch != 0) { diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index 118ee2d95..2b01be372 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -260,7 +260,7 @@ fixed_t UDMFParserBase::CheckFixed(const char *key) angle_t UDMFParserBase::CheckAngle(const char *key) { - return angle_t(CheckFloat(key) * ANGLE_90 / 90.); + return FLOAT2ANGLE(CheckFloat(key)); } bool UDMFParserBase::CheckBool(const char *key) diff --git a/src/r_data/voxels.cpp b/src/r_data/voxels.cpp index d5ad1fa89..66c6937e5 100644 --- a/src/r_data/voxels.cpp +++ b/src/r_data/voxels.cpp @@ -531,7 +531,7 @@ static void VOX_ReadOptions(FScanner &sc, VoxelOptions &opts) { sc.TokenMustBe(TK_FloatConst); } - opts.AngleOffset = ANGLE_90 + angle_t(sc.Float * ANGLE_180 / 180.0); + opts.AngleOffset = ANGLE_90 + FLOAT2ANGLE(sc.Float); } else if (sc.Compare("overridepalette")) { diff --git a/src/r_plane.cpp b/src/r_plane.cpp index 3e0f2444e..e53523008 100644 --- a/src/r_plane.cpp +++ b/src/r_plane.cpp @@ -1531,7 +1531,7 @@ void R_DrawNormalPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske yscale = pl->yscale << (16 - ds_ybits); if (planeang != 0) { - double rad = bam2rad(planeang); + double rad = ANGLE2RAD(planeang); double cosine = cos(rad), sine = sin(rad); pviewx = xs_RoundToInt(pl->xoffs + viewx * cosine - viewy * sine); @@ -1668,13 +1668,13 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske // p is the texture origin in view space // Don't add in the offsets at this stage, because doing so can result in // errors if the flat is rotated. - ang = bam2rad(ANG270 - viewangle); + ang = ANGLE2RAD(ANG270 - viewangle); p[0] = vx * cos(ang) - vy * sin(ang); p[2] = vx * sin(ang) + vy * cos(ang); p[1] = pl->height.ZatPoint(0.0, 0.0) - vz; // m is the v direction vector in view space - ang = bam2rad(ANG180 - viewangle - pl->angle); + ang = ANGLE2RAD(ANG180 - viewangle - pl->angle); m[0] = yscale * cos(ang); m[2] = yscale * sin(ang); // m[1] = FIXED2FLOAT(pl->height.ZatPoint (0, iyscale) - pl->height.ZatPoint (0,0)); @@ -1690,7 +1690,7 @@ void R_DrawTiltedPlane (visplane_t *pl, fixed_t alpha, bool additive, bool maske // This code keeps the texture coordinates constant across the x,y plane no matter // how much you slope the surface. Use the commented-out code above instead to keep // the textures a constant size across the surface's plane instead. - ang = bam2rad(pl->angle); + ang = ANGLE2RAD(pl->angle); m[1] = pl->height.ZatPoint(vx + yscale * sin(ang), vy + yscale * cos(ang)) - zeroheight; ang += PI/2; n[1] = pl->height.ZatPoint(vx + xscale * sin(ang), vy + xscale * cos(ang)) - zeroheight; diff --git a/src/r_things.cpp b/src/r_things.cpp index 682ad5f35..407bf54c7 100644 --- a/src/r_things.cpp +++ b/src/r_things.cpp @@ -1012,7 +1012,7 @@ void R_ProjectSprite (AActor *thing, int fakeside, F3DFloor *fakefloor, F3DFloor if (voxelspin != 0) { double ang = double(I_FPSTime()) * voxelspin / 1000; - vis->angle -= angle_t(ang * (4294967296.f / 360)); + vis->angle -= FLOAT2ANGLE(ang); } vis->vx = viewx; diff --git a/src/s_sound.cpp b/src/s_sound.cpp index 4c60f62a3..6baaa5c65 100644 --- a/src/s_sound.cpp +++ b/src/s_sound.cpp @@ -1953,7 +1953,7 @@ static void S_SetListener(SoundListener &listener, AActor *listenactor) { if (listenactor != NULL) { - listener.angle = (float)(listenactor->angle) * ((float)PI / 2147483648.f); + listener.angle = ANGLE2RADF(listenactor->angle); /* listener.velocity.X = listenactor->velx * (TICRATE/65536.f); listener.velocity.Y = listenactor->velz * (TICRATE/65536.f); diff --git a/src/tables.h b/src/tables.h index dbe9af0c1..287e5465d 100644 --- a/src/tables.h +++ b/src/tables.h @@ -108,13 +108,4 @@ inline angle_t absangle(angle_t a) // without additional checking. extern angle_t tantoangle[SLOPERANGE+1]; -inline double bam2rad(angle_t ang) -{ - return double(ang >> 1) * (PI / ANGLE_90); -} -inline angle_t rad2bam(double ang) -{ - return angle_t(ang * (double(1<<30) / PI)) << 1; -} - #endif // __TABLES_H__ diff --git a/src/zscript/vm.h b/src/zscript/vm.h index 1fc884ffb..69cbe9d8d 100644 --- a/src/zscript/vm.h +++ b/src/zscript/vm.h @@ -892,7 +892,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_COLOR_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_INT); PalEntry x; x.d = param[p].i; #define PARAM_FLOAT_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); double x = param[p].f; #define PARAM_FIXED_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); fixed_t x = FLOAT2FIXED(param[p].f); -#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); angle_t x = angle_t(int(param[p].f * (ANGLE_90 / 90.0))); +#define PARAM_ANGLE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_FLOAT); angle_t x = FLOAT2ANGLE(param[p].f); #define PARAM_STRING_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_STRING); FString x = param[p].s(); #define PARAM_STATE_AT(p,x) assert((p) < numparam); assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); FState *x = (FState *)param[p].a; #define PARAM_POINTER_AT(p,x,type) assert((p) < numparam); assert(param[p].Type == REGT_POINTER); type *x = (type *)param[p].a; @@ -910,7 +910,7 @@ void VMDisasm(FILE *out, const VMOP *code, int codesize, const VMScriptFunction #define PARAM_COLOR_OPT_AT(p,x) PalEntry x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_INT); x.d = param[p].i; } else #define PARAM_FLOAT_OPT_AT(p,x) double x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = param[p].f; } else #define PARAM_FIXED_OPT_AT(p,x) fixed_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2FIXED(param[p].f); } else -#define PARAM_ANGLE_OPT_AT(p,x) angle_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = angle_t(int(param[p].f * (ANGLE_90 / 90.0))); } else +#define PARAM_ANGLE_OPT_AT(p,x) angle_t x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_FLOAT); x = FLOAT2ANGLE(param[p].f); } else #define PARAM_STRING_OPT_AT(p,x) FString x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_STRING); x = param[p].s(); } else #define PARAM_STATE_OPT_AT(p,x) FState *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER && (param[p].atag == ATAG_STATE || param[p].a == NULL)); x = (FState *)param[p].a; } else #define PARAM_POINTER_OPT_AT(p,x,type) type *x; if ((p) < numparam && param[p].Type != REGT_NIL) { assert(param[p].Type == REGT_POINTER); x = (type *)param[p].a; } else diff --git a/src/zscript/vmexec.cpp b/src/zscript/vmexec.cpp index ceecf5e01..7185f784d 100644 --- a/src/zscript/vmexec.cpp +++ b/src/zscript/vmexec.cpp @@ -1,5 +1,6 @@ #include #include "vm.h" +#include "xs_Float.h" #define IMPLEMENT_VMEXEC diff --git a/src/zscript/vmexec.h b/src/zscript/vmexec.h index 01c0e28de..30369baf4 100644 --- a/src/zscript/vmexec.h +++ b/src/zscript/vmexec.h @@ -339,14 +339,13 @@ begin: OP(SANG): ASSERTA(a); ASSERTF(B); ASSERTKD(C); GETADDR(PA,KC,X_WRITE_NIL); - *(VM_UWORD *)ptr = (VM_UWORD)(reg.f[B] * ((1<<30) / 180.0)) << 1; // deg -> BAM + *(VM_UWORD *)ptr = (VM_UWORD)(xs_CRoundToInt((reg.f[B]) * (0x40000000/90.))); // deg -> BAM NEXTOP; OP(SANG_R): ASSERTA(a); ASSERTF(B); ASSERTD(C); GETADDR(PA,RC,X_WRITE_NIL); - *(VM_UWORD *)ptr = (VM_UWORD)(reg.f[B] * ((1<<30) / 180.0)) << 1; + *(VM_UWORD *)ptr = (VM_UWORD)(xs_CRoundToInt((reg.f[B]) * (0x40000000/90.))); NEXTOP; - OP(SBIT): ASSERTA(a); ASSERTD(B); GETADDR(PA,0,X_WRITE_NIL);