get sensor fusion and basic tilt steering working

This commit is contained in:
minenice55 2026-02-26 02:20:10 -05:00
parent 0cfb873f4f
commit a7ddeddbe4
9 changed files with 310 additions and 61 deletions

View file

@ -370,7 +370,7 @@ typedef enum
DBG_PLAYER = 0x00000004,
DBG_RENDER = 0x00000008,
DBG_MUSIC = 0x00000010,
//DBG_NIGHTS = 0x00000020, // free
DBG_IMU = 0x00000020,
DBG_POLYOBJ = 0x00000040,
DBG_GAMELOGIC = 0x00000080,
DBG_NETPLAY = 0x00000100,

View file

@ -51,6 +51,7 @@
#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"
@ -1334,12 +1335,14 @@ vector3_t G_PlayerInputSensor(UINT8 p, motionsensortype_e sensor)
gamekeydown[deviceID][KEY_ACCELEROMETER1+1],
gamekeydown[deviceID][KEY_ACCELEROMETER1+2]
);
break;
case GYROSCOPE:
FV3_Load(&out,
gamekeydown[deviceID][KEY_GYROSCOPE1+0],
gamekeydown[deviceID][KEY_GYROSCOPE1+1],
gamekeydown[deviceID][KEY_GYROSCOPE1+2]
);
break;
}
return out;
}
@ -1417,20 +1420,61 @@ static void G_HandleAxisDeadZone(UINT8 splitnum, joystickvector2_t *joystickvect
}
}
// copy/pasted from the lua version of this routine
inline static vector4_t AngleAxis(angle_t angle, vector3_t *axis)
// copy/pasted from the lua version of these routines
static vector4_t *QuaternionMul(vector4_t *out, vector4_t *a, vector4_t *b)
{
fixed_t cosangle = FINECOSINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
fixed_t sinangle = FINESINE(((angle / 2) >> ANGLETOFINESHIFT) & FINEMASK);
vector4_t result;
vector3_t normaxis;
fixed_t ax = a->x, ay = a->y, az = a->z, aw = a->a;
fixed_t bx = b->x, by = b->y, bz = b->z, bw = b->a;
FV3_NormalizeEx(axis, &normaxis);
FV4_NormalizeEx(out, FV4_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),
FixedMul(aw, bw) - FixedMul(ax, bx) - FixedMul(ay, by) - FixedMul(az, bz)
));
return out;
}
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;
}
static vector4_t *QuaternionInvert(vector4_t *out)
{
FV4_Load(out,
-out->x,
-out->y,
-out->z,
out->a
);
return out;
}
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(normaxis.x, sinangle),
FixedMul(normaxis.y, sinangle),
FixedMul(normaxis.z, sinangle),
FixedMul(axis.x, sinangle),
FixedMul(axis.y, sinangle),
FixedMul(axis.z, sinangle),
cosangle
);
@ -1439,32 +1483,177 @@ inline static vector4_t AngleAxis(angle_t angle, vector3_t *axis)
// math sourced from this article
// http://gyrowiki.jibbsmart.com/blog:finding-gravity-with-sensor-fusion
#define Interpolator (FRACUNIT/4)
// thresholds of trust for accel shakiness. less shakiness = more trust
#define ShakinessMaxThreshold (4*FRACUNIT/10)
#define ShakinessMinThreshold (FRACUNIT/10)
// 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 (FRACUNIT/10)
// if our old gravity vector is close enough to our new one, limit further corrections to this proportion of the rotation speed
#define CorrectionGyroFactor (FRACUNIT/10)
// 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 (FRACUNIT/10)
// state
fixed_t localshakinessfac[MAXSPLITSCREENPLAYERS];
vector3_t localsmoothedaccel[MAXSPLITSCREENPLAYERS];
vector3_t localgravityvectors[MAXSPLITSCREENPLAYERS];
vector3_t G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel)
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel)
{
const vector3_t invGyro = {-gyro.x, -gyro.y, -gyro.z};
const vector3_t newGravity = {-accel.x, -accel.y, -accel.z};
const vector4_t invRotation = AngleAxis(FixedMul(FV3_Magnitude(&gyro), FRACUNIT/TICRATE), &invGyro);
const fixed_t correctionRate = FRACUNIT/8;
vector3_t gravityDelta;
FV3_Mul(&localgravityvectors[p], &invRotation);
FV3_SubEx(&gravityDelta, &newGravity, &localgravityvectors[p]);
FV3_Load(&localgravityvectors[p],
FixedMul(gravityDelta.x, correctionRate),
FixedMul(gravityDelta.y, correctionRate),
FixedMul(gravityDelta.z, correctionRate)
// convert gyro input to reverse rotation
const vector3_t invAccel = {-accel.x, -accel.y, -accel.z};
fixed_t correctionRate = CorrectionMinimumSpeed;
fixed_t correctionMagnitude, gravityDeltaMagnitude, angleRate, correctionLimit;
vector4_t invRotation = AngleAxis(
-gyro.x,
-gyro.y,
-gyro.z,
FixedMul(FV3_Magnitude(&gyro), FRACUNIT/TICRATE)
);
vector3_t gravityDelta = {0};
vector3_t gravityDeltaDirection = {0};
vector3_t fv3_temp = {0};
// rotate gravity vector
QuaternionMulVec3(&localgravityvectors[p], &localgravityvectors[p], &invRotation);
QuaternionMulVec3(&localsmoothedaccel[p], &localsmoothedaccel[p], &invRotation);
FV3_SubEx(&accel, &localsmoothedaccel[p], &fv3_temp);
localshakinessfac[p] = max(
FixedMul(localshakinessfac[p], Interpolator),
FV3_Magnitude(&fv3_temp)
);
FV3_Load(&localsmoothedaccel[p],
Easing_Linear(Interpolator, accel.x, localsmoothedaccel[p].x),
Easing_Linear(Interpolator, accel.y, localsmoothedaccel[p].y),
Easing_Linear(Interpolator, accel.z, localsmoothedaccel[p].z)
);
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(stillness, (CorrectionShakyRate - CorrectionStillRate));
}
else if (localshakinessfac[p] > ShakinessMaxThreshold)
{
correctionRate = CorrectionShakyRate;
}
else
{
correctionRate = CorrectionStillRate;
}
// limit in proportion to rotation rate
angleRate = FixedMul(FV3_Magnitude(&gyro), M_PI_FIXED)/180;
correctionLimit = FixedMul(FixedMul(angleRate, FV3_Magnitude(&localgravityvectors[p])), CorrectionGyroFactor);
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;
}
correctionRate = correctionRate + FixedMul((correctionLimit - correctionRate), closeEnoughFactor);
}
// finally, let's always allow a little bit of correction
correctionRate = max(correctionRate, CorrectionMinimumSpeed);
FV3_Load(&gravityDeltaDirection,
FixedMul(FixedMul(correctionRate, FRACUNIT/TICRATE), gravityDeltaDirection.x),
FixedMul(FixedMul(correctionRate, FRACUNIT/TICRATE), gravityDeltaDirection.y),
FixedMul(FixedMul(correctionRate, FRACUNIT/TICRATE), gravityDeltaDirection.z)
);
correctionMagnitude = FV3_Magnitude(&gravityDeltaDirection);
gravityDeltaMagnitude = FV3_Magnitude(&gravityDelta);
if (FixedMul(correctionMagnitude, correctionMagnitude) > FixedMul(gravityDeltaMagnitude, gravityDeltaMagnitude))
{
FV3_Add(&localgravityvectors[p], &gravityDeltaDirection);
}
else
{
FV3_Add(&localgravityvectors[p], &gravityDelta);
}
}
#define TILTRANGE 35*FRACUNIT
fixed_t G_GetGamepadTilt(INT32 p)
{
fixed_t tilt;
fixed_t axis;
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_PlayerInputAnalog: Invalid player ID %d\n", p);
#endif
return 0;
}
tilt = CLAMP(G_GetGamepadGravity(p).x, -TILTRANGE, TILTRANGE);
//TODO: this is really dumb, pinch towards 0 and towards the farthest we can tilt comfortably
axis = Easing_Linear(FixedDiv(tilt + TILTRANGE, (2*TILTRANGE)), -32768, 32767);
return axis;
}
#undef TILTRANGE
vector3_t G_GetGamepadGravity(INT32 p)
{
const vector3_t zero = {0};
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_PlayerInputAnalog: Invalid player ID %d\n", p);
#endif
return zero;
}
return localgravityvectors[p];
}
vector3_t G_GetGamepadTilt(INT32 p, vector3_t gravity)
vector3_t G_GetGamepadShake(INT32 p)
{
vector3_t out;
return out;
const vector3_t zero = {0};
vector3_t accel;
if (p >= MAXSPLITSCREENPLAYERS)
{
#ifdef PARANOIA
CONS_Debug(DBG_GAMELOGIC, "G_PlayerInputAnalog: Invalid player ID %d\n", p);
#endif
return zero;
}
accel = G_PlayerInputSensor(p, ACCELEROMETER);
FV3_Add(&accel, &localgravityvectors[p]);
return accel;
}
#undef Interpolator
#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
@ -1501,8 +1690,6 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
INT32 forward, side, tspeed;
joystickvector2_t joystickvector;
vector3_t gravity = {0};
INT16 accelerometertilt;
// you'd BETTER not touch the player while freecamming...
@ -1528,19 +1715,13 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
break;
}
if (K_PlayerUsesBotMovement(player))
{
// Bot ticcmd is generated by K_BuildBotTiccmd
return;
}
// update our gamepad gravity when applicable
// this should always execute so we have an accurate state
if (true) //todo: check if gamepad supports accel or accel and gyro
{
vector3_t accel = G_PlayerInputSensor(forplayer, ACCELEROMETER);
vector3_t gyro = G_PlayerInputSensor(forplayer, GYROSCOPE);
gravity = G_UpdateGamepadGravity(forplayer, gyro, accel);
G_UpdateGamepadGravity(forplayer, gyro, accel);
}
// why build a ticcmd if we're paused?
@ -1550,6 +1731,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
return;
}
if (K_PlayerUsesBotMovement(player))
{
// Bot ticcmd is generated by K_BuildBotTiccmd
return;
}
joystickvector.xaxis = G_PlayerInputAnalog(forplayer, gc_turnright, false, DEADZONE_X) - G_PlayerInputAnalog(forplayer, gc_turnleft, false, DEADZONE_X);
joystickvector.yaxis = 0;
G_HandleAxisDeadZone(forplayer, &joystickvector);
@ -1557,10 +1744,11 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
if (joystickvector.xaxis != 0)
{
joystickactive[forplayer] = true;
accelerometertilt = 0;
}
else if (!joystickactive[forplayer])
{
accelerometertilt = G_GetGamepadTilt(forplayer);
}
// For kart, I've turned the aim axis into a digital axis because we only
@ -1576,7 +1764,14 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
}
forward = side = 0;
tspeed = joystickvector.xaxis;
if (joystickactive[forplayer])
{
tspeed = joystickvector.xaxis;
}
else
{
tspeed = accelerometertilt;
}
// use two stage accelerative turning
// on the keyboard and (NOT!) joystick
@ -1609,6 +1804,12 @@ void G_BuildTiccmd(ticcmd_t *cmd, INT32 realtics, UINT8 ssplayer)
cmd->angle -= (tspeed * KART_FULLTURN) / JOYAXISRANGE;
side += (joystickvector.xaxis * 4) / JOYAXISRANGE;
}
else if (accelerometertilt != 0)
{
cmd->turning -= (tspeed * KART_FULLTURN) / JOYAXISRANGE;
cmd->angle -= (tspeed * KART_FULLTURN) / JOYAXISRANGE;
side += (accelerometertilt * 4) / JOYAXISRANGE;
}
// Specator mouse turning
if (spectating)

