Feat[Gyro]: Use sensor fusion implementation (#3998)

* Feat[Gyro]: Use sensor fusion implementation

* Fix: Remove time factor

It is pointless when mesuring an absolute rotation, since regardless how big the difference in timing is, we can get the same difference

* Handle ORIENTATION_UNKNOWN

* Cleanup unused timestamp saving code

* Fix[Gyro]: inverted factors on edges

I watch out for the screen surface rotation now

* Fix[Gyro]: update rotation factors only on non unknown cases

* Fix[gyro]: portrait factors on landscape upon start

---------

Co-authored-by: artdeell <ultramaksim@gmail.com>
This commit is contained in:
Boulay Mathias 2023-02-28 22:58:52 +01:00 committed by GitHub
parent a84cd3a5f9
commit 292b56f26f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 41 additions and 22 deletions

View File

@ -1,31 +1,40 @@
package net.kdt.pojavlaunch;
import android.app.Activity;
import android.content.Context;
import android.hardware.Sensor;
import android.hardware.SensorEvent;
import android.hardware.SensorEventListener;
import android.hardware.SensorManager;
import android.view.OrientationEventListener;
import android.view.WindowManager;
import net.kdt.pojavlaunch.prefs.LauncherPreferences;
import org.lwjgl.glfw.CallbackBridge;
public class GyroControl implements SensorEventListener, GrabListener{
private final WindowManager mWindowManager;
private int mSurfaceRotation;
private final SensorManager mSensorManager;
private final Sensor mSensor;
private final OrientationCorrectionListener mCorrectionListener;
private boolean mShouldHandleEvents;
private boolean mFirstPass;
private long mPreviousTimestamp;
private float xFactor; // -1 or 1 depending on device orientation
private float yFactor;
private boolean mSwapXY;
public GyroControl(Context context) {
mSensorManager = (SensorManager) context.getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GYROSCOPE);
mCorrectionListener = new OrientationCorrectionListener(context);
private final float[] mPreviousRotation = new float[16];
private final float[] mCurrentRotation = new float[16];
private final float[] mAngleDifference = new float[3];
public GyroControl(Activity activity) {
mWindowManager = activity.getWindowManager();
mSurfaceRotation = -10;
mSensorManager = (SensorManager) activity.getSystemService(Context.SENSOR_SERVICE);
mSensor = mSensorManager.getDefaultSensor(Sensor.TYPE_GAME_ROTATION_VECTOR);
mCorrectionListener = new OrientationCorrectionListener(activity);
}
public void enable() {
@ -45,21 +54,20 @@ public class GyroControl implements SensorEventListener, GrabListener{
}
@Override
public void onSensorChanged(SensorEvent sensorEvent) {
if(mShouldHandleEvents && sensorEvent.sensor == mSensor) {
float factor = LauncherPreferences.PREF_GYRO_SENSITIVITY;
if(!mFirstPass) {
factor *= (sensorEvent.timestamp - mPreviousTimestamp) * 0.000001;
}else mFirstPass = false;
if(mSwapXY) {
float interm = sensorEvent.values[0];
sensorEvent.values[0] = sensorEvent.values[1];
sensorEvent.values[1] = interm;
}
CallbackBridge.mouseX += sensorEvent.values[0] * factor * xFactor;
CallbackBridge.mouseY += sensorEvent.values[1] * factor * yFactor;
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
mPreviousTimestamp = sensorEvent.timestamp;
if (!mShouldHandleEvents) return;
// Copy the old array content
System.arraycopy(mCurrentRotation, 0, mPreviousRotation, 0, 16);
SensorManager.getRotationMatrixFromVector(mCurrentRotation, sensorEvent.values);
if(mFirstPass){ // Setup initial position
mFirstPass = false;
return;
}
SensorManager.getAngleChange(mAngleDifference, mCurrentRotation, mPreviousRotation);
CallbackBridge.mouseX -= (mAngleDifference[mSwapXY ? 2 : 1] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * xFactor);
CallbackBridge.mouseY += (mAngleDifference[mSwapXY ? 1 : 2] * 1000 * LauncherPreferences.PREF_GYRO_SENSITIVITY * yFactor);
CallbackBridge.sendCursorPos(CallbackBridge.mouseX, CallbackBridge.mouseY);
}
@Override
@ -81,10 +89,21 @@ public class GyroControl implements SensorEventListener, GrabListener{
@Override
public void onOrientationChanged(int i) {
// Force to wait to be in game before setting factors
// Theoretically, one could use the whole interface in portrait...
if(!mShouldHandleEvents) return;
int surfaceRotation = mWindowManager.getDefaultDisplay().getRotation();
if(surfaceRotation == mSurfaceRotation) return;
if(i == OrientationEventListener.ORIENTATION_UNKNOWN) {
return; //change nothing
}
mSurfaceRotation = surfaceRotation;
if((315 < i && i <= 360) || (i < 45) ) {
mSwapXY = true;
xFactor = 1;
yFactor = -1;
yFactor = 1;
}else if(45 < i && i < 135) {
mSwapXY = false;
xFactor = 1;
@ -92,7 +111,7 @@ public class GyroControl implements SensorEventListener, GrabListener{
}else if(135 < i && i < 225) {
mSwapXY = true;
xFactor = -1;
yFactor = 1;
yFactor = -1;
}else if(225 < i && i < 315) {
mSwapXY = false;
xFactor = -1;

View File

@ -54,7 +54,7 @@ public class LauncherPreferences {
public static boolean PREF_JAVA_SANDBOX = true;
public static int PREF_SCALE_FACTOR = 100;
public static boolean PREF_ENALBE_GYRO = false;
public static float PREF_GYRO_SENSITIVITY = 100;
public static float PREF_GYRO_SENSITIVITY = 1f;
public static int PREF_GYRO_SAMPLE_RATE = 16;
public static boolean PREF_GYRO_INVERT_X = false;