Files
Duy Tran Khanh b9d6e14015 Fix[gyro]: invert axis on upside down orientations
This commit fixes #570

Also fix gyro factor to match 1:1 ratio like the comment
2023-07-06 18:36:49 +07:00

72 lines
2.4 KiB
Objective-C

#import <CoreMotion/CoreMotion.h>
#import <UIKit/UIKit.h>
#import "GyroInput.h"
#import "../SurfaceViewController.h"
#import "../utils.h"
@implementation GyroInput
static CGFloat lastXValue, lastYValue, lastFrameTime;
static CGFloat gyroSensitivity;
static int gyroInvertX;
static BOOL gyroInvertAxis, gyroSwapAxis;
static CMMotionManager* cmInstance;
+ (void)updateOrientation {
UIInterfaceOrientation orientation = UIApplication.sharedApplication.windows[0].windowScene.interfaceOrientation;
gyroInvertAxis =
orientation==UIInterfaceOrientationPortraitUpsideDown ||
orientation==UIInterfaceOrientationLandscapeLeft;
gyroSwapAxis = UIInterfaceOrientationIsPortrait(orientation);
// FIXME: camera jumps upon rotating screen
}
+ (void)updateSensitivity:(int)sensitivity invertXAxis:(BOOL)invertX {
if (cmInstance == nil) {
cmInstance = [[CMMotionManager alloc] init];
}
gyroSensitivity = sensitivity / 100.0;
if (sensitivity > 0) {
gyroInvertX = invertX ? 1 : -1;
[self updateOrientation];
[cmInstance startDeviceMotionUpdates];
} else {
lastXValue = lastYValue = lastFrameTime = 0;
[cmInstance stopDeviceMotionUpdates];
}
}
+ (void)tick {
if (!isGrabbing || gyroSensitivity == 0) {
lastFrameTime = 0;
return;
}
// Compute delta since last tick time
CGFloat frameTime = CACurrentMediaTime();
CGFloat factor = gyroSensitivity;
if (lastFrameTime != 0) {
CGFloat deltaTimeScale = (frameTime - lastFrameTime) / (1.0/60.0); // Scale of 1 = 60Hz
factor *= deltaTimeScale;
}
// 100% sensitivity -> 1:1 ratio between real world and ingame camera
if (gyroInvertAxis) {
factor *= -1;
}
if (gyroSwapAxis) {
lastXValue = cmInstance.deviceMotion.rotationRate.y / (M_PI*90) * windowWidth * factor * gyroInvertX;
lastYValue = -cmInstance.deviceMotion.rotationRate.x / (M_PI*180) * windowHeight * factor;
} else {
lastXValue = cmInstance.deviceMotion.rotationRate.x / (M_PI*180) * windowWidth * factor * gyroInvertX;
lastYValue = cmInstance.deviceMotion.rotationRate.y / (M_PI*90) * windowHeight * factor;
}
SurfaceViewController *vc = (id)(currentWindow().rootViewController);
[vc sendTouchPoint:CGPointMake(lastXValue, lastYValue) withEvent:ACTION_MOVE_MOTION];
lastFrameTime = frameTime;
}
@end