Merge pull request 'Clean up Controller Sensors code, Gyro calibration, Gyro cameras' (#234) from gyrostuff into next
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/234
This commit is contained in:
commit
782f3b6184
13 changed files with 478 additions and 298 deletions
|
|
@ -5102,8 +5102,9 @@ static boolean CheckForSpeedHacks(UINT8 p)
|
|||
{
|
||||
if (netcmds[maketic%BACKUPTICS][p].forwardmove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].forwardmove < -MAXPLMOVE
|
||||
|| netcmds[maketic%BACKUPTICS][p].sidemove > MAXPLMOVE || netcmds[maketic%BACKUPTICS][p].sidemove < -MAXPLMOVE
|
||||
|| netcmds[maketic%BACKUPTICS][p].throwdir > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].throwdir < -KART_FULLTURN
|
||||
|| netcmds[maketic%BACKUPTICS][p].turning > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].turning < -KART_FULLTURN
|
||||
|| netcmds[maketic%BACKUPTICS][p].throwdir > KART_FULLTURN || netcmds[maketic%BACKUPTICS][p].throwdir < -KART_FULLTURN)
|
||||
)
|
||||
{
|
||||
CONS_Alert(CONS_WARNING, M_GetText("Illegal movement value received from node %d\n"), playernode[p]);
|
||||
//D_Clearticcmd(k);
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@
|
|||
#define ASSET_HASH_TEXTURES_KART 0xb4211b2f32b6a291
|
||||
#define ASSET_HASH_CHARS_KART 0x1e68a3e01aa5c68b
|
||||
#define ASSET_HASH_MAPS_KART 0x38558ed00da41ce9
|
||||
#define ASSET_HASH_MAIN_PK3 0xa83b5f0cfc1ffd7b
|
||||
#define ASSET_HASH_MAIN_PK3 0x5bb203462b8eb19b
|
||||
#define ASSET_HASH_MAPPATCH_PK3 0x1745690024efbaf8
|
||||
#define ASSET_HASH_BONUSCHARS_KART 0x60e6f13d822a7461
|
||||
#ifdef USE_PATCH_FILE
|
||||
|
|
|
|||
|
|
@ -64,11 +64,11 @@ typedef enum
|
|||
// 16 bytes long now!
|
||||
struct ticcmd_t
|
||||
{
|
||||
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50)
|
||||
SINT8 sidemove; // -MAXPLMOVE to MAXPLMOVE (50)
|
||||
INT16 turning; // Turn speed
|
||||
SINT8 forwardmove; // -MAXPLMOVE to MAXPLMOVE (50) (has anticheat)
|
||||
SINT8 sidemove; // -MAXPLMOVE to MAXPLMOVE (50) (has anticheat)
|
||||
INT16 turning; // "Steering Wheel" turn speed when driving (has anticheat)
|
||||
INT16 angle; // Predicted angle, use me if you can!
|
||||
INT16 throwdir; // Aiming direction
|
||||
INT16 throwdir; // Forwards/Backwards item use direction (has anticheat)
|
||||
INT16 aiming; // vertical aiming, see G_BuildTicCmd
|
||||
UINT16 buttons;
|
||||
UINT8 latency; // Netgames: how many tics ago was this ticcmd generated from this player's end?
|
||||
|
|
|
|||
|
|
@ -1574,6 +1574,7 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"GC_RESPAWN",gc_respawn},
|
||||
{"GC_DIRECTOR",gc_director},
|
||||
{"GC_HORNCODE",gc_horncode},
|
||||
{"GC_FREELOOK",gc_freelook},
|
||||
{"NUM_GAMECONTROLS",num_gamecontrols},
|
||||
|
||||
// screen.h constants
|
||||
|
|
|
|||
277
src/g_game.c
277
src/g_game.c
|
|
@ -51,7 +51,6 @@
|
|||
#include "m_cond.h" // condition sets
|
||||
#include "r_fps.h" // frame interpolation/uncapped
|
||||
#include "lua_hud.h"
|
||||
#include "m_easing.h"
|
||||
|
||||
// SRB2kart
|
||||
#include "k_kart.h"
|
||||
|
|
@ -1404,235 +1403,6 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect
|
|||
}
|
||||
}
|
||||
|
||||
// copy/pasted from the lua version of these routines
|
||||
inline static vector3_t *QuaternionMulVec3(vector3_t *out, vector3_t *a, vector4_t *b)
|
||||
{
|
||||
fixed_t ax = a->x, ay = a->y, az = a->z, aw = 0;
|
||||
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->a;
|
||||
|
||||
FV3_NormalizeEx(out, FV3_Load(out,
|
||||
FixedMul(aw, bx) + FixedMul(ax, bw) + FixedMul(ay, bz) - FixedMul(az, by),
|
||||
FixedMul(aw, by) - FixedMul(ax, bz) + FixedMul(ay, bw) + FixedMul(az, bx),
|
||||
FixedMul(aw, bz) + FixedMul(ax, by) - FixedMul(ay, bx) + FixedMul(az, bw)
|
||||
));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline static fixed_t FV3_LengthSquared(const vector3_t *vec)
|
||||
{
|
||||
return FixedMul(vec->x, vec->x) + FixedMul(vec->y, vec->y) + FixedMul(vec->z, vec->z);
|
||||
}
|
||||
|
||||
inline static fixed_t FV3_Length(const vector3_t *vec)
|
||||
{
|
||||
return FixedSqrt(FV3_LengthSquared(vec));
|
||||
}
|
||||
|
||||
inline static vector4_t AngleAxis(fixed_t angle, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
fixed_t sinangle = FINESINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
|
||||
fixed_t cosangle = FINECOSINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
|
||||
vector3_t axis = {x, y, z};
|
||||
vector4_t result;
|
||||
|
||||
FV3_Normalize(&axis);
|
||||
|
||||
FV4_Load(&result,
|
||||
FixedMul(axis.x, sinangle),
|
||||
FixedMul(axis.y, sinangle),
|
||||
FixedMul(axis.z, sinangle),
|
||||
cosangle
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
// math sourced from this article
|
||||
// http://gyrowiki.jibbsmart.com/blog:finding-gravity-with-sensor-fusion
|
||||
// state
|
||||
fixed_t localshakinessfac[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localsmoothedaccel[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localgravityvectors[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
// the time it takes in our acceleration smoothing for 'A' to get halfway to 'B'
|
||||
#define SmoothingHalfTime (0.01)
|
||||
// thresholds of trust for accel shakiness. less shakiness = more trust
|
||||
#define ShakinessMaxThreshold (50*FRACUNIT/100)
|
||||
#define ShakinessMinThreshold (1*FRACUNIT/100)
|
||||
// when we trust the accel a lot (the controller is "still"), how quickly do we correct our gravity vector?
|
||||
#define CorrectionStillRate (FRACUNIT)
|
||||
// when we don't trust the accel (the controller is "shaky"), how quickly do we correct our gravity vector?
|
||||
#define CorrectionShakyRate (10*FRACUNIT/100)
|
||||
// if our old gravity vector is close enough to our new one, limit further corrections to this proportion of the rotation speed
|
||||
#define CorrectionGyroFactor (40*FRACUNIT/100)
|
||||
// thresholds for what's considered "close enough"
|
||||
#define CorrectionGyroMinThreshold (5*FRACUNIT/100)
|
||||
#define CorrectionGyroMaxThreshold (FRACUNIT/4)
|
||||
// no matter what, always apply a minimum of this much correction to our gravity vector
|
||||
#define CorrectionMinimumSpeed (1*FRACUNIT/100)
|
||||
|
||||
// when holding the controller still (shaking and turning included), corrcet this quickly to resolve error
|
||||
#define CorrectionInstantRate (80*FRACUNIT/100)
|
||||
#define CorrectionInstantShake (4*FRACUNIT/100)
|
||||
#define CorrectionInstantTurn (5*FRACUNIT/100)
|
||||
|
||||
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel)
|
||||
{
|
||||
// convert gyro input to reverse rotation
|
||||
vector3_t invAccel = {-accel.x, -accel.y, -accel.z};
|
||||
fixed_t correctionRate = 0;
|
||||
// scaling is reversed, smaller time scales = larger steps in this code
|
||||
// (1/timescale)/dt
|
||||
fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE;
|
||||
// we don't have exp2 and we actually need it here to take timescale into account :(
|
||||
fixed_t smoothFactor = FloatToFixed(exp2(-FixedToFloat(deltaseconds) / SmoothingHalfTime));
|
||||
fixed_t angleRate;
|
||||
fixed_t correctionLimit;
|
||||
vector4_t invRotation = AngleAxis(
|
||||
FixedMul(FV3_Length(&gyro), deltaseconds),
|
||||
-gyro.x,
|
||||
-gyro.y,
|
||||
-gyro.z
|
||||
);
|
||||
vector3_t gravityDelta = {0};
|
||||
vector3_t gravityDeltaDirection = {0};
|
||||
vector3_t correction = {0};
|
||||
|
||||
if (!G_GetGamepadCanUseTilt(p)) return;
|
||||
CONS_Debug(DBG_IMU, "= Update Gravity Delta Time: %4.3f =\n", FixedToFloat(deltaseconds));
|
||||
|
||||
// rotate gravity vector
|
||||
QuaternionMulVec3(&localgravityvectors[p], &localgravityvectors[p], &invRotation);
|
||||
QuaternionMulVec3(&localsmoothedaccel[p], &localsmoothedaccel[p], &invRotation);
|
||||
localshakinessfac[p] = FixedMul(localshakinessfac[p], smoothFactor),
|
||||
FV3_SubEx(&accel, &localsmoothedaccel[p], &correction);
|
||||
localshakinessfac[p] = max(localshakinessfac[p], FV3_Length(&correction));
|
||||
FV3_Load(&localsmoothedaccel[p],
|
||||
Easing_Linear(smoothFactor, accel.x, localsmoothedaccel[p].x),
|
||||
Easing_Linear(smoothFactor, accel.y, localsmoothedaccel[p].y),
|
||||
Easing_Linear(smoothFactor, accel.z, localsmoothedaccel[p].z)
|
||||
);
|
||||
|
||||
CONS_Debug(DBG_IMU, "Shakiness: %4.2f\n", FixedToFloat(localshakinessfac[p]));
|
||||
|
||||
FV3_SubEx(&invAccel, &localgravityvectors[p], &gravityDelta);
|
||||
FV3_NormalizeEx(&gravityDelta, &gravityDeltaDirection);
|
||||
|
||||
if (ShakinessMaxThreshold > ShakinessMinThreshold)
|
||||
{
|
||||
fixed_t stillness = CLAMP(FixedDiv((localshakinessfac[p] - ShakinessMinThreshold), (ShakinessMaxThreshold - ShakinessMinThreshold)), 0, FRACUNIT);
|
||||
correctionRate = CorrectionStillRate + FixedMul((CorrectionShakyRate - CorrectionStillRate), stillness);
|
||||
}
|
||||
else if (localshakinessfac[p] > ShakinessMaxThreshold)
|
||||
{
|
||||
correctionRate = CorrectionShakyRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
correctionRate = CorrectionStillRate;
|
||||
}
|
||||
|
||||
// limit in proportion to rotation rate
|
||||
angleRate = FixedMul(FV3_Length(&gyro), M_PI_FIXED/180);
|
||||
correctionLimit = max(FixedMul(FixedMul(angleRate, FV3_Length(&localgravityvectors[p])), CorrectionGyroFactor), CorrectionMinimumSpeed);
|
||||
|
||||
CONS_Debug(DBG_IMU, "Angle Rate: %4.3f\n", FixedToFloat(angleRate));
|
||||
CONS_Debug(DBG_IMU, "Correction Limit: %4.3f\n", FixedToFloat(correctionLimit));
|
||||
|
||||
if (correctionRate > correctionLimit) {
|
||||
fixed_t closeEnoughFactor;
|
||||
if (CorrectionGyroMaxThreshold > CorrectionGyroMinThreshold)
|
||||
{
|
||||
closeEnoughFactor = CLAMP(FixedDiv((FV3_Length(&gravityDelta) - CorrectionGyroMinThreshold), (CorrectionGyroMaxThreshold - CorrectionGyroMinThreshold)), 0, FRACUNIT);
|
||||
}
|
||||
else if (FV3_Length(&gravityDelta) > CorrectionGyroMaxThreshold)
|
||||
{
|
||||
closeEnoughFactor = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
closeEnoughFactor = 0;
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_IMU, "'Close Enough' Fac: %4.3f\n", FixedToFloat(closeEnoughFactor));
|
||||
correctionRate = correctionLimit + FixedMul((correctionRate - correctionLimit), closeEnoughFactor);
|
||||
}
|
||||
|
||||
if (localshakinessfac[p] < CorrectionInstantShake && angleRate < CorrectionInstantTurn)
|
||||
{
|
||||
correctionRate = max(correctionRate, CorrectionInstantRate);
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_IMU, "Correction Rate: %4.2f\n", FixedToFloat(correctionRate));
|
||||
|
||||
FV3_Load(&correction,
|
||||
FixedMul(gravityDelta.x, FixedMul(deltaseconds, correctionRate)),
|
||||
FixedMul(gravityDelta.y, FixedMul(deltaseconds, correctionRate)),
|
||||
FixedMul(gravityDelta.z, FixedMul(deltaseconds, correctionRate))
|
||||
);
|
||||
if ((FV3_LengthSquared(&correction) < FV3_LengthSquared(&gravityDelta)))
|
||||
{
|
||||
FV3_Add(&localgravityvectors[p], &correction);
|
||||
}
|
||||
else
|
||||
{
|
||||
FV3_Load(&localgravityvectors[p], invAccel.x, invAccel.y, invAccel.z);
|
||||
}
|
||||
}
|
||||
|
||||
INT32 G_GetGamepadTilt(INT32 p)
|
||||
{
|
||||
fixed_t tilt;
|
||||
fixed_t curve;
|
||||
if (!G_GetGamepadCanUseTilt(p)) return 0;
|
||||
tilt = CLAMP(FixedDiv(G_GetGamepadGravity(p).x + MAXGAMEPADTILT, 2*MAXGAMEPADTILT), 0, FRACUNIT);
|
||||
CONS_Debug(DBG_IMU, "Tilt: %4.2f\n", FixedToFloat(tilt));
|
||||
|
||||
curve = FINESINE(FixedAngle(180*(tilt-FRACUNIT/2))>>ANGLETOFINESHIFT);
|
||||
CONS_Debug(DBG_IMU, "Pinched Tilt: %4.2f\n", FixedToFloat(curve));
|
||||
|
||||
return (JOYAXISRANGE * curve)/FRACUNIT;
|
||||
}
|
||||
|
||||
vector3_t G_GetGamepadGravity(INT32 p)
|
||||
{
|
||||
const vector3_t zero = {0, -ACCELEROMETERGRAVITY, 0};
|
||||
if (!G_GetGamepadCanUseTilt(p)) return zero;
|
||||
return localgravityvectors[p];
|
||||
}
|
||||
|
||||
vector3_t G_GetGamepadShake(INT32 p)
|
||||
{
|
||||
vector3_t accel = {0};
|
||||
if (!G_GetGamepadCanUseTilt(p)) return accel;
|
||||
accel = G_PlayerInputSensor(p, ACCELEROMETER);
|
||||
FV3_Add(&accel, &localgravityvectors[p]);
|
||||
|
||||
return accel;
|
||||
}
|
||||
|
||||
boolean G_GetGamepadCanUseTilt(INT32 p)
|
||||
{
|
||||
if (p >= MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
CONS_Debug(DBG_GAMELOGIC, "G_GetGamepadCanUseTilt: Invalid player ID %d\n", p);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return (I_ControllerSupportsSensorAccelerometer(p) && I_ControllerSupportsSensorGyro(p));
|
||||
}
|
||||
#undef ShakinessMaxThreshold
|
||||
#undef ShakinessMinThreshold
|
||||
#undef CorrectionStillRate
|
||||
#undef CorrectionShakyRate
|
||||
#undef CorrectionGyroFactor
|
||||
#undef CorrectionGyroMinThreshold
|
||||
#undef CorrectionGyroMaxThreshold
|
||||
#undef CorrectionMinimumSpeed
|
||||
|
||||
//
|
||||
// G_BuildTiccmd
|
||||
// Builds a ticcmd from all of the available inputs
|
||||
|
|
@ -1699,7 +1469,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
{
|
||||
vector3_t accel = G_PlayerInputSensor(forplayer, ACCELEROMETER);
|
||||
vector3_t gyro = G_PlayerInputSensor(forplayer, GYROSCOPE);
|
||||
G_UpdateGamepadGravity(forplayer, gyro, accel);
|
||||
|
||||
G_UpdateGamepadAutoCalibration(forplayer, accel, gyro,
|
||||
(menustack[0] == MN_OP_CONTROLSETUP));
|
||||
|
||||
G_UpdateGamepadGyro(forplayer, gyro);
|
||||
G_UpdateGamepadGravity(forplayer, G_GetGamepadCalibratedGyro(forplayer), accel);
|
||||
}
|
||||
|
||||
// why build a ticcmd if we're paused?
|
||||
|
|
@ -1782,10 +1557,26 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->angle -= (tspeed * KART_FULLTURN) / JOYAXISRANGE;
|
||||
side += (accelerometertilt * 4) / JOYAXISRANGE;
|
||||
|
||||
//todo: control spectator camera using the gyro
|
||||
// if (spectating)
|
||||
// {
|
||||
// }
|
||||
//control spectator camera using the gyro
|
||||
// player space gyro from http://gyrowiki.jibbsmart.com/blog:player-space-gyro-and-alternatives-explained
|
||||
if (spectating)
|
||||
{
|
||||
fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE;
|
||||
fixed_t yawRelaxFactor = 141*FRACUNIT/100;
|
||||
vector3_t gyro = G_GetGamepadCalibratedGyro(forplayer);
|
||||
vector3_t gravnorm = G_GetGamepadGravity(forplayer);
|
||||
vector2_t gyroYZ = {gyro.y, gyro.z};
|
||||
|
||||
// use world yaw for yaw direction, local combined yaw for magnitude
|
||||
FV3_Normalize(&gravnorm);
|
||||
fixed_t worldYaw = FixedMul(gyro.y, gravnorm.y) + FixedMul(gyro.z, gravnorm.z); // dot product but just yaw and roll
|
||||
|
||||
fixed_t yaw = intsign(worldYaw) * (encoremode ? -1 : 1) *
|
||||
min(FixedMul(-abs(worldYaw), yawRelaxFactor), FV2_Magnitude(&gyroYZ));
|
||||
|
||||
cmd->angle -= FixedMul(yaw, deltaseconds*180)/FRACUNIT;
|
||||
cmd->aiming -= FixedMul(gyro.x, deltaseconds*180)/FRACUNIT;
|
||||
}
|
||||
}
|
||||
else if (joystickvector.xaxis != 0)
|
||||
{
|
||||
|
|
@ -1798,7 +1589,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
if (spectating)
|
||||
{
|
||||
INT32 mousex = gamekeydown[0][KEY_MOUSEMOVE+3] - gamekeydown[0][KEY_MOUSEMOVE+2];
|
||||
cmd->turning -= (mousex * 8) * (encoremode ? -1 : 1);
|
||||
cmd->angle -= (mousex * 8) * (encoremode ? -1 : 1);
|
||||
}
|
||||
|
||||
|
|
@ -1977,11 +1767,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
cmd->turning = KART_FULLTURN;
|
||||
else if (cmd->turning < -KART_FULLTURN)
|
||||
cmd->turning = -KART_FULLTURN;
|
||||
|
||||
if (cmd->angle > KART_FULLTURN)
|
||||
cmd->angle = KART_FULLTURN;
|
||||
else if (cmd->angle < -KART_FULLTURN)
|
||||
cmd->angle = -KART_FULLTURN;
|
||||
|
||||
if (!spectating)
|
||||
{
|
||||
if (cmd->angle > KART_FULLTURN)
|
||||
cmd->angle = KART_FULLTURN;
|
||||
else if (cmd->angle < -KART_FULLTURN)
|
||||
cmd->angle = -KART_FULLTURN;
|
||||
}
|
||||
|
||||
if (cmd->throwdir > KART_FULLTURN)
|
||||
cmd->throwdir = KART_FULLTURN;
|
||||
|
|
@ -2001,8 +1794,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
|
|||
if (abs(tilt) > MAXGAMEPADTILT)
|
||||
cmd->flags |= TICCMD_EXCESSTILT;
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_IMU, "Shake: %4.2f\n", FixedToFloat(FV3_Length(&shake)));
|
||||
//cmd->shake = CLAMP((GAMEPADSHAKETHRESHOLD*FV3_Length(&shake))/FRACUNIT, 0, UINT8_MAX);
|
||||
|
||||
//CONS_Debug(DBG_IMU, "CMD Tilt: %d, Shake: %d\n", cmd->tilt, cmd->shake);
|
||||
|
|
|
|||
28
src/g_game.h
28
src/g_game.h
|
|
@ -121,6 +121,9 @@ mapnum_t G_LevelTitleToMapNum(const char * leveltitle);
|
|||
mapnum_t G_KartMapToNative(mapnum_t mapnum);
|
||||
mapnum_t G_NativeMapToKart(mapnum_t mapnum);
|
||||
|
||||
#define GAMEPADSHAKETHRESHOLD (UINT8_MAX/2)
|
||||
#define TILTTOSTICKEASE 6
|
||||
|
||||
void G_ResetAnglePrediction(player_t *player);
|
||||
void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer);
|
||||
|
||||
|
|
@ -137,31 +140,6 @@ void G_FinalClipAimingPitch(INT32 *aiming, player_t *player, boolean skybox);
|
|||
extern angle_t localangle[MAXSPLITSCREENPLAYERS];
|
||||
extern INT32 localaiming[MAXSPLITSCREENPLAYERS]; // should be an angle_t but signed
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEADZONE_X,
|
||||
DEADZONE_Y,
|
||||
DEADZONE_BUTTON,
|
||||
} analogdeadzone_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ACCELEROMETER,
|
||||
GYROSCOPE,
|
||||
} motionsensortype_e;
|
||||
|
||||
#define MAXGAMEPADTILT (50*FRACUNIT/100)
|
||||
// #define ACCELEROMETERGRAVITY ((fixed_t)(9.80665f * ((float)FRACUNIT)))
|
||||
#define ACCELEROMETERGRAVITY 642688
|
||||
#define GAMEPADSHAKETHRESHOLD (UINT8_MAX/2)
|
||||
#define TILTTOSTICKEASE 6
|
||||
boolean G_GetGamepadCanUseTilt(INT32 p);
|
||||
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
|
||||
INT32 G_GetGamepadTilt(INT32 p);
|
||||
vector3_t G_GetGamepadShake(INT32 p);
|
||||
vector3_t G_GetGamepadGravity(INT32 p);
|
||||
vector3_t G_PlayerInputSensor(UINT8 p, motionsensortype_e sensor);
|
||||
|
||||
fixed_t G_GetDeadZoneType(INT32 p, SINT8 type);
|
||||
INT32 G_PlayerInputAnalog(UINT8 p, INT32 gc, boolean digital, SINT8 type);
|
||||
boolean G_PlayerInputDown(UINT8 p, INT32 gc, boolean digital, SINT8 type);
|
||||
|
|
|
|||
344
src/g_input.c
344
src/g_input.c
|
|
@ -26,6 +26,8 @@
|
|||
#include "v_video.h"
|
||||
#include "p_local.h"
|
||||
#include "k_kart.h"
|
||||
#include "m_fixed.h"
|
||||
#include "m_easing.h"
|
||||
|
||||
#define MAXMOUSESENSITIVITY 100 // sensitivity steps
|
||||
|
||||
|
|
@ -177,6 +179,7 @@ INT32 gamecontroldefault[num_gamecontrols][MAXINPUTMAPPING] = {
|
|||
[gc_centerview ] = {KEY_END },
|
||||
[gc_camreset ] = {KEY_HOME },
|
||||
[gc_camtoggle ] = {KEY_BACKSPACE },
|
||||
[gc_freelook ] = {KEY_RCTRL },
|
||||
};
|
||||
|
||||
// lists of GC codes for selective operation
|
||||
|
|
@ -1226,3 +1229,344 @@ void Command_Setcontrol4_f(void)
|
|||
|
||||
setcontrol(3);
|
||||
}
|
||||
|
||||
// accelerometer and gyro stuff
|
||||
|
||||
// when holding the controller still (shaking and turning included), correct this quickly to resolve error
|
||||
#define GyroCalibrationRollingAvgSamples (TICRATE/2)
|
||||
#define GyroCalibrationStart (TICRATE/2)
|
||||
#define GyroCalibrationTrust (1*FRACUNIT/100)
|
||||
|
||||
boolean localgyrocalibrating[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localgyrovectors[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
tic_t localgyrocalibrationsamples[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localgyrocalibrationlastoffset[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localgyrocalibrationoffset[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
// assume the accelerometer doesn't need calibration, use this to determine if gyro can be calibrated
|
||||
vector3_t localaccelcalibrationoffset[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
fixed_t localshakinessfac[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localsmoothedaccel[MAXSPLITSCREENPLAYERS];
|
||||
vector3_t localgravityvectors[MAXSPLITSCREENPLAYERS];
|
||||
vector4_t localquaternions[MAXSPLITSCREENPLAYERS];
|
||||
|
||||
// copy/pasted from the lua version of these routines
|
||||
inline static vector3_t *QuaternionMulVec3(vector3_t *out, vector3_t *a, vector4_t *b)
|
||||
{
|
||||
fixed_t ax = a->x, ay = a->y, az = a->z, aw = 0;
|
||||
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->a;
|
||||
|
||||
FV3_NormalizeEx(out, FV3_Load(out,
|
||||
FixedMul(aw, bx) + FixedMul(ax, bw) + FixedMul(ay, bz) - FixedMul(az, by),
|
||||
FixedMul(aw, by) - FixedMul(ax, bz) + FixedMul(ay, bw) + FixedMul(az, bx),
|
||||
FixedMul(aw, bz) + FixedMul(ax, by) - FixedMul(ay, bx) + FixedMul(az, bw)
|
||||
));
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
inline static fixed_t FV3_LengthSquared(const vector3_t *vec)
|
||||
{
|
||||
return FixedMul(vec->x, vec->x) + FixedMul(vec->y, vec->y) + FixedMul(vec->z, vec->z);
|
||||
}
|
||||
|
||||
inline static vector4_t AngleAxis(fixed_t angle, fixed_t x, fixed_t y, fixed_t z)
|
||||
{
|
||||
fixed_t sinangle = FINESINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
|
||||
fixed_t cosangle = FINECOSINE(FixedAngle(angle/2) >> ANGLETOFINESHIFT);
|
||||
vector3_t axis = {x, y, z};
|
||||
vector4_t result;
|
||||
|
||||
FV3_Normalize(&axis);
|
||||
|
||||
FV4_Load(&result,
|
||||
FixedMul(axis.x, sinangle),
|
||||
FixedMul(axis.y, sinangle),
|
||||
FixedMul(axis.z, sinangle),
|
||||
cosangle
|
||||
);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
vector3_t G_GetCalibratedGyroOffset(INT32 p)
|
||||
{
|
||||
return localgyrocalibrationoffset[p];
|
||||
}
|
||||
|
||||
void G_UpdateGamepadAutoCalibration(INT32 p, vector3_t accel, vector3_t gyro, boolean allowautocalibration)
|
||||
{
|
||||
fixed_t trust = FV3_Distance(&localaccelcalibrationoffset[p], &accel);
|
||||
FV3_Load(
|
||||
&localaccelcalibrationoffset[p],
|
||||
(localaccelcalibrationoffset[p].x + accel.x)/2,
|
||||
(localaccelcalibrationoffset[p].y + accel.y)/2,
|
||||
(localaccelcalibrationoffset[p].z + accel.z)/2
|
||||
);
|
||||
|
||||
CONS_Debug(DBG_IMU, "== Gyro Update ==\n");
|
||||
CONS_Debug(DBG_IMU, "Gyro calibration safety: %4.3f\n", FixedToFloat(trust));
|
||||
if (allowautocalibration && (trust < GyroCalibrationTrust))
|
||||
{
|
||||
if (!localgyrocalibrating[p])
|
||||
{
|
||||
localgyrocalibrationsamples[p] = 0;
|
||||
FV3_Copy(&localgyrocalibrationlastoffset[p], &localgyrocalibrationoffset[p]);
|
||||
FV3_Load(
|
||||
&localgyrocalibrationoffset[p],
|
||||
0, 0, 0
|
||||
);
|
||||
localgyrocalibrating[p] = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// incomplete calibration
|
||||
if (localgyrocalibrating[p] && localgyrocalibrationsamples[p] <= (GyroCalibrationRollingAvgSamples + GyroCalibrationStart))
|
||||
{
|
||||
FV3_Copy(&localgyrocalibrationoffset[p], &localgyrocalibrationlastoffset[p]);
|
||||
localgyrocalibrationsamples[p] = 0;
|
||||
}
|
||||
localgyrocalibrating[p] = false;
|
||||
}
|
||||
}
|
||||
|
||||
void G_UpdateGamepadGyro(INT32 p, vector3_t gyro)
|
||||
{
|
||||
vector3_t offset = {0};
|
||||
|
||||
if (p >= MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
CONS_Debug(DBG_GAMELOGIC, "G_UpdateGamepadGyro: Invalid player ID %d\n", p);
|
||||
#endif
|
||||
return;
|
||||
}
|
||||
if (!I_ControllerSupportsSensorGyro(p)) return;
|
||||
|
||||
if (localgyrocalibrating[p])
|
||||
{
|
||||
localgyrocalibrationsamples[p]++;
|
||||
if (localgyrocalibrationsamples[p] > GyroCalibrationStart)
|
||||
{
|
||||
FV3_Load(
|
||||
&localgyrocalibrationoffset[p],
|
||||
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].x) + gyro.x)/GyroCalibrationRollingAvgSamples,
|
||||
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].y) + gyro.y)/GyroCalibrationRollingAvgSamples,
|
||||
(((GyroCalibrationRollingAvgSamples-1)*localgyrocalibrationoffset[p].z) + gyro.z)/GyroCalibrationRollingAvgSamples
|
||||
);
|
||||
}
|
||||
}
|
||||
CONS_Debug(DBG_IMU, "Gyro calibration samples: %d\n", localgyrocalibrationsamples[p]);
|
||||
|
||||
offset = G_GetCalibratedGyroOffset(p);
|
||||
FV3_SubEx(&gyro, &offset, &localgyrovectors[p]);
|
||||
}
|
||||
|
||||
// math sourced from this article
|
||||
// http://gyrowiki.jibbsmart.com/blog:finding-gravity-with-sensor-fusion
|
||||
|
||||
// the time it takes in our acceleration smoothing for 'A' to get halfway to 'B'
|
||||
#define SmoothingHalfTime (0.25)
|
||||
// thresholds of trust for accel shakiness. less shakiness = more trust
|
||||
#define ShakinessMaxThreshold (40*FRACUNIT/100)
|
||||
#define ShakinessMinThreshold (1*FRACUNIT/100)
|
||||
// when we trust the accel a lot (the controller is "still"), how quickly do we correct our gravity vector?
|
||||
#define CorrectionStillRate (FRACUNIT)
|
||||
// when we don't trust the accel (the controller is "shaky"), how quickly do we correct our gravity vector?
|
||||
#define CorrectionShakyRate (1*FRACUNIT/100)
|
||||
// if our old gravity vector is close enough to our new one, limit further corrections to this proportion of the rotation speed
|
||||
#define CorrectionGyroFactor (5*FRACUNIT/100)
|
||||
// thresholds for what's considered "close enough"
|
||||
#define CorrectionGyroMinThreshold (5*FRACUNIT/100)
|
||||
#define CorrectionGyroMaxThreshold (FRACUNIT/4)
|
||||
// no matter what, always apply a minimum of this much correction to our gravity vector
|
||||
#define CorrectionMinimumSpeed (1*FRACUNIT/100)
|
||||
|
||||
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel)
|
||||
{
|
||||
// convert gyro input to reverse rotation
|
||||
vector3_t invAccel = {-accel.x, -accel.y, -accel.z};
|
||||
fixed_t correctionRate = 0;
|
||||
// scaling is reversed, smaller time scales = larger steps in this code
|
||||
// (1/timescale)/dt
|
||||
fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE;
|
||||
// we don't have exp2 and we actually need it here to take timescale into account :(
|
||||
fixed_t smoothFactor = FloatToFixed(exp2(-FixedToFloat(deltaseconds) / SmoothingHalfTime));
|
||||
fixed_t angleRate = FixedMul(FV3_Magnitude(&gyro), M_PI_FIXED)/180;
|
||||
fixed_t correctionLimit;
|
||||
vector4_t invRotation = {0};
|
||||
vector3_t gravityDelta = {0};
|
||||
vector3_t gravityDeltaDirection = {0};
|
||||
vector3_t correction = {0};
|
||||
|
||||
if (!G_GetGamepadCanUseTilt(p)) return;
|
||||
CONS_Debug(DBG_IMU, "= Update Gravity Delta Time: %4.3f =\n", FixedToFloat(deltaseconds));
|
||||
|
||||
invRotation = AngleAxis(
|
||||
FixedMul(FixedMul(FV3_Magnitude(&gyro), deltaseconds), 190*FRACUNIT/100),
|
||||
-gyro.x,
|
||||
-gyro.y,
|
||||
-gyro.z
|
||||
);
|
||||
|
||||
// rotate gravity vector
|
||||
QuaternionMulVec3(&localgravityvectors[p], &localgravityvectors[p], &invRotation);
|
||||
QuaternionMulVec3(&localsmoothedaccel[p], &localsmoothedaccel[p], &invRotation);
|
||||
localshakinessfac[p] = FixedMul(localshakinessfac[p], smoothFactor),
|
||||
FV3_SubEx(&accel, &localsmoothedaccel[p], &correction);
|
||||
localshakinessfac[p] = max(localshakinessfac[p], FV3_Magnitude(&correction));
|
||||
FV3_Load(&localsmoothedaccel[p],
|
||||
Easing_Linear(smoothFactor, accel.x, localsmoothedaccel[p].x),
|
||||
Easing_Linear(smoothFactor, accel.y, localsmoothedaccel[p].y),
|
||||
Easing_Linear(smoothFactor, accel.z, localsmoothedaccel[p].z)
|
||||
);
|
||||
|
||||
CONS_Debug(DBG_IMU, "Shakiness: %4.2f\n", FixedToFloat(localshakinessfac[p]));
|
||||
|
||||
FV3_SubEx(&invAccel, &localgravityvectors[p], &gravityDelta);
|
||||
if (FV3_Magnitude(&gravityDelta) > 0)
|
||||
{
|
||||
FV3_NormalizeEx(&gravityDelta, &gravityDeltaDirection);
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_IMU, "Gravity Delta Magnitude: %4.3f\n", FixedToFloat(FV3_Magnitude(&gravityDelta)));
|
||||
|
||||
if (ShakinessMaxThreshold > ShakinessMinThreshold)
|
||||
{
|
||||
fixed_t stillness = CLAMP(FixedDiv((localshakinessfac[p] - ShakinessMinThreshold), (ShakinessMaxThreshold - ShakinessMinThreshold)), 0, FRACUNIT);
|
||||
correctionRate = CorrectionStillRate + FixedMul((CorrectionShakyRate - CorrectionStillRate), stillness);
|
||||
}
|
||||
else if (localshakinessfac[p] > ShakinessMaxThreshold)
|
||||
{
|
||||
correctionRate = CorrectionShakyRate;
|
||||
}
|
||||
else
|
||||
{
|
||||
correctionRate = CorrectionStillRate;
|
||||
}
|
||||
|
||||
// limit in proportion to rotation rate
|
||||
correctionLimit = FixedMul(angleRate, CorrectionGyroFactor);
|
||||
|
||||
CONS_Debug(DBG_IMU, "Angle Rate: %4.3f\n", FixedToFloat(angleRate));
|
||||
CONS_Debug(DBG_IMU, "Correction Limit: %4.3f\n", FixedToFloat(correctionLimit));
|
||||
|
||||
if (correctionRate > correctionLimit) {
|
||||
fixed_t closeEnoughFactor;
|
||||
if (CorrectionGyroMaxThreshold > CorrectionGyroMinThreshold)
|
||||
{
|
||||
closeEnoughFactor = CLAMP(FixedDiv((FV3_Magnitude(&gravityDelta) - CorrectionGyroMinThreshold), (CorrectionGyroMaxThreshold - CorrectionGyroMinThreshold)), 0, FRACUNIT);
|
||||
}
|
||||
else if (FV3_Magnitude(&gravityDelta) > CorrectionGyroMaxThreshold)
|
||||
{
|
||||
closeEnoughFactor = FRACUNIT;
|
||||
}
|
||||
else
|
||||
{
|
||||
closeEnoughFactor = 0;
|
||||
}
|
||||
|
||||
CONS_Debug(DBG_IMU, "'Close Enough' Fac: %4.3f\n", FixedToFloat(closeEnoughFactor));
|
||||
correctionRate = correctionLimit + FixedMul((correctionRate - correctionLimit), closeEnoughFactor);
|
||||
}
|
||||
|
||||
correctionRate = max(correctionRate, CorrectionMinimumSpeed);
|
||||
|
||||
CONS_Debug(DBG_IMU, "Correction Rate: %4.2f\n", FixedToFloat(correctionRate));
|
||||
|
||||
FV3_Load(&correction,
|
||||
FixedMul(gravityDeltaDirection.x, FixedMul(deltaseconds, correctionRate)),
|
||||
FixedMul(gravityDeltaDirection.y, FixedMul(deltaseconds, correctionRate)),
|
||||
FixedMul(gravityDeltaDirection.z, FixedMul(deltaseconds, correctionRate))
|
||||
);
|
||||
if ((FV3_LengthSquared(&correction) < FV3_LengthSquared(&gravityDelta)))
|
||||
{
|
||||
FV3_Add(&localgravityvectors[p], &correction);
|
||||
}
|
||||
else
|
||||
{
|
||||
FV3_Add(&localgravityvectors[p], &gravityDelta);
|
||||
}
|
||||
}
|
||||
|
||||
INT32 G_GetGamepadTilt(INT32 p)
|
||||
{
|
||||
fixed_t tilt;
|
||||
fixed_t curve;
|
||||
if (!G_GetGamepadCanUseTilt(p)) return 0;
|
||||
tilt = CLAMP(FixedDiv(G_GetGamepadGravity(p).x + MAXGAMEPADTILT, 2*MAXGAMEPADTILT), 0, FRACUNIT);
|
||||
CONS_Debug(DBG_IMU, "Tilt: %4.2f\n", FixedToFloat(tilt));
|
||||
|
||||
curve = FINESINE(FixedAngle(180*(tilt-FRACUNIT/2))>>ANGLETOFINESHIFT);
|
||||
CONS_Debug(DBG_IMU, "Pinched Tilt: %4.2f\n", FixedToFloat(curve));
|
||||
|
||||
return (JOYAXISRANGE * curve)/FRACUNIT;
|
||||
}
|
||||
|
||||
vector3_t G_GetGamepadGravity(INT32 p)
|
||||
{
|
||||
const vector3_t zero = {0, -ACCELEROMETERGRAVITY, 0};
|
||||
if (!G_GetGamepadCanUseTilt(p)) return zero;
|
||||
return localgravityvectors[p];
|
||||
}
|
||||
|
||||
vector3_t G_GetGamepadShake(INT32 p)
|
||||
{
|
||||
vector3_t accel = {0};
|
||||
if (!G_GetGamepadCanUseTilt(p)) return accel;
|
||||
accel = G_PlayerInputSensor(p, ACCELEROMETER);
|
||||
FV3_Add(&accel, &localgravityvectors[p]);
|
||||
|
||||
return accel;
|
||||
}
|
||||
|
||||
fixed_t G_GetGamepadShakinessFactor(INT32 p)
|
||||
{
|
||||
if (!G_GetGamepadCanUseTilt(p)) return 0;
|
||||
return localshakinessfac[p];
|
||||
}
|
||||
|
||||
vector3_t G_GetGamepadCalibratedGyro(INT32 p)
|
||||
{
|
||||
vector3_t zero = {0};
|
||||
if (p >= MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
CONS_Debug(DBG_GAMELOGIC, "G_GetGamepadGyro: Invalid player ID %d\n", p);
|
||||
#endif
|
||||
return zero;
|
||||
}
|
||||
|
||||
if (!I_ControllerSupportsSensorGyro(p)) return zero;
|
||||
|
||||
return localgyrovectors[p];
|
||||
}
|
||||
|
||||
boolean G_GetGamepadCanUseTilt(INT32 p)
|
||||
{
|
||||
if (p >= MAXSPLITSCREENPLAYERS)
|
||||
{
|
||||
#ifdef PARANOIA
|
||||
CONS_Debug(DBG_GAMELOGIC, "G_GetGamepadCanUseTilt: Invalid player ID %d\n", p);
|
||||
#endif
|
||||
return false;
|
||||
}
|
||||
|
||||
return (I_ControllerSupportsSensorAccelerometer(p) && I_ControllerSupportsSensorGyro(p));
|
||||
}
|
||||
#undef ShakinessMaxThreshold
|
||||
#undef ShakinessMinThreshold
|
||||
#undef CorrectionStillRate
|
||||
#undef CorrectionShakyRate
|
||||
#undef CorrectionGyroFactor
|
||||
#undef CorrectionGyroMinThreshold
|
||||
#undef CorrectionGyroMaxThreshold
|
||||
#undef CorrectionMinimumSpeed
|
||||
#undef SmoothingHalfTime
|
||||
|
||||
#undef GyroCalibrationTrust
|
||||
#undef GyroCalibrationStart
|
||||
#undef GyroCalibrationRollingAvgSamples
|
||||
|
|
@ -95,9 +95,23 @@ typedef enum
|
|||
gc_respawn,
|
||||
gc_director,
|
||||
gc_horncode,
|
||||
gc_freelook,
|
||||
num_gamecontrols
|
||||
} gamecontrols_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
DEADZONE_X,
|
||||
DEADZONE_Y,
|
||||
DEADZONE_BUTTON,
|
||||
} analogdeadzone_e;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ACCELEROMETER,
|
||||
GYROSCOPE,
|
||||
} motionsensortype_e;
|
||||
|
||||
// mouse values are used once
|
||||
extern consvar_t cv_mousesens, cv_mouseysens;
|
||||
extern consvar_t cv_mousesens2, cv_mouseysens2;
|
||||
|
|
@ -178,6 +192,22 @@ void G_ResetControls(UINT8 p);
|
|||
void G_SaveKeySetting(FILE *f, INT32 (*fromcontrolsa)[MAXINPUTMAPPING], INT32 (*fromcontrolsb)[MAXINPUTMAPPING], INT32 (*fromcontrolsc)[MAXINPUTMAPPING], INT32 (*fromcontrolsd)[MAXINPUTMAPPING]);
|
||||
INT32 G_CheckDoubleUsage(INT32 keynum, INT32 playernum, boolean modify);
|
||||
|
||||
#define MAXGAMEPADTILT (50*FRACUNIT/100)
|
||||
// #define ACCELEROMETERGRAVITY ((fixed_t)(9.80665f * ((float)FRACUNIT)))
|
||||
#define ACCELEROMETERGRAVITY 642688
|
||||
boolean G_GetGamepadCanUseTilt(INT32 p);
|
||||
void G_ResetGyroCalibration(INT32 p);
|
||||
void G_UpdateGamepadAutoCalibration(INT32 p, vector3_t accel, vector3_t gyro, boolean allowautocalibration);
|
||||
void G_UpdateGamepadGyro(INT32 p, vector3_t gyro);
|
||||
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
|
||||
fixed_t G_GetGamepadShakinessFactor(INT32 p);
|
||||
vector3_t G_GetGamepadShake(INT32 p);
|
||||
vector3_t G_GetGamepadGravity(INT32 p);
|
||||
vector3_t G_GetCalibratedGyroOffset(INT32 p);
|
||||
vector3_t G_GetGamepadCalibratedGyro(INT32 p);
|
||||
vector3_t G_PlayerInputSensor(UINT8 p, motionsensortype_e sensor);
|
||||
INT32 G_GetGamepadTilt(INT32 p);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#include "doomstat.h"
|
||||
#include "d_clisrv.h"
|
||||
#include "g_game.h"
|
||||
#include "g_input.h"
|
||||
#include "p_local.h"
|
||||
#include "z_zone.h"
|
||||
#include "m_cond.h"
|
||||
|
|
|
|||
|
|
@ -132,14 +132,17 @@ struct camera_t
|
|||
fixed_t pan;
|
||||
// SRB2Kart: camera pitches on slopes
|
||||
angle_t pitch;
|
||||
|
||||
|
||||
// Freecam: A button was held since entering from menu, so don't move camera
|
||||
UINT8 button_a_held;
|
||||
|
||||
|
||||
boolean reset_aiming; // camera aiming needs to be reset from chase camera
|
||||
|
||||
|
||||
// Hold up/down to pan the camera vertically
|
||||
SINT8 dpad_y_held;
|
||||
SINT8 freelook_held;
|
||||
// between -45 deg and 45 deg
|
||||
fixed_t freelook_pitch;
|
||||
fixed_t freelook_pitch_add;
|
||||
|
||||
// Interpolation data
|
||||
fixed_t old_x, old_y, old_z;
|
||||
|
|
|
|||
44
src/p_tick.c
44
src/p_tick.c
|
|
@ -650,16 +650,50 @@ void P_RunChaseCameras(void)
|
|||
{
|
||||
if (camera[i].chase)
|
||||
{
|
||||
player_t *p = &players[displayplayers[i]];
|
||||
INT32 forplayer = displayplayers[i];
|
||||
player_t *p = &players[forplayer];
|
||||
camera_t *cam = &camera[i];
|
||||
|
||||
if (p->mo && p->cmd.throwdir != 0)
|
||||
// client sided
|
||||
if (p->mo && G_PlayerInputDown(forplayer, gc_freelook, false, DEADZONE_BUTTON))
|
||||
{
|
||||
if (p->speed < 6 * p->mo->scale && abs(cam->dpad_y_held) < 2*TICRATE)
|
||||
cam->dpad_y_held += intsign(p->cmd.throwdir);
|
||||
// instantly able to move camera
|
||||
if (p->speed < 6 * p->mo->scale && abs(cam->freelook_held) < 2*TICRATE)
|
||||
{
|
||||
cam->freelook_held = 2*TICRATE;
|
||||
}
|
||||
|
||||
if (abs(cam->freelook_held) >= 2*TICRATE)
|
||||
{
|
||||
cam->freelook_pitch = (45*FixedDiv(p->cmd.throwdir, KART_FULLTURN));
|
||||
|
||||
// gyro aiming
|
||||
if (G_GetGamepadCanUseTilt(forplayer) && cv_tiltcontrol[forplayer].value == 1)
|
||||
{
|
||||
fixed_t deltaseconds = FixedDiv(FRACUNIT, max(cv_timescale.value, FRACUNIT/20))/TICRATE;
|
||||
vector3_t gyro = G_GetGamepadCalibratedGyro(forplayer);
|
||||
cam->freelook_pitch_add -= FixedMul(gyro.x, deltaseconds);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (p->mo && p->cmd.throwdir != 0)
|
||||
{
|
||||
if (p->speed < 6 * p->mo->scale && abs(cam->freelook_held) < 2*TICRATE)
|
||||
{
|
||||
cam->freelook_held += intsign(p->cmd.throwdir);
|
||||
}
|
||||
|
||||
if (abs(cam->freelook_held) >= 2*TICRATE)
|
||||
{
|
||||
cam->freelook_pitch = 45*FRACUNIT*intsign(p->cmd.throwdir);
|
||||
}
|
||||
}
|
||||
else
|
||||
cam->dpad_y_held = 0;
|
||||
{
|
||||
cam->freelook_held = 0;
|
||||
cam->freelook_pitch = 0;
|
||||
cam->freelook_pitch_add = 0;
|
||||
}
|
||||
|
||||
P_MoveChaseCamera(p, cam, false);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2831,7 +2831,7 @@ void P_DemoCameraMovement(camera_t *cam, UINT8 num)
|
|||
cam->reset_aiming = false;
|
||||
}
|
||||
|
||||
cam->angle += cmd->turning << TICCMD_REDUCE;
|
||||
cam->angle = cmd->angle << TICCMD_REDUCE;
|
||||
|
||||
// camera movement:
|
||||
if (!cam->button_a_held)
|
||||
|
|
@ -3098,9 +3098,9 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
focusaiming = player->aiming;
|
||||
}
|
||||
|
||||
if (abs(thiscam->dpad_y_held) >= 2*TICRATE)
|
||||
if (abs(thiscam->freelook_held) >= 2*TICRATE)
|
||||
{
|
||||
focusaiming += ANGLE_45 * intsign(thiscam->dpad_y_held) * P_MobjFlip(mo);
|
||||
focusaiming += FixedAngle(CLAMP(thiscam->freelook_pitch + thiscam->freelook_pitch_add, -45*FRACUNIT, 45*FRACUNIT) * P_MobjFlip(mo));
|
||||
}
|
||||
|
||||
if (P_CameraThinker(player, thiscam, resetcalled))
|
||||
|
|
|
|||
|
|
@ -475,15 +475,10 @@ static void ST_drawMusicDebug(INT32 *height)
|
|||
ST_pushDebugString(height, va(" Song: %8s", mname));
|
||||
}
|
||||
|
||||
static INT32 ST_getFixedFrac(fixed_t val)
|
||||
{
|
||||
return ((abs(val) * 100)>>FRACBITS) % 100;
|
||||
}
|
||||
|
||||
static void ST_drawImuDebug(INT32 *height)
|
||||
{
|
||||
INT32 pnum = stplyrnum;
|
||||
vector3_t accel, gyro, grav, shake;
|
||||
vector3_t accel, gyro, gyrocalibrated, grav, shake;
|
||||
if (demo.playback || (!P_IsMachineLocalPlayer(stplyr)))
|
||||
{
|
||||
ST_pushDebugString(height, va("Only for local player!!"));
|
||||
|
|
@ -491,14 +486,16 @@ static void ST_drawImuDebug(INT32 *height)
|
|||
}
|
||||
|
||||
accel = G_PlayerInputSensor(pnum, ACCELEROMETER);
|
||||
gyro = G_PlayerInputSensor(pnum, GYROSCOPE);
|
||||
grav = G_GetGamepadGravity(pnum);
|
||||
gyro = G_PlayerInputSensor(pnum, GYROSCOPE);
|
||||
gyrocalibrated = G_GetGamepadCalibratedGyro(pnum);
|
||||
grav = G_GetGamepadGravity(pnum);
|
||||
shake = G_GetGamepadShake(pnum);
|
||||
|
||||
ST_pushDebugString(height, va(" Gyro :%4.2f, %4.2f,%4.2f", FixedToFloat(gyro.x), FixedToFloat(gyro.y), FixedToFloat(gyro.z)));
|
||||
ST_pushDebugString(height, va("Accel :%4.2f, %4.2f,%4.2f", FixedToFloat(accel.x), FixedToFloat(accel.y), FixedToFloat(accel.z)));
|
||||
ST_pushDebugString(height, va("Shake :%4.2f, %4.2f,%4.2f", FixedToFloat(shake.x), FixedToFloat(shake.y), FixedToFloat(shake.z)));
|
||||
ST_pushDebugString(height, va(" Grav :%4.2f, %4.2f,%4.2f", FixedToFloat(grav.x), FixedToFloat(grav.y), FixedToFloat(grav.z)));
|
||||
ST_pushDebugString(height, va(" Grav :%4.2f,%4.2f,%4.2f", FixedToFloat(grav.x), FixedToFloat(grav.y), FixedToFloat(grav.z)));
|
||||
ST_pushDebugString(height, va("Shake :%4.2f,%4.2f,%4.2f", FixedToFloat(shake.x), FixedToFloat(shake.y), FixedToFloat(shake.z)));
|
||||
ST_pushDebugString(height, va("Cal. G:%4.2f,%4.2f,%4.2f", FixedToFloat(gyrocalibrated.x), FixedToFloat(gyrocalibrated.y), FixedToFloat(gyrocalibrated.z)));
|
||||
ST_pushDebugString(height, va(" Gyro :%4.2f,%4.2f,%4.2f", FixedToFloat(gyro.x), FixedToFloat(gyro.y), FixedToFloat(gyro.z)));
|
||||
ST_pushDebugString(height, va("Accel :%4.2f,%4.2f,%4.2f", FixedToFloat(accel.x), FixedToFloat(accel.y), FixedToFloat(accel.z)));
|
||||
}
|
||||
|
||||
static void ST_drawRenderDebug(INT32 *height)
|
||||
|
|
|
|||
Loading…
Reference in a new issue