Improve axis scaling algorithm to fix cardinal direction issues

This commit is contained in:
Cameron Gutman 2014-10-16 21:16:12 -07:00
parent 415e96dec6
commit 8dbb03114d
2 changed files with 85 additions and 44 deletions

View File

@ -3,6 +3,8 @@ package com.limelight.nvstream.input;
import java.nio.ByteBuffer; import java.nio.ByteBuffer;
import java.nio.ByteOrder; import java.nio.ByteOrder;
import com.limelight.utils.Vector2d;
public class ControllerPacket extends InputPacket { public class ControllerPacket extends InputPacket {
public static final byte[] HEADER = public static final byte[] HEADER =
{ {
@ -47,11 +49,7 @@ public class ControllerPacket extends InputPacket {
InputPacket.HEADER_LENGTH; InputPacket.HEADER_LENGTH;
// This is the highest value that is read as zero on the PC // 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 MIN_MAGNITUDE = 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);
// Set this flag if you want ControllerPacket to handle scaling for you // Set this flag if you want ControllerPacket to handle scaling for you
// Note: You MUST properly handle deadzones to use this flag // Note: You MUST properly handle deadzones to use this flag
@ -74,51 +72,47 @@ public class ControllerPacket extends InputPacket {
this.buttonFlags = buttonFlags; this.buttonFlags = buttonFlags;
this.leftTrigger = leftTrigger; this.leftTrigger = leftTrigger;
this.rightTrigger = rightTrigger; this.rightTrigger = rightTrigger;
this.leftStickX = scaleLeftStickAxis(leftStickX);
this.leftStickY = scaleLeftStickAxis(leftStickY); Vector2d leftStick = handleDeadZone(leftStickX, leftStickY);
this.rightStickX = scaleRightStickAxis(rightStickX); this.leftStickX = (short) leftStick.getX();
this.rightStickY = scaleRightStickAxis(rightStickY); 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) { private static Vector2d inputVector = new Vector2d();
// Exit quit if it's zero private static Vector2d normalizedInputVector = new Vector2d();
if (axisValue == 0) {
return 0; // 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;
} }
// Remember the sign and remove it from the value // Reinitialize our cached Vector2d object
int sign = axisValue < 0 ? -1 : 1; inputVector.initialize(x, y);
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 short scaleLeftStickAxis(short axisValue) {
if (enableAxisScaling) { 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;
} }
else {
return axisValue; return inputVector;
}
private static short scaleRightStickAxis(short axisValue) {
if (enableAxisScaling) {
axisValue = scaleAxis(axisValue, ABS_RS_OFFSET, ABS_RS_SCALE_FACTOR);
} }
return axisValue;
} }
@Override @Override

View File

@ -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;
}
}