View file

@ -143,8 +143,11 @@ typedef enum
#define MAXGAMEPADTILT (ANG30)
#define ACCEL_GRAVITY (FLOAT_TO_FIXED(9.80665f))
vector3_t G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
vector3_t G_GetGamepadTilt(INT32 p, vector3_t gravity);
void G_UpdateGamepadGravity(INT32 p, vector3_t gyro, vector3_t accel);
vector3_t G_GetGamepadGravity(INT32 p);
vector3_t G_GetGamepadShake(INT32 p);
fixed_t G_GetGamepadTilt(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);

View file

@ -491,19 +491,13 @@ static keyname_t keynames[] =
{KEY_AXIS1+8, "L TRIGGER"},
{KEY_AXIS1+9, "R TRIGGER"},
{KEY_ACCELEROMETER1+0, "TILT -X"},
{KEY_ACCELEROMETER1+1, "TILT +X"},
{KEY_ACCELEROMETER1+2, "TILT -Y"},
{KEY_ACCELEROMETER1+3, "TILT +Y"},
{KEY_ACCELEROMETER1+4, "TILT -Z"},
{KEY_ACCELEROMETER1+5, "TILT +Z"},
{KEY_ACCELEROMETER1+0, "TILT X"},
{KEY_ACCELEROMETER1+1, "TILT Y"},
{KEY_ACCELEROMETER1+2, "TILT Z"},
{KEY_GYROSCOPE1+0, "ROTATE -X"},
{KEY_GYROSCOPE1+1, "ROTATE +X"},
{KEY_GYROSCOPE1+2, "ROTATE -Y"},
{KEY_GYROSCOPE1+3, "ROTATE +Y"},
{KEY_GYROSCOPE1+4, "ROTATE -Z"},
{KEY_GYROSCOPE1+5, "ROTATE +Z"},
{KEY_GYROSCOPE1+0, "ROTATE X"},
{KEY_GYROSCOPE1+1, "ROTATE Y"},
{KEY_GYROSCOPE1+2, "ROTATE Z"},
};
static const char *gamecontrolname[num_gamecontrols] =

View file

@ -35,8 +35,9 @@ extern "C" {
#define JOYANALOGS 4 // 4 analog stick axes (2 sticks * 2 axes)
#define JOYTRIGGERS 2 // 2 trigger axes, positive only
#define JOYIMUAXISES 6 // 3 accelerometer, 3 gyroscope axes (x, y, z)
#define JOYAXISES (JOYANALOGS + JOYTRIGGERS + JOYIMUAXISES)
#define JOYAXISKEYS ((2 * JOYANALOGS) + JOYTRIGGERS + (2 * JOYIMUAXISES))
#define JOYAXISES (JOYANALOGS + JOYTRIGGERS + JOYIMUAXISES)
#define JOYAXISKEYS (2 * JOYANALOGS) + JOYTRIGGERS
#define JOYSTATEKEYS JOYAXISKEYS + JOYIMUAXISES
#define MAXINPUTMAPPING 4
@ -48,9 +49,9 @@ typedef enum
KEY_JOY1 = NUMKEYS,
KEY_HAT1 = KEY_JOY1 + JOY_DPAD_UP,
KEY_AXIS1 = KEY_JOY1 + JOYBUTTONS,
KEY_ACCELEROMETER1 = KEY_AXIS1 + JOYANALOGS + JOYTRIGGERS,
KEY_GYROSCOPE1 = KEY_ACCELEROMETER1 + 6,
JOYINPUTEND = KEY_AXIS1 + JOYAXISKEYS,
KEY_ACCELEROMETER1 = KEY_AXIS1 + JOYAXISKEYS,
KEY_GYROSCOPE1 = KEY_ACCELEROMETER1 + 3,
JOYINPUTEND = KEY_AXIS1 + JOYSTATEKEYS,
KEY_MOUSE1 = JOYINPUTEND,
KEY_MOUSEMOVE = KEY_MOUSE1 + MOUSEBUTTONS,

View file

@ -723,6 +723,11 @@ struct debugFlagNames_s const debug_flag_names[] =
{"Player", DBG_PLAYER},
{"Render", DBG_RENDER},
{"Renderer", DBG_RENDER}, // alt name
{"Music", DBG_MUSIC},
{"IMU", DBG_IMU},
{"Accelerometer", DBG_IMU}, // alt name
{"Gyro", DBG_IMU}, // alt name
{"Sensors", DBG_IMU}, // alt name
{"Polyobj", DBG_POLYOBJ},
{"GameLogic", DBG_GAMELOGIC},
{"Game", DBG_GAMELOGIC}, // alt name

View file

@ -95,7 +95,7 @@ void I_ShutdownController(UINT8 index)
for (i = 0; i < 3; i++)
{
event.data1 = 0;
event.data2 = 0;
event.data2 = FLOAT_TO_FIXED(9.80665f);
event.data3 = 0;
D_PostEvent(&event);
}
@ -250,6 +250,18 @@ void I_InitController(UINT8 playernum)
controller->flipbuttons = SDL_GetGamepadButtonLabel(newcontroller, SDL_GAMEPAD_BUTTON_SOUTH) == SDL_GAMEPAD_BUTTON_LABEL_B;
controller->flipgc = SDL_GetGamepadButtonLabel(newcontroller, SDL_GAMEPAD_BUTTON_WEST) == SDL_GAMEPAD_BUTTON_LABEL_B
&& SDL_GetGamepadButtonLabel(newcontroller, SDL_GAMEPAD_BUTTON_EAST) == SDL_GAMEPAD_BUTTON_LABEL_X;
if (controller->hasaccelerometer)
{
CONS_Debug(DBG_GAMELOGIC, "Enabling accelerometer for controller %d\n", joystick_id);
SDL_SetGamepadSensorEnabled(controller->dev, SDL_SENSOR_ACCEL, true);
}
if (controller->hasgyro)
{
CONS_Debug(DBG_GAMELOGIC, "Enabling gyro for controller %d\n", joystick_id);
SDL_SetGamepadSensorEnabled(controller->dev, SDL_SENSOR_GYRO, true);
}
}
void I_InitController1(void)

View file

@ -1057,6 +1057,7 @@ static void Impl_HandleControllerSensorEvent(SDL_GamepadSensorEvent evt)
// data[2]: z acceleration in m/s
// we convert to gs before passing it to the event
case SDL_SENSOR_ACCEL:
// CONS_Debug(DBG_IMU, "Got Accelerometer event %4.2f %4.2f %4.2f\n", evt.data[0]/SDL_STANDARD_GRAVITY, evt.data[1]/SDL_STANDARD_GRAVITY, evt.data[2]/SDL_STANDARD_GRAVITY);
event.type = ev_accelerometer;
event.data1 = FLOAT_TO_FIXED(evt.data[0] / SDL_STANDARD_GRAVITY);
event.data2 = FLOAT_TO_FIXED(evt.data[1] / SDL_STANDARD_GRAVITY);
@ -1070,10 +1071,11 @@ static void Impl_HandleControllerSensorEvent(SDL_GamepadSensorEvent evt)
// we convert to degrees per second before passing it to the event
case SDL_SENSOR_GYRO:
#define RAD2DEG 57.295779513f
// CONS_Debug(DBG_IMU, "Got Gyro event %4.2f %4.2f %4.2f\n", RAD2DEG * evt.data[0], RAD2DEG * evt.data[1], RAD2DEG * evt.data[2]);
event.type = ev_gyroscope;
event.data1 = FixedAngle(FLOAT_TO_FIXED(RAD2DEG * evt.data[0]));
event.data2 = FixedAngle(FLOAT_TO_FIXED(RAD2DEG * evt.data[1]));
event.data3 = FixedAngle(FLOAT_TO_FIXED(RAD2DEG * evt.data[2]));
event.data1 = FLOAT_TO_FIXED(RAD2DEG * evt.data[0]);
event.data2 = FLOAT_TO_FIXED(RAD2DEG * evt.data[1]);
event.data3 = FLOAT_TO_FIXED(RAD2DEG * evt.data[2]);
#undef RAD2DEG
D_PostEvent(&event);
return;

View file

@ -474,6 +474,32 @@ 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;
if (demo.playback || (!P_IsMachineLocalPlayer(stplyr)))
{
ST_pushDebugString(height, va("Only for local player!!"));
return;
}
accel = G_PlayerInputSensor(pnum, ACCELEROMETER);
gyro = G_PlayerInputSensor(pnum, GYROSCOPE);
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)));
}
static void ST_drawRenderDebug(INT32 *height)
{
const struct RenderStats *i = &g_renderstats;
@ -569,6 +595,11 @@ static void ST_drawDebugInfo(void)
height -= 32;
}
if (cht_debug & DBG_IMU)
{
ST_drawImuDebug(&height);
}
if (cht_debug & DBG_MUSIC)
{
ST_drawMusicDebug(&height);