- 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
This commit is contained in:
Christoph Oelckers 2016-02-08 12:10:53 +01:00
parent 7b42093dc9
commit 6d0ef7a9da
18 changed files with 58 additions and 46 deletions

View file

@ -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);
}
}

View file

@ -894,7 +894,7 @@ void ReadCompatibleUserInfo(FArchive &arc, userinfo_t &info)
*static_cast<FStringCVar *>(info[NAME_Name]) = netname;
*static_cast<FIntCVar *>(info[NAME_Team]) = team;
*static_cast<FFloatCVar *>(info[NAME_Autoaim]) = (float)aimdist / ANGLE_1;
*static_cast<FFloatCVar *>(info[NAME_Autoaim]) = ANGLE2FLOAT(aimdist);
*static_cast<FIntCVar *>(info[NAME_Skin]) = skin;
*static_cast<FIntCVar *>(info[NAME_Gender]) = gender;
*static_cast<FBoolCVar *>(info[NAME_NeverSwitchOnPickup]) = neverswitch;

View file

@ -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"))
{

View file

@ -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;
}

View file

@ -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; }

View file

@ -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<AActor> 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;

View file

@ -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;

View file

@ -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

View file

@ -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)
{

View file

@ -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)

View file

@ -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"))
{

View file

@ -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;

View file

@ -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;

View file

@ -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);

View file

@ -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__

View file

@ -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

View file

@ -1,5 +1,6 @@
#include <math.h>
#include "vm.h"
#include "xs_Float.h"
#define IMPLEMENT_VMEXEC

View file

@ -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);