diff --git a/source/core/binaryangle.h b/source/core/binaryangle.h index 1986f2d83..da35af869 100644 --- a/source/core/binaryangle.h +++ b/source/core/binaryangle.h @@ -136,22 +136,49 @@ public: }; +//--------------------------------------------------------------------------- +// +// Constants and functions for use with fixedhoriz and friendly functions. +// +//--------------------------------------------------------------------------- + +// 280039127 is the maximum horizon in Q16.16 the engine will handle before wrapping around. +constexpr double horizDiff = 280039127 * 3. / 100.; + +// Degrees needed to convert horizAngle into pitch degrees. +constexpr double horizDegrees = 183.503609961216825; + +// Ratio to convert inverse tangent to -90/90 degrees of pitch. +constexpr double horizRatio = horizDegrees / pi::pi(); + +// Horizon conversion functions. +inline double HorizToPitch(double horiz) { return atan2(horiz, horizDiff / 65536.) * horizRatio; } +inline double HorizToPitch(fixed_t q16horiz) { return atan2(q16horiz, horizDiff) * horizRatio; } +inline fixed_t PitchToHoriz(double horizAngle) { return xs_CRoundToInt(horizDiff * tan(horizAngle * (pi::pi() / horizDegrees))); } +inline int32_t PitchToBAM(double horizAngle) { return xs_CRoundToInt(clamp(horizAngle * (1073741823.5 / 45.), -INT32_MAX, INT32_MAX)); } +inline constexpr double BAMToPitch(int32_t bam) { return bam * (45. / 1073741823.5); } + + class fixedhoriz { - int value; + fixed_t value; - constexpr fixedhoriz(int v) : value(v) {} + constexpr fixedhoriz(fixed_t v) : value(v) {} - friend constexpr fixedhoriz q16horiz(int v); + friend constexpr fixedhoriz q16horiz(fixed_t v); friend constexpr fixedhoriz buildhoriz(int v); + friend fixedhoriz pitchhoriz(double v); + friend fixedhoriz bamhoriz(int32_t v); public: fixedhoriz() = default; fixedhoriz(const fixedhoriz &other) = default; // This class intentionally makes no allowances for implicit type conversions because those would render it ineffective. - short asbuild() const { return FixedToInt(value); } + constexpr short asbuild() const { return FixedToInt(value); } constexpr fixed_t asq16() const { return value; } + double aspitch() const { return HorizToPitch(value); } + int32_t asbam() const { return PitchToBAM(aspitch()); } bool operator< (fixedhoriz other) const { @@ -218,6 +245,8 @@ inline constexpr binangle buildang(unsigned int v) { return binangle(v << 21); } inline binangle radang(double v) { return binangle(xs_CRoundToUInt(v * (0x80000000u / binangle::pi()))); } inline binangle degang(double v) { return binangle(xs_CRoundToUInt(v * (0x40000000 / 90.))); } -inline constexpr fixedhoriz q16horiz(int v) { return fixedhoriz(v); } +inline constexpr fixedhoriz q16horiz(fixed_t v) { return fixedhoriz(v); } inline constexpr fixedhoriz buildhoriz(int v) { return fixedhoriz(IntToFixed(v)); } +inline fixedhoriz pitchhoriz(double v) { return fixedhoriz(PitchToHoriz(v)); } +inline fixedhoriz bamhoriz(int32_t v) { return pitchhoriz(BAMToPitch(v)); } diff --git a/source/core/gamecontrol.cpp b/source/core/gamecontrol.cpp index 259482c44..bc7d45163 100644 --- a/source/core/gamecontrol.cpp +++ b/source/core/gamecontrol.cpp @@ -1571,7 +1571,7 @@ void processMovement(InputPacket* currInput, InputPacket* inputBuffer, ControlIn void sethorizon(fixed_t* q16horiz, fixed_t const q16horz, ESyncBits* actions, double const scaleAdjust) { // Calculate adjustment as true pitch (Fixed point math really sucks...) - double horizAngle = atan2(*q16horiz, IntToFixed(128)) * (512. / pi::pi()); + double horizAngle = HorizToPitch(*q16horiz); if (q16horz) { @@ -1583,7 +1583,7 @@ void sethorizon(fixed_t* q16horiz, fixed_t const q16horz, ESyncBits* actions, do if (*actions & (SB_AIM_UP|SB_AIM_DOWN)) { *actions &= ~SB_CENTERVIEW; - double const amount = 250. / GameTicRate; + double const amount = HorizToPitch(250. / GameTicRate); if (*actions & SB_AIM_DOWN) horizAngle -= scaleAdjust * amount; @@ -1596,7 +1596,7 @@ void sethorizon(fixed_t* q16horiz, fixed_t const q16horz, ESyncBits* actions, do if (*actions & (SB_LOOK_UP|SB_LOOK_DOWN)) { *actions |= SB_CENTERVIEW; - double const amount = 500. / GameTicRate; + double const amount = HorizToPitch(500. / GameTicRate); if (*actions & SB_LOOK_DOWN) horizAngle -= scaleAdjust * amount; @@ -1606,12 +1606,12 @@ void sethorizon(fixed_t* q16horiz, fixed_t const q16horz, ESyncBits* actions, do } // clamp horizAngle after processing - horizAngle = clamp(horizAngle, -180, 180); + horizAngle = clamp(horizAngle, -90, 90); // return to center if conditions met. if ((*actions & SB_CENTERVIEW) && !(*actions & (SB_LOOK_UP|SB_LOOK_DOWN))) { - if (abs(horizAngle) > 0.275) + if (abs(horizAngle) > 0.1375) { // move horizAngle back to 0 horizAngle += -scaleAdjust * horizAngle * (9. / GameTicRate); @@ -1625,7 +1625,7 @@ void sethorizon(fixed_t* q16horiz, fixed_t const q16horz, ESyncBits* actions, do } // clamp before returning - *q16horiz = clamp(xs_CRoundToInt(IntToFixed(128) * tan(horizAngle * (pi::pi() / 512.))), gi->playerHorizMin(), gi->playerHorizMax()); + *q16horiz = clamp(PitchToHoriz(horizAngle), gi->playerHorizMin(), gi->playerHorizMax()); } //--------------------------------------------------------------------------- diff --git a/source/core/gamecontrol.h b/source/core/gamecontrol.h index db8b0d09d..ee33ee238 100644 --- a/source/core/gamecontrol.h +++ b/source/core/gamecontrol.h @@ -12,6 +12,7 @@ #include "i_time.h" #include "palentry.h" #include "pragmas.h" +#include "binaryangle.h" extern FString currentGame; extern FString LumpFilter; diff --git a/source/games/duke/src/duke3d.h b/source/games/duke/src/duke3d.h index b918d7823..b8012f67b 100644 --- a/source/games/duke/src/duke3d.h +++ b/source/games/duke/src/duke3d.h @@ -19,7 +19,6 @@ #include "rts.h" #include "sounds.h" #include "soundefs.h" -#include "binaryangle.h" BEGIN_DUKE_NS