From 9843f16cc09328d2f871bb484cc6ef65dda8893a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Thu, 10 Mar 2016 22:36:28 +0100 Subject: [PATCH] - some rework of vectors.h, mostly to remove all those silenced double->float conversions. --- src/doomtype.h | 8 +- src/m_joy.cpp | 1 + src/oplsynth/mlopl_io.cpp | 3 +- src/v_video.h | 1 + src/vectors.h | 180 +++++++++++++++++++------------------- src/zscript/zcc_expr.cpp | 1 + 6 files changed, 100 insertions(+), 94 deletions(-) diff --git a/src/doomtype.h b/src/doomtype.h index 22a4d6ffd..decf256b3 100644 --- a/src/doomtype.h +++ b/src/doomtype.h @@ -44,7 +44,6 @@ #include "tarray.h" #include "name.h" #include "zstring.h" -#include "vectors.h" class PClassActor; typedef TMap FClassMap; @@ -240,10 +239,13 @@ enum ESSType SS_BGRA }; -#ifndef M_PI -#define M_PI 3.14159265358979323846 // matches value in gcc v2 math.h +// always use our own definition for consistency. +#ifdef M_PI +#undef M_PI #endif +const double M_PI = 3.14159265358979323846; // matches value in gcc v2 math.h + template char ( &_ArraySizeHelper( T (&array)[N] ))[N]; diff --git a/src/m_joy.cpp b/src/m_joy.cpp index d2a067846..46c0b9006 100644 --- a/src/m_joy.cpp +++ b/src/m_joy.cpp @@ -1,5 +1,6 @@ // HEADER FILES ------------------------------------------------------------ +#include #include "m_joy.h" #include "gameconfigfile.h" #include "d_event.h" diff --git a/src/oplsynth/mlopl_io.cpp b/src/oplsynth/mlopl_io.cpp index 64c4ad962..e6ed3bba8 100644 --- a/src/oplsynth/mlopl_io.cpp +++ b/src/oplsynth/mlopl_io.cpp @@ -37,6 +37,7 @@ * Cleaned up the source */ +#include #ifdef _WIN32 #include #include @@ -45,7 +46,7 @@ #include "opl.h" #include "c_cvars.h" -#define HALF_PI (PI*0.5) +const double HALF_PI = (M_PI*0.5); EXTERN_CVAR(Int, opl_core) extern int current_opl_core; diff --git a/src/v_video.h b/src/v_video.h index 7e0b09258..c94e6ec76 100644 --- a/src/v_video.h +++ b/src/v_video.h @@ -35,6 +35,7 @@ #define __V_VIDEO_H__ #include "doomtype.h" +#include "vectors.h" #include "doomdef.h" #include "dobject.h" diff --git a/src/vectors.h b/src/vectors.h index 87db3461e..ecd37e5a7 100644 --- a/src/vectors.h +++ b/src/vectors.h @@ -42,16 +42,14 @@ #include #include +#include "m_fixed.h" -#ifndef PI -#define PI 3.14159265358979323846 // matches value in gcc v2 math.h -#endif #define EQUAL_EPSILON (1/65536.f) -#define DEG2RAD(d) ((d)*PI/180.f) -#define RAD2DEG(r) ((r)*180.f/PI) +//#define DEG2RAD(d) ((d)*M_PI/180.) +//#define RAD2DEG(r) ((r)*180./M_PI) template struct TVector3; template struct TRotator; @@ -66,8 +64,8 @@ struct TVector2 { } - TVector2 (double a, double b) - : X(vec_t(a)), Y(vec_t(b)) + TVector2 (vec_t a, vec_t b) + : X(a), Y(b) { } @@ -81,6 +79,9 @@ struct TVector2 { } + TVector2(const TRotator &rot); + + void Zero() { Y = X = 0; @@ -102,12 +103,12 @@ struct TVector2 // Access X and Y as an array vec_t &operator[] (int index) { - return *(&X + index); + return index == 0 ? X : Y; } const vec_t &operator[] (int index) const { - return *(&X + index); + return index == 0 ? X : Y; } // Test for equality @@ -147,53 +148,53 @@ struct TVector2 return *this; } - friend TVector2 operator+ (const TVector2 &v, double scalar) + friend TVector2 operator+ (const TVector2 &v, vec_t scalar) { return TVector2(v.X + scalar, v.Y + scalar); } - friend TVector2 operator+ (double scalar, const TVector2 &v) + friend TVector2 operator+ (vec_t scalar, const TVector2 &v) { return TVector2(v.X + scalar, v.Y + scalar); } // Scalar subtraction - TVector2 &operator-= (double scalar) + TVector2 &operator-= (vec_t scalar) { X -= scalar, Y -= scalar; return *this; } - TVector2 operator- (double scalar) const + TVector2 operator- (vec_t scalar) const { return TVector2(X - scalar, Y - scalar); } // Scalar multiplication - TVector2 &operator*= (double scalar) + TVector2 &operator*= (vec_t scalar) { X *= scalar, Y *= scalar; return *this; } - friend TVector2 operator* (const TVector2 &v, double scalar) + friend TVector2 operator* (const TVector2 &v, vec_t scalar) { return TVector2(v.X * scalar, v.Y * scalar); } - friend TVector2 operator* (double scalar, const TVector2 &v) + friend TVector2 operator* (vec_t scalar, const TVector2 &v) { return TVector2(v.X * scalar, v.Y * scalar); } // Scalar division - TVector2 &operator/= (double scalar) + TVector2 &operator/= (vec_t scalar) { scalar = 1 / scalar, X *= scalar, Y *= scalar; return *this; } - TVector2 operator/ (double scalar) const + TVector2 operator/ (vec_t scalar) const { scalar = 1 / scalar; return TVector2(X * scalar, Y * scalar); @@ -224,12 +225,12 @@ struct TVector2 } // Vector length - double Length() const + vec_t Length() const { - return sqrt (X*X + Y*Y); + return (vec_t)sqrt (X*X + Y*Y); } - double LengthSquared() const + vec_t LengthSquared() const { return X*X + Y*Y; } @@ -237,15 +238,15 @@ struct TVector2 // Return a unit vector facing the same direction as this one TVector2 Unit() const { - double len = Length(); + vec_t len = Length(); if (len != 0) len = 1 / len; return *this * len; } // Scales this vector into a unit vector. Returns the old length - double MakeUnit() + vec_t MakeUnit() { - double len, ilen; + vec_t len, ilen; len = ilen = Length(); if (ilen != 0) ilen = 1 / ilen; *this *= ilen; @@ -296,8 +297,8 @@ struct TVector3 { } - TVector3 (double a, double b, double c) - : X(vec_t(a)), Y(vec_t(b)), Z(vec_t(c)) + TVector3 (vec_t a, vec_t b, vec_t c) + : X(a), Y(b), Z(c) { } @@ -306,7 +307,7 @@ struct TVector3 { } - TVector3 (const Vector2 &xy, double z) + TVector3 (const Vector2 &xy, vec_t z) : X(xy.X), Y(xy.Y), Z(z) { } @@ -327,12 +328,12 @@ struct TVector3 // Access X and Y and Z as an array vec_t &operator[] (int index) { - return *(&X + index); + return index == 0 ? X : index == 1 ? Y : Z; } const vec_t &operator[] (int index) const { - return *(&X + index); + return index == 0 ? X : index == 1 ? Y : Z; } // Test for equality @@ -366,59 +367,59 @@ struct TVector3 } // Scalar addition - TVector3 &operator+= (double scalar) + TVector3 &operator+= (vec_t scalar) { X += scalar, Y += scalar, Z += scalar; return *this; } - friend TVector3 operator+ (const TVector3 &v, double scalar) + friend TVector3 operator+ (const TVector3 &v, vec_t scalar) { return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); } - friend TVector3 operator+ (double scalar, const TVector3 &v) + friend TVector3 operator+ (vec_t scalar, const TVector3 &v) { return TVector3(v.X + scalar, v.Y + scalar, v.Z + scalar); } // Scalar subtraction - TVector3 &operator-= (double scalar) + TVector3 &operator-= (vec_t scalar) { X -= scalar, Y -= scalar, Z -= scalar; return *this; } - TVector3 operator- (double scalar) const + TVector3 operator- (vec_t scalar) const { return TVector3(X - scalar, Y - scalar, Z - scalar); } // Scalar multiplication - TVector3 &operator*= (double scalar) + TVector3 &operator*= (vec_t scalar) { X = vec_t(X *scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); return *this; } - friend TVector3 operator* (const TVector3 &v, double scalar) + friend TVector3 operator* (const TVector3 &v, vec_t scalar) { return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); } - friend TVector3 operator* (double scalar, const TVector3 &v) + friend TVector3 operator* (vec_t scalar, const TVector3 &v) { return TVector3(v.X * scalar, v.Y * scalar, v.Z * scalar); } // Scalar division - TVector3 &operator/= (double scalar) + TVector3 &operator/= (vec_t scalar) { scalar = 1 / scalar, X = vec_t(X * scalar), Y = vec_t(Y * scalar), Z = vec_t(Z * scalar); return *this; } - TVector3 operator/ (double scalar) const + TVector3 operator/ (vec_t scalar) const { scalar = 1 / scalar; return TVector3(X * scalar, Y * scalar, Z * scalar); @@ -754,16 +755,11 @@ struct TAngle { } - TAngle (float amt) + TAngle (vec_t amt) : Degrees(amt) { } - TAngle (double amt) - : Degrees(vec_t(amt)) - { - } - TAngle (int amt) : Degrees(vec_t(amt)) { @@ -786,8 +782,7 @@ struct TAngle return *this; } - operator float() const { return Degrees; } - operator double() const { return Degrees; } + operator vec_t() const { return Degrees; } TAngle operator- () const { @@ -838,53 +833,53 @@ struct TAngle return Degrees / other.Degrees; } - TAngle &operator+= (double other) + TAngle &operator+= (vec_t other) { - Degrees = vec_t(Degrees + other); + Degrees = Degrees + other; return *this; } - TAngle &operator-= (double other) + TAngle &operator-= (vec_t other) { - Degrees = vec_t(Degrees - other); + Degrees = Degrees - other; return *this; } - TAngle &operator*= (double other) + TAngle &operator*= (vec_t other) { - Degrees = vec_t(Degrees * other); + Degrees = Degrees * other; return *this; } - TAngle &operator/= (double other) + TAngle &operator/= (vec_t other) { - Degrees = vec_t(Degrees / other); + Degrees = Degrees / other; return *this; } - TAngle operator+ (double other) const + TAngle operator+ (vec_t other) const { return Degrees + other; } - TAngle operator- (double other) const + TAngle operator- (vec_t other) const { return Degrees - other; } - friend TAngle operator- (double o1, TAngle o2) + friend TAngle operator- (vec_t o1, TAngle o2) { return TAngle(o1 - o2.Degrees); } - TAngle operator* (double other) const + TAngle operator* (vec_t other) const { - return Degrees * vec_t(other); + return Degrees * other; } - TAngle operator/ (double other) const + TAngle operator/ (vec_t other) const { - return Degrees / vec_t(other); + return Degrees / other; } // Should the comparisons consider an epsilon value? @@ -918,32 +913,32 @@ struct TAngle return Degrees != other.Degrees; } - bool operator< (double other) const + bool operator< (vec_t other) const { return Degrees < other; } - bool operator> (double other) const + bool operator> (vec_t other) const { return Degrees > other; } - bool operator<= (double other) const + bool operator<= (vec_t other) const { return Degrees <= other; } - bool operator>= (double other) const + bool operator>= (vec_t other) const { return Degrees >= other; } - bool operator== (double other) const + bool operator== (vec_t other) const { return Degrees == other; } - bool operator!= (double other) const + bool operator!= (vec_t other) const { return Degrees != other; } @@ -951,49 +946,47 @@ struct TAngle // Ensure the angle is between [0.0,360.0) degrees TAngle &Normalize360() { - // Normalizing the angle converts it to a BAM, masks it, and converts it back to a float. - - // This could have been kept entirely in floating point using fmod(), but the MSVCRT has lots - // of overhead for that function, despite the x87 offering the FPREM instruction which does - // exactly what fmod() is supposed to do. So fmod ends up being an order of magnitude slower - // than casting to and from an int. - - // Casting Degrees to a volatile ensures that the compiler will not try to evaluate an expression - // such as "TAngle a(360*100+24); a.Normalize360();" at compile time. Normally, it would see that - // this expression is constant and attempt to remove the Normalize360() call entirely and store - // the result of the function in the TAngle directly. Unfortunately, it does not do the casting - // properly and will overflow, producing an incorrect result. So we need to make sure it always - // evaluates Normalize360 at run time and never at compile time. (This applies to VC++. I don't - // know if other compilers suffer similarly). - Degrees = vec_t((int(*(volatile vec_t *)&Degrees * ((1<<30)/360.0)) & ((1<<30)-1)) * (360.f/(1<<30))); + // Normalizing the angle converts it to a BAM, which masks it, and converts it back to a float. + // Note: We MUST use xs_Float here because it is the only method that guarantees reliable wraparound. + Degrees = (vec_t)ANGLE2DBL((unsigned int)FLOAT2ANGLE(Degrees)); return *this; } // Ensures the angle is between (-180.0,180.0] degrees TAngle &Normalize180() { - Degrees = vec_t((((int(*(volatile vec_t *)&Degrees * ((1<<30)/360.0))+(1<<29)-1) & ((1<<30)-1)) - (1<<29)+1) * (360.f/(1<<30))); + Degrees = (vec_t)ANGLE2DBL((signed int)FLOAT2ANGLE(Degrees)); return *this; } // Like Normalize360(), except the integer value is not converted back to a float. // The steps parameter must be a power of 2. - int Quantize(int steps) + int Quantize(int steps) const { - return int(*(volatile vec_t *)&Degrees * (steps/360.0)) & (steps-1); + return xs_CRoundToInt((Degrees * (steps/360.0)) & (steps-1)); + } + + vec_t Radians() const + { + return Degrees * (M_PI / 180.0); + } + + unsigned BAM() const + { + return FLOAT2ANGLE(Degrees); } }; template inline double ToRadians (const TAngle °) { - return double(deg.Degrees * (PI / 180.0)); + return double(deg.Degrees * (M_PI / 180.0)); } template inline TAngle ToDegrees (double rad) { - return TAngle (double(rad * (180.0 / PI))); + return TAngle (T(rad * (180.0 / M_PI))); } template @@ -1023,13 +1016,13 @@ inline TAngle fabs (const TAngle °) template inline TAngle vectoyaw (const TVector2 &vec) { - return atan2(vec.Y, vec.X) * (180.0 / PI); + return (vec_t)atan2(vec.Y, vec.X) * (180.0 / M_PI); } template inline TAngle vectoyaw (const TVector3 &vec) { - return atan2(vec.Y, vec.X) * (180.0 / PI); + return (vec_t)atan2(vec.Y, vec.X) * (180.0 / M_PI); } // Much of this is copied from TVector3. Is all that functionality really appropriate? @@ -1203,6 +1196,13 @@ inline TVector3::TVector3 (const TRotator &rot) { } +template +inline TVector2::TVector2(const TRotator &rot) + : X(cos(rot.Yaw)), Y(sin(rot.Yaw)) +{ +} + + template inline TMatrix3x3::TMatrix3x3(const TVector3 &axis, TAngle degrees) { diff --git a/src/zscript/zcc_expr.cpp b/src/zscript/zcc_expr.cpp index 644a122a5..0cd399d64 100644 --- a/src/zscript/zcc_expr.cpp +++ b/src/zscript/zcc_expr.cpp @@ -1,3 +1,4 @@ +#include #include "dobject.h" #include "sc_man.h" #include "c_console.h"