summaryrefslogtreecommitdiff
path: root/src/input_common/motion_emu.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/input_common/motion_emu.cpp')
-rw-r--r--src/input_common/motion_emu.cpp58
1 files changed, 34 insertions, 24 deletions
diff --git a/src/input_common/motion_emu.cpp b/src/input_common/motion_emu.cpp
index d4cdf76a3..d4da5596b 100644
--- a/src/input_common/motion_emu.cpp
+++ b/src/input_common/motion_emu.cpp
@@ -18,11 +18,11 @@ namespace InputCommon {
18// Implementation class of the motion emulation device 18// Implementation class of the motion emulation device
19class MotionEmuDevice { 19class MotionEmuDevice {
20public: 20public:
21 MotionEmuDevice(int update_millisecond, float sensitivity) 21 explicit MotionEmuDevice(int update_millisecond_, float sensitivity_)
22 : update_millisecond(update_millisecond), 22 : update_millisecond(update_millisecond_),
23 update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>( 23 update_duration(std::chrono::duration_cast<std::chrono::steady_clock::duration>(
24 std::chrono::milliseconds(update_millisecond))), 24 std::chrono::milliseconds(update_millisecond))),
25 sensitivity(sensitivity), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {} 25 sensitivity(sensitivity_), motion_emu_thread(&MotionEmuDevice::MotionEmuThread, this) {}
26 26
27 ~MotionEmuDevice() { 27 ~MotionEmuDevice() {
28 if (motion_emu_thread.joinable()) { 28 if (motion_emu_thread.joinable()) {
@@ -37,16 +37,18 @@ public:
37 } 37 }
38 38
39 void Tilt(int x, int y) { 39 void Tilt(int x, int y) {
40 auto mouse_move = Common::MakeVec(x, y) - mouse_origin; 40 if (!is_tilting) {
41 if (is_tilting) { 41 return;
42 std::lock_guard guard{tilt_mutex}; 42 }
43 if (mouse_move.x == 0 && mouse_move.y == 0) { 43
44 tilt_angle = 0; 44 std::lock_guard guard{tilt_mutex};
45 } else { 45 const auto mouse_move = Common::MakeVec(x, y) - mouse_origin;
46 tilt_direction = mouse_move.Cast<float>(); 46 if (mouse_move.x == 0 && mouse_move.y == 0) {
47 tilt_angle = 47 tilt_angle = 0;
48 std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f); 48 } else {
49 } 49 tilt_direction = mouse_move.Cast<float>();
50 tilt_angle =
51 std::clamp(tilt_direction.Normalize() * sensitivity, 0.0f, Common::PI * 0.5f);
50 } 52 }
51 } 53 }
52 54
@@ -56,7 +58,7 @@ public:
56 is_tilting = false; 58 is_tilting = false;
57 } 59 }
58 60
59 std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() { 61 Input::MotionStatus GetStatus() {
60 std::lock_guard guard{status_mutex}; 62 std::lock_guard guard{status_mutex};
61 return status; 63 return status;
62 } 64 }
@@ -76,7 +78,7 @@ private:
76 78
77 Common::Event shutdown_event; 79 Common::Event shutdown_event;
78 80
79 std::tuple<Common::Vec3<float>, Common::Vec3<float>> status; 81 Input::MotionStatus status;
80 std::mutex status_mutex; 82 std::mutex status_mutex;
81 83
82 // Note: always keep the thread declaration at the end so that other objects are initialized 84 // Note: always keep the thread declaration at the end so that other objects are initialized
@@ -86,11 +88,10 @@ private:
86 void MotionEmuThread() { 88 void MotionEmuThread() {
87 auto update_time = std::chrono::steady_clock::now(); 89 auto update_time = std::chrono::steady_clock::now();
88 Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0); 90 Common::Quaternion<float> q = Common::MakeQuaternion(Common::Vec3<float>(), 0);
89 Common::Quaternion<float> old_q;
90 91
91 while (!shutdown_event.WaitUntil(update_time)) { 92 while (!shutdown_event.WaitUntil(update_time)) {
92 update_time += update_duration; 93 update_time += update_duration;
93 old_q = q; 94 const Common::Quaternion<float> old_q = q;
94 95
95 { 96 {
96 std::lock_guard guard{tilt_mutex}; 97 std::lock_guard guard{tilt_mutex};
@@ -100,23 +101,32 @@ private:
100 Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle); 101 Common::MakeVec(-tilt_direction.y, 0.0f, tilt_direction.x), tilt_angle);
101 } 102 }
102 103
103 auto inv_q = q.Inverse(); 104 const auto inv_q = q.Inverse();
104 105
105 // Set the gravity vector in world space 106 // Set the gravity vector in world space
106 auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f); 107 auto gravity = Common::MakeVec(0.0f, -1.0f, 0.0f);
107 108
108 // Find the angular rate vector in world space 109 // Find the angular rate vector in world space
109 auto angular_rate = ((q - old_q) * inv_q).xyz * 2; 110 auto angular_rate = ((q - old_q) * inv_q).xyz * 2;
110 angular_rate *= 1000 / update_millisecond / Common::PI * 180; 111 angular_rate *= static_cast<float>(1000 / update_millisecond) / Common::PI * 180.0f;
111 112
112 // Transform the two vectors from world space to 3DS space 113 // Transform the two vectors from world space to 3DS space
113 gravity = QuaternionRotate(inv_q, gravity); 114 gravity = QuaternionRotate(inv_q, gravity);
114 angular_rate = QuaternionRotate(inv_q, angular_rate); 115 angular_rate = QuaternionRotate(inv_q, angular_rate);
115 116
117 // TODO: Calculate the correct rotation vector and orientation matrix
118 const auto matrix4x4 = q.ToMatrix();
119 const auto rotation = Common::MakeVec(0.0f, 0.0f, 0.0f);
120 const std::array orientation{
121 Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]),
122 Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]),
123 Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10]),
124 };
125
116 // Update the sensor state 126 // Update the sensor state
117 { 127 {
118 std::lock_guard guard{status_mutex}; 128 std::lock_guard guard{status_mutex};
119 status = std::make_tuple(gravity, angular_rate); 129 status = std::make_tuple(gravity, angular_rate, rotation, orientation);
120 } 130 }
121 } 131 }
122 } 132 }
@@ -127,11 +137,11 @@ private:
127// can forward all the inputs to the implementation only when it is valid. 137// can forward all the inputs to the implementation only when it is valid.
128class MotionEmuDeviceWrapper : public Input::MotionDevice { 138class MotionEmuDeviceWrapper : public Input::MotionDevice {
129public: 139public:
130 MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) { 140 explicit MotionEmuDeviceWrapper(int update_millisecond, float sensitivity) {
131 device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity); 141 device = std::make_shared<MotionEmuDevice>(update_millisecond, sensitivity);
132 } 142 }
133 143
134 std::tuple<Common::Vec3<float>, Common::Vec3<float>> GetStatus() const override { 144 Input::MotionStatus GetStatus() const override {
135 return device->GetStatus(); 145 return device->GetStatus();
136 } 146 }
137 147
@@ -139,8 +149,8 @@ public:
139}; 149};
140 150
141std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) { 151std::unique_ptr<Input::MotionDevice> MotionEmu::Create(const Common::ParamPackage& params) {
142 int update_period = params.Get("update_period", 100); 152 const int update_period = params.Get("update_period", 100);
143 float sensitivity = params.Get("sensitivity", 0.01f); 153 const float sensitivity = params.Get("sensitivity", 0.01f);
144 auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity); 154 auto device_wrapper = std::make_unique<MotionEmuDeviceWrapper>(update_period, sensitivity);
145 // Previously created device is disconnected here. Having two motion devices for 3DS is not 155 // Previously created device is disconnected here. Having two motion devices for 3DS is not
146 // expected. 156 // expected.