Rotate the sensor axes to match gamepad orientation when using the device sensors for game controllers

This commit is contained in:
Sam Lantinga 2023-06-16 17:48:34 -07:00
parent a9c86e518a
commit 8de6ce7e92
2 changed files with 28 additions and 8 deletions

View file

@ -89,13 +89,12 @@ typedef enum
* values[1]: Acceleration on the y axis * values[1]: Acceleration on the y axis
* values[2]: Acceleration on the z axis * values[2]: Acceleration on the z axis
* *
* For phones held in portrait mode and game controllers held in front of you, * For phones and tablets held in natural orientation and game controllers held in front of you, the axes are defined as follows:
* the axes are defined as follows:
* -X ... +X : left ... right * -X ... +X : left ... right
* -Y ... +Y : bottom ... top * -Y ... +Y : bottom ... top
* -Z ... +Z : farther ... closer * -Z ... +Z : farther ... closer
* *
* The axis data is not changed when the phone is rotated. * The axis data is not changed when the device is rotated.
* *
* \sa SDL_GetDisplayOrientation() * \sa SDL_GetDisplayOrientation()
*/ */
@ -114,13 +113,12 @@ typedef enum
* values[1]: Angular speed around the y axis (yaw) * values[1]: Angular speed around the y axis (yaw)
* values[2]: Angular speed around the z axis (roll) * values[2]: Angular speed around the z axis (roll)
* *
* For phones held in portrait mode and game controllers held in front of you, * For phones and tablets held in natural orientation and game controllers held in front of you, the axes are defined as follows:
* the axes are defined as follows:
* -X ... +X : left ... right * -X ... +X : left ... right
* -Y ... +Y : bottom ... top * -Y ... +Y : bottom ... top
* -Z ... +Z : farther ... closer * -Z ... +Z : farther ... closer
* *
* The axis data is not changed when the phone or controller is rotated. * The axis data is not changed when the device is rotated.
* *
* \sa SDL_GetDisplayOrientation() * \sa SDL_GetDisplayOrientation()
*/ */

View file

@ -370,6 +370,24 @@ static void RecenterGamepad(SDL_Gamepad *gamepad)
} }
} }
/* SDL defines sensor orientation for phones relative to the natural
orientation, and for gamepads relative to being held in front of you.
When a phone is being used as a gamepad, its orientation changes,
so adjust sensor axes to match.
*/
static void AdjustSensorOrientation(float *src, float *dst)
{
/* When a phone is rotated left and laid flat, the axes change
orientation as follows:
-X to +X becomes +Z to -Z
-Y to +Y becomes +X to -X
-Z to +Z becomes -Y to +Y
*/
dst[0] = -src[1];
dst[1] = src[2];
dst[2] = -src[0];
}
/* /*
* Event filter to fire gamepad events from joystick ones * Event filter to fire gamepad events from joystick ones
*/ */
@ -449,10 +467,14 @@ static int SDLCALL SDL_GamepadEventWatcher(void *userdata, SDL_Event *event)
SDL_LockJoysticks(); SDL_LockJoysticks();
for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) { for (gamepad = SDL_gamepads; gamepad; gamepad = gamepad->next) {
if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) { if (gamepad->joystick->accel && gamepad->joystick->accel_sensor == event->sensor.which) {
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, event->sensor.data, SDL_arraysize(event->sensor.data)); float data[3];
AdjustSensorOrientation(event->sensor.data, data);
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_ACCEL, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
} }
if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) { if (gamepad->joystick->gyro && gamepad->joystick->gyro_sensor == event->sensor.which) {
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, event->sensor.data, SDL_arraysize(event->sensor.data)); float data[3];
AdjustSensorOrientation(event->sensor.data, data);
SDL_SendJoystickSensor(event->common.timestamp, gamepad->joystick, SDL_SENSOR_GYRO, event->sensor.sensor_timestamp, data, SDL_arraysize(data));
} }
} }
SDL_UnlockJoysticks(); SDL_UnlockJoysticks();