Skip to content

Commit

Permalink
render: Scale relative mouse motion better for logical sizing
Browse files Browse the repository at this point in the history
From hmk:

"When scaling is enabled (e.g. via SDL_RenderSetLogicalSize, size not equal
to window size), mouse motion events are also scaled.  Small motions are
rounded up (SDL_max() when the value after scaling is less than 1), while
larger motions are truncated by the floating point -> integer conversion.

https://hg.libsdl.org/SDL/file/b18197f9bf9d/src/render/SDL_render.c#l658

The end result feels something like mouse reverse mouse acceleration + angle
snapping at low speeds, but less consistent (amount of truncation & rounding
depends on how fast the mouse is moved) and potentially much worse if the
scaling factor is large.  This pretty much makes it useless for anything
where you need precise mouse aiming (think of games).  I suspect this is why
aiming gets so terrible in some games that let you use scaling to reduce the
render resolution (e.g. Ion Fury).

With 4x4 scaling, I can reproduce a situation where it takes three fast flicks
of the mouse across the pad to undo one slow sweep across the pad.  In other
words, extreme reverse acceleration.  This does not happen when scaling is
disabled.

Furthermore, any game that uses relative mouse motion events for 3D camera
rotation probably wants the raw mouse deltas and not a value that depends on
scaling and resolution and rounding and truncation.  Ideal camera rotation
just takes mouse input, multiplies it by sensitivity, and adds it to the
angle-in-radians or whatever measure is used for yaw & pitch.  Pixels and
screen resolution or window dimensions should not be a part of the equation
at all, even if it could be implemented without rounding errors.

[...]

This [patch] completely eliminates angle snapping for me, and makes
sensitivity consistent.  In other words, it's completely usable for, say,
aiming in a first person shooter."

Partially fixes Bugzilla #4811.
  • Loading branch information
hmk committed Apr 10, 2020
1 parent d292f6b commit aa18804
Show file tree
Hide file tree
Showing 2 changed files with 14 additions and 8 deletions.
18 changes: 10 additions & 8 deletions src/render/SDL_render.c
Expand Up @@ -660,15 +660,17 @@ SDL_RendererEventWatch(void *userdata, SDL_Event *event)
event->motion.y -= (int)(viewport.y * renderer->dpi_scale.y);
event->motion.x = (int)(event->motion.x / (scale.x * renderer->dpi_scale.x));
event->motion.y = (int)(event->motion.y / (scale.y * renderer->dpi_scale.y));
if (event->motion.xrel > 0) {
event->motion.xrel = SDL_max(1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
} else if (event->motion.xrel < 0) {
event->motion.xrel = SDL_min(-1, (int)(event->motion.xrel / (scale.x * renderer->dpi_scale.x)));
if (event->motion.xrel != 0) {
float rel = renderer->xrel + event->motion.xrel / (scale.x * renderer->dpi_scale.x);
float trunc = SDL_truncf(rel);
renderer->xrel = rel - trunc;
event->motion.xrel = trunc;
}
if (event->motion.yrel > 0) {
event->motion.yrel = SDL_max(1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
} else if (event->motion.yrel < 0) {
event->motion.yrel = SDL_min(-1, (int)(event->motion.yrel / (scale.y * renderer->dpi_scale.y)));
if (event->motion.yrel != 0) {
float rel = renderer->yrel + event->motion.yrel / (scale.y * renderer->dpi_scale.y);
float trunc = SDL_truncf(rel);
renderer->yrel = rel - trunc;
event->motion.yrel = trunc;
}
}
}
Expand Down
4 changes: 4 additions & 0 deletions src/render/SDL_sysrender.h
Expand Up @@ -189,6 +189,10 @@ struct SDL_Renderer
/* The pixel to point coordinate scale */
SDL_FPoint dpi_scale;

/* Remainder from scaled relative motion */
float xrel;
float yrel;

/* The list of textures */
SDL_Texture *textures;
SDL_Texture *target;
Expand Down

0 comments on commit aa18804

Please sign in to comment.