- buildhoriz: Implementation of pitch and BAM conversion code.

* Determined maximum horizon able to be handed by engine in Q16.16 format is 280039127.
* Re-did pitch math to work on this known maximum and standardised pitch around -90/90 degrees as it should be.
* Because pitch is now -90/90 and not ~-188/188, m_sensitivity_y probably requires re-scaling.
This commit is contained in:
Mitchell Richters 2020-10-07 07:34:20 +11:00
parent 90e711464a
commit 082336e5f8
4 changed files with 41 additions and 12 deletions

View file

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

View file

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

View file

@ -12,6 +12,7 @@
#include "i_time.h"
#include "palentry.h"
#include "pragmas.h"
#include "binaryangle.h"
extern FString currentGame;
extern FString LumpFilter;

View file

@ -19,7 +19,6 @@
#include "rts.h"
#include "sounds.h"
#include "soundefs.h"
#include "binaryangle.h"
BEGIN_DUKE_NS