Fix mouselook

Likely with the change to SDL's 'captured mouse' mode, mouse movements
during fullscreen became deltas *from the last movement*, not from
the last sampled position or frame. In order to correctly measure the
mouse movement, the deltas must be summed up and then reset when 'read'
at input-processing time.

Moving to summing the deltas threw many other mouse-related calibration
factors out of whack, so these factors are re-determined empirically
across a range of mice, from 400dpi 125hz to 30,000dpi 8khz. Reasonable
defaults are chosen targeting an 'average' mouse of 1000dpi, and the
mouse sensitivity precision is increased to allow finer user tuning.
This commit is contained in:
Chris Sarbora
2025-04-12 01:57:43 -05:00
parent 11f93221e7
commit 5b18e22e18
4 changed files with 22 additions and 11 deletions

View File

@@ -303,7 +303,7 @@
#define IDV_OPTIONS 18
// used for adjusting settings.
#define CFG_AXIS_SENS_RANGE 20
#define CFG_AXIS_SENS_RANGE 200
const int16_t UID_JOYCFG = 0x1000;

View File

@@ -395,8 +395,8 @@ int sdlMouseMotionFilter(SDL_Event const *event) {
} // if
else {
if (ddio_mouseGrabbed) {
DDIO_mouse_state.dx = event->motion.xrel;
DDIO_mouse_state.dy = event->motion.yrel;
DDIO_mouse_state.dx += event->motion.xrel;
DDIO_mouse_state.dy += event->motion.yrel;
DDIO_mouse_state.x += DDIO_mouse_state.dx;
DDIO_mouse_state.y += DDIO_mouse_state.dy;
} // if

View File

@@ -876,8 +876,10 @@ bool sdlgameController::enum_controllers() {
m_ControlList[num_devs].buttons = nbtns;
m_ControlList[num_devs].flags = CTF_X_AXIS | CTF_Y_AXIS; // | (naxis>=3 ? CTF_Z_AXIS : 0);
m_ControlList[num_devs].btnmask = btnmask;
m_ControlList[num_devs].normalizer[0] = 320.0f;
m_ControlList[num_devs].normalizer[1] = 240.0f;
// normalizer is the "available area" in dots - this is the max we expect ANY mouse to EVER travel in 1.0s
// if a mouse is faster than (normalizer / frame_time), rot speed will be CLAMPED to kMaxRevPerSec
m_ControlList[num_devs].normalizer[0] = 100000.0f;
m_ControlList[num_devs].normalizer[1] = 100000.0f;
m_ControlList[num_devs].normalizer[2] = 100.0f;
m_ControlList[num_devs].sens[0] = 1.0f;
m_ControlList[num_devs].sens[1] = 1.0f;
@@ -1108,6 +1110,11 @@ float sdlgameController::get_button_value(int8_t controller, ct_format format, u
return val;
}
// rot: fraction of one full circle (1.0 == 360 degrees)
static constexpr angle rotationToFixAngle(double rot) {
return static_cast<angle>(std::numeric_limits<angle>::max() * rot);
}
// note controller is index into ControlList.
float sdlgameController::get_axis_value(int8_t controller, uint8_t axis, ct_format format, bool invert) {
struct sdlgameController::t_controller *ctldev;
@@ -1212,6 +1219,8 @@ float sdlgameController::get_axis_value(int8_t controller, uint8_t axis, ct_form
return val;
}
if ((Current_pilot.mouselook_control) && (GAME_MODE == GetFunctionMode())) {
constexpr double kMaxRevPerSec = 10; // number of rotations when val == 1.0 (ie, max movement)
// Don't do mouselook controls if they aren't enabled in multiplayer
if ((Game_mode & GM_MULTI) && (!(Netgame.flags & NF_ALLOW_MLOOK)))
return val;
@@ -1236,7 +1245,7 @@ float sdlgameController::get_axis_value(int8_t controller, uint8_t axis, ct_form
if (invert)
val = -val;
vm_AnglesToMatrix(&orient, 0.0, val * (((float)(65535.0f / 20)) * .5), 0.0);
vm_AnglesToMatrix(&orient, 0.0, rotationToFixAngle(val * kMaxRevPerSec * m_frame_time), 0.0);
Objects[Players[Player_num].objnum].orient = Objects[Players[Player_num].objnum].orient * orient;
@@ -1259,7 +1268,7 @@ float sdlgameController::get_axis_value(int8_t controller, uint8_t axis, ct_form
if (invert)
val = -val;
vm_AnglesToMatrix(&orient, val * (((float)(65535.0f / 20)) * .5), 0.0, 0.0);
vm_AnglesToMatrix(&orient, rotationToFixAngle(val * kMaxRevPerSec * m_frame_time), 0.0, 0.0);
Objects[Players[Player_num].objnum].orient = Objects[Players[Player_num].objnum].orient * orient;

View File

@@ -174,6 +174,8 @@
#include "renderer.h"
#include "Macros.h"
constexpr float kDefaultMouseScale = 20;
#define UI_MOUSE_HOTX 2
#define UI_MOUSE_HOTY 2
constexpr int ui_FrameTimeMS = 50;
@@ -270,8 +272,8 @@ bool ui_MousePoll(bool buttons) {
btn_mask = ddio_MouseGetState(&mx, &my, NULL, NULL);
UI_input.last_mx = UI_input.mx;
UI_input.last_my = UI_input.my;
UI_input.mx = mx;
UI_input.my = my;
UI_input.mx = mx / kDefaultMouseScale;
UI_input.my = my / kDefaultMouseScale;
} else if (UI_cursor_show) {
// if bX_count is 0, then repeat processing can occur, otherwise only real mouse events are processed.
if (ddio_MouseGetEvent(&msebtn, &state)) {
@@ -537,6 +539,7 @@ bool ui_HideCursor() {
}
return true; // cursor was hidden before.
}
// set user interface screen resolution
void ui_SetScreenMode(int w, int h) {
UI_screen_width = w;
@@ -544,8 +547,7 @@ void ui_SetScreenMode(int w, int h) {
UI_aspect_x = (float)w / (float)FIXED_SCREEN_WIDTH;
UI_aspect_y = (float)h / (float)FIXED_SCREEN_HEIGHT;
ddio_MouseReset();
// ddio_MouseSetLimits(0,0, UI_screen_width, UI_screen_height);
ddio_MouseSetVCoords(UI_screen_width, UI_screen_height);
ddio_MouseSetVCoords(UI_screen_width * kDefaultMouseScale, UI_screen_height * kDefaultMouseScale);
UI_input.cur_time = timer_GetTime();
// reposition all active open windows to their correct locations in this new resolution
//@@ tUIWindowNode *wndnode = UIWindowList;