From 8dbb03114dd9628303b6be691142a0517f7b688f Mon Sep 17 00:00:00 2001 From: Cameron Gutman Date: Thu, 16 Oct 2014 21:16:12 -0700 Subject: [PATCH] Improve axis scaling algorithm to fix cardinal direction issues --- .../nvstream/input/ControllerPacket.java | 82 +++++++++---------- .../src/com/limelight/utils/Vector2d.java | 47 +++++++++++ 2 files changed, 85 insertions(+), 44 deletions(-) create mode 100644 moonlight-common/src/com/limelight/utils/Vector2d.java diff --git a/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java b/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java index fc3078cc..f1ca1d13 100644 --- a/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java +++ b/moonlight-common/src/com/limelight/nvstream/input/ControllerPacket.java @@ -3,6 +3,8 @@ package com.limelight.nvstream.input; import java.nio.ByteBuffer; import java.nio.ByteOrder; +import com.limelight.utils.Vector2d; + public class ControllerPacket extends InputPacket { public static final byte[] HEADER = { @@ -47,11 +49,7 @@ public class ControllerPacket extends InputPacket { InputPacket.HEADER_LENGTH; // This is the highest value that is read as zero on the PC - public static final short ABS_LS_OFFSET = 7000; - public static final short ABS_RS_OFFSET = 7000; - - public static final double ABS_LS_SCALE_FACTOR = 1 - (ABS_LS_OFFSET / 32768.0); - public static final double ABS_RS_SCALE_FACTOR = 1 - (ABS_RS_OFFSET / 32768.0); + public static final short MIN_MAGNITUDE = 7000; // Set this flag if you want ControllerPacket to handle scaling for you // Note: You MUST properly handle deadzones to use this flag @@ -74,51 +72,47 @@ public class ControllerPacket extends InputPacket { this.buttonFlags = buttonFlags; this.leftTrigger = leftTrigger; this.rightTrigger = rightTrigger; - this.leftStickX = scaleLeftStickAxis(leftStickX); - this.leftStickY = scaleLeftStickAxis(leftStickY); - this.rightStickX = scaleRightStickAxis(rightStickX); - this.rightStickY = scaleRightStickAxis(rightStickY); + + Vector2d leftStick = handleDeadZone(leftStickX, leftStickY); + this.leftStickX = (short) leftStick.getX(); + this.leftStickY = (short) leftStick.getY(); + + Vector2d rightStick = handleDeadZone(rightStickX, rightStickY); + this.rightStickX = (short) rightStick.getX(); + this.rightStickY = (short) rightStick.getY(); } - private static short scaleAxis(int axisValue, short offset, double factor) { - // Exit quit if it's zero - if (axisValue == 0) { - return 0; - } - - // Remember the sign and remove it from the value - int sign = axisValue < 0 ? -1 : 1; - axisValue = Math.abs(axisValue); - - // Scale the initial value - axisValue = (int)(axisValue * factor); - - // Add the offset - axisValue += offset; - - // Correct the value if it's over the limit - if (axisValue > 32767) { - axisValue = 32767; - } - - // Restore sign and return - return (short)(sign * axisValue); - } + private static Vector2d inputVector = new Vector2d(); + private static Vector2d normalizedInputVector = new Vector2d(); - private static short scaleLeftStickAxis(short axisValue) { + // This function is NOT THREAD SAFE! + private static Vector2d handleDeadZone(short x, short y) { + // Get out fast if we're in the dead zone + if (x == 0 && y == 0) { + return Vector2d.ZERO; + } + + // Reinitialize our cached Vector2d object + inputVector.initialize(x, y); + if (enableAxisScaling) { - axisValue = scaleAxis(axisValue, ABS_LS_OFFSET, ABS_LS_SCALE_FACTOR); + // Remember our original magnitude for scaling later + double magnitude = inputVector.getMagnitude(); + + // Scale to hit a minimum magnitude + inputVector.getNormalized(normalizedInputVector); + + normalizedInputVector.setX(normalizedInputVector.getX() * MIN_MAGNITUDE); + normalizedInputVector.setY(normalizedInputVector.getY() * MIN_MAGNITUDE); + + // Now scale the rest of the way + normalizedInputVector.scalarMultiply((32766.0 / MIN_MAGNITUDE) / (32768.0 / magnitude)); + + return normalizedInputVector; } - - return axisValue; - } - - private static short scaleRightStickAxis(short axisValue) { - if (enableAxisScaling) { - axisValue = scaleAxis(axisValue, ABS_RS_OFFSET, ABS_RS_SCALE_FACTOR); + else { + return inputVector; } - - return axisValue; } @Override diff --git a/moonlight-common/src/com/limelight/utils/Vector2d.java b/moonlight-common/src/com/limelight/utils/Vector2d.java new file mode 100644 index 00000000..d01b78ba --- /dev/null +++ b/moonlight-common/src/com/limelight/utils/Vector2d.java @@ -0,0 +1,47 @@ +package com.limelight.utils; + +public class Vector2d { + private float x; + private float y; + private double magnitude; + + public static final Vector2d ZERO = new Vector2d(); + + public Vector2d() { + initialize(0, 0); + } + + public void initialize(float x, float y) { + this.x = x; + this.y = y; + this.magnitude = Math.sqrt(Math.pow(x, 2) + Math.pow(y, 2)); + } + + public double getMagnitude() { + return magnitude; + } + + public void getNormalized(Vector2d vector) { + vector.initialize((float)(x / magnitude), (float)(y / magnitude)); + } + + public void scalarMultiply(double factor) { + initialize((float)(x * factor), (float)(y * factor)); + } + + public void setX(float x) { + initialize(x, this.y); + } + + public void setY(float y) { + initialize(this.x, y); + } + + public float getX() { + return x; + } + + public float getY() { + return y; + } +}