From fdd8d4252c60b055cac2d792b414ba15046d484d Mon Sep 17 00:00:00 2001 From: lizzie Date: Tue, 8 Sep 2026 20:39:39 +0200 Subject: [PATCH] [common] remove unused vector_math.h fluff (#4333) Signed-off-by: lizzie - [x] I have read and followed the [Contribution Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/CONTRIBUTING.md#code-contributions). - [x] I have read and followed the [AI Policy](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/AI.md) - [x] I have read and followed the [Coding Guidelines](https://git.eden-emu.dev/eden-emu/eden/src/branch/master/docs/policies/Coding.md) to the best of my ability. ------------------- We don't use half of this file for anything -- it's dead code also the NEON intrinsic replacements suck -- we are not beating GLM (plus we use registers for decomposition instead of using vec regs like everyone else does, so the "optimizations" dont matter) Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/4333 Reviewed-by: CamilleLaVey Reviewed-by: Maufeat --- src/common/CMakeLists.txt | 1 - src/common/quaternion.h | 79 -- src/common/vector_math.h | 800 ++---------------- .../set/setting_formats/device_settings.h | 9 +- .../set/setting_formats/system_settings.h | 8 +- src/hid_core/frontend/emulated_console.cpp | 4 +- src/hid_core/frontend/emulated_console.h | 13 +- src/hid_core/frontend/emulated_controller.cpp | 4 +- src/hid_core/frontend/emulated_controller.h | 10 +- src/hid_core/frontend/motion_input.cpp | 182 ++-- src/hid_core/frontend/motion_input.h | 44 +- src/hid_core/hid_types.h | 8 +- src/hid_core/resources/shared_memory_format.h | 4 +- .../resources/six_axis/seven_six_axis.cpp | 11 +- .../resources/six_axis/seven_six_axis.h | 8 +- src/hid_core/resources/six_axis/six_axis.cpp | 9 +- src/input_common/drivers/mouse.cpp | 79 +- src/input_common/drivers/mouse.h | 10 +- .../configure_input_player_widget.cpp | 42 +- .../configure_input_player_widget.h | 4 +- 20 files changed, 315 insertions(+), 1014 deletions(-) delete mode 100644 src/common/quaternion.h diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index d90190e6a0..3a6d2acf8a 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -89,7 +89,6 @@ add_library( param_package.h parent_of_member.h point.h - quaternion.h range_map.h range_mutex.h range_sets.h diff --git a/src/common/quaternion.h b/src/common/quaternion.h deleted file mode 100644 index 5bb5f2af08..0000000000 --- a/src/common/quaternion.h +++ /dev/null @@ -1,79 +0,0 @@ -// SPDX-FileCopyrightText: 2016 Citra Emulator Project -// SPDX-License-Identifier: GPL-2.0-or-later - -#pragma once - -#include "common/vector_math.h" - -namespace Common { - -template -class Quaternion { -public: - Vec3 xyz; - T w{}; - - [[nodiscard]] Quaternion Inverse() const { - return {-xyz, w}; - } - - [[nodiscard]] Quaternion operator+(const Quaternion& other) const { - return {xyz + other.xyz, w + other.w}; - } - - [[nodiscard]] Quaternion operator-(const Quaternion& other) const { - return {xyz - other.xyz, w - other.w}; - } - - [[nodiscard]] Quaternion operator*( - const Quaternion& other) const { - return {xyz * other.w + other.xyz * w + Cross(xyz, other.xyz), - w * other.w - Dot(xyz, other.xyz)}; - } - - [[nodiscard]] Quaternion Normalized() const { - T length = std::sqrt(xyz.Length2() + w * w); - return {xyz / length, w / length}; - } - - [[nodiscard]] std::array ToMatrix() const { - const T x2 = xyz[0] * xyz[0]; - const T y2 = xyz[1] * xyz[1]; - const T z2 = xyz[2] * xyz[2]; - - const T xy = xyz[0] * xyz[1]; - const T wz = w * xyz[2]; - const T xz = xyz[0] * xyz[2]; - const T wy = w * xyz[1]; - const T yz = xyz[1] * xyz[2]; - const T wx = w * xyz[0]; - - return {1.0f - 2.0f * (y2 + z2), - 2.0f * (xy + wz), - 2.0f * (xz - wy), - 0.0f, - 2.0f * (xy - wz), - 1.0f - 2.0f * (x2 + z2), - 2.0f * (yz + wx), - 0.0f, - 2.0f * (xz + wy), - 2.0f * (yz - wx), - 1.0f - 2.0f * (x2 + y2), - 0.0f, - 0.0f, - 0.0f, - 0.0f, - 1.0f}; - } -}; - -template -[[nodiscard]] auto QuaternionRotate(const Quaternion& q, const Vec3& v) { - return v + 2 * Cross(q.xyz, Cross(q.xyz, v) + v * q.w); -} - -[[nodiscard]] inline Quaternion MakeQuaternion(const Vec3& axis, float angle) { - return {axis * std::sin(angle / 2), std::cos(angle / 2)}; -} - -} // namespace Common diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 829a79ce5a..f99fdcb01e 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: 2014 Tony Wasserka @@ -7,752 +7,128 @@ #pragma once -#ifdef __ARM_NEON -#include -#endif - #include #include namespace Common { -template -class Vec2; -template -class Vec3; -template -class Vec4; - -template -class Vec2 { -public: - T x{}; - T y{}; - - constexpr Vec2() = default; - constexpr Vec2(const T& x_, const T& y_) : x(x_), y(y_) {} - - template - [[nodiscard]] constexpr Vec2 Cast() const { - return Vec2(static_cast(x), static_cast(y)); - } - - [[nodiscard]] static constexpr Vec2 AssignToAll(const T& f) { - return Vec2{f, f}; - } - - [[nodiscard]] constexpr Vec2 operator+(const Vec2& other) const { - return {x + other.x, y + other.y}; - } - constexpr Vec2& operator+=(const Vec2& other) { - x += other.x; - y += other.y; - return *this; - } - [[nodiscard]] constexpr Vec2 operator-(const Vec2& other) const { - return {x - other.x, y - other.y}; - } - constexpr Vec2& operator-=(const Vec2& other) { - x -= other.x; - y -= other.y; - return *this; - } - - template - [[nodiscard]] constexpr Vec2, U>> operator-() const { - return {-x, -y}; - } - [[nodiscard]] constexpr Vec2 operator*(const Vec2& other) const { - return {x * other.x, y * other.y}; - } - - template - [[nodiscard]] constexpr Vec2 operator*(const V& f) const { - using TV = decltype(T{} * V{}); - using C = std::common_type_t; - - return { - static_cast(static_cast(x) * static_cast(f)), - static_cast(static_cast(y) * static_cast(f)), - }; - } - - template - constexpr Vec2& operator*=(const V& f) { - *this = *this * f; - return *this; - } - - template - [[nodiscard]] constexpr Vec2 operator/(const V& f) const { - using TV = decltype(T{} / V{}); - using C = std::common_type_t; - - return { - static_cast(static_cast(x) / static_cast(f)), - static_cast(static_cast(y) / static_cast(f)), - }; - } - - template - constexpr Vec2& operator/=(const V& f) { - *this = *this / f; - return *this; - } - - [[nodiscard]] constexpr T Length2() const { - return x * x + y * y; - } - - // Only implemented for T=float - [[nodiscard]] float Length() const; - [[nodiscard]] float Normalize(); // returns the previous length, which is often useful - - [[nodiscard]] constexpr T& operator[](std::size_t i) { - return *((&x) + i); - } - [[nodiscard]] constexpr const T& operator[](std::size_t i) const { - return *((&x) + i); - } - - constexpr void SetZero() { - x = 0; - y = 0; - } - - // Common aliases: UV (texel coordinates), ST (texture coordinates) - [[nodiscard]] constexpr T& u() { - return x; - } - [[nodiscard]] constexpr T& v() { - return y; - } - [[nodiscard]] constexpr T& s() { - return x; - } - [[nodiscard]] constexpr T& t() { - return y; - } - - [[nodiscard]] constexpr const T& u() const { - return x; - } - [[nodiscard]] constexpr const T& v() const { - return y; - } - [[nodiscard]] constexpr const T& s() const { - return x; - } - [[nodiscard]] constexpr const T& t() const { - return y; - } - - // swizzlers - create a subvector of specific components - [[nodiscard]] constexpr Vec2 yx() const { - return Vec2(y, x); - } - [[nodiscard]] constexpr Vec2 vu() const { - return Vec2(y, x); - } - [[nodiscard]] constexpr Vec2 ts() const { - return Vec2(y, x); - } -}; - -template -[[nodiscard]] constexpr Vec2 operator*(const V& f, const Vec2& vec) { - using C = std::common_type_t; - - return Vec2(static_cast(static_cast(f) * static_cast(vec.x)), - static_cast(static_cast(f) * static_cast(vec.y))); -} - -using Vec2f = Vec2; - -template <> -inline float Vec2::Length() const { - return std::sqrt(x * x + y * y); -} - -template <> -inline float Vec2::Normalize() { - float length = Length(); - *this /= length; - return length; -} - -template -class Vec3 { +template +class Vec { public: - T x{}; - T y{}; - T z{}; + std::array elems{}; - constexpr Vec3() = default; - constexpr Vec3(const T& x_, const T& y_, const T& z_) : x(x_), y(y_), z(z_) {} - - template - [[nodiscard]] constexpr Vec3 Cast() const { - return Vec3(static_cast(x), static_cast(y), static_cast(z)); - } - - [[nodiscard]] static constexpr Vec3 AssignToAll(const T& f) { - return Vec3(f, f, f); - } + constexpr Vec() = default; + constexpr Vec(T e0) noexcept : elems{e0} {} + constexpr Vec(T e0, T e1) noexcept : elems{e0, e1} {} + constexpr Vec(T e0, T e1, T e2) noexcept : elems{e0, e1, e2} {} + constexpr Vec(T e0, T e1, T e2, T e4) noexcept : elems{e0, e1, e2, e4} {} + //explicit constexpr Vec(const std::initializer_list elems_) noexcept : elems{elems_} {} - [[nodiscard]] constexpr Vec3 operator+(const Vec3& other) const { - return {x + other.x, y + other.y, z + other.z}; + [[nodiscard]] constexpr Vec operator+(const Vec o) const noexcept { + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = elems[i] + o.elems[i]; + return r; } + constexpr Vec operator+=(const Vec o) noexcept { return *this = *this + o; } - constexpr Vec3& operator+=(const Vec3& other) { - x += other.x; - y += other.y; - z += other.z; - return *this; - } - - [[nodiscard]] constexpr Vec3 operator-(const Vec3& other) const { - return {x - other.x, y - other.y, z - other.z}; - } - - constexpr Vec3& operator-=(const Vec3& other) { - x -= other.x; - y -= other.y; - z -= other.z; - return *this; + [[nodiscard]] constexpr Vec operator-(const Vec o) const noexcept { + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = elems[i] - o.elems[i]; + return r; } + constexpr Vec operator-=(const Vec o) noexcept { return *this = *this - o; } template - [[nodiscard]] constexpr Vec3, U>> operator-() const { - return {-x, -y, -z}; + [[nodiscard]] constexpr Vec, U>, N> operator-() const noexcept { + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = -elems[i]; + return r; } - [[nodiscard]] constexpr Vec3 operator*(const Vec3& other) const { - return {x * other.x, y * other.y, z * other.z}; + [[nodiscard]] constexpr Vec operator*(const Vec o) const noexcept { + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = elems[i] * o.elems[i]; + return r; } - template - [[nodiscard]] constexpr Vec3 operator*(const V& f) const { + [[nodiscard]] constexpr Vec operator*(const V f) const noexcept { using TV = decltype(T{} * V{}); using C = std::common_type_t; - - return { - static_cast(static_cast(x) * static_cast(f)), - static_cast(static_cast(y) * static_cast(f)), - static_cast(static_cast(z) * static_cast(f)), - }; + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = TV(C(elems[i]) * C(f)); + return r; } - template - constexpr Vec3& operator*=(const V& f) { - *this = *this * f; - return *this; - } + constexpr Vec operator*=(const V f) noexcept { return *this = *this * f; } + template - [[nodiscard]] constexpr Vec3 operator/(const V& f) const { + [[nodiscard]] constexpr Vec operator/(const V f) const noexcept { using TV = decltype(T{} / V{}); using C = std::common_type_t; - - return { - static_cast(static_cast(x) / static_cast(f)), - static_cast(static_cast(y) / static_cast(f)), - static_cast(static_cast(z) / static_cast(f)), - }; + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = TV(C(elems[i]) / C(f)); + return r; } - template - constexpr Vec3& operator/=(const V& f) { - *this = *this / f; - return *this; - } - - void RotateFromOrigin(float roll, float pitch, float yaw) { - float temp = y; - y = std::cos(roll) * y - std::sin(roll) * z; - z = std::sin(roll) * temp + std::cos(roll) * z; - - temp = x; - x = std::cos(pitch) * x + std::sin(pitch) * z; - z = -std::sin(pitch) * temp + std::cos(pitch) * z; - - temp = x; - x = std::cos(yaw) * x - std::sin(yaw) * y; - y = std::sin(yaw) * temp + std::cos(yaw) * y; - } + constexpr Vec operator/=(const V f) noexcept { return *this = *this / f; } - [[nodiscard]] constexpr T Length2() const { - return x * x + y * y + z * z; + [[nodiscard]] constexpr T Length2() const noexcept { + T r{}; + for (size_t i = 0; i < N; ++i) + r += elems[i] * elems[i]; + return r; } - // Only implemented for T=float - [[nodiscard]] float Length() const; - [[nodiscard]] Vec3 Normalized() const; - [[nodiscard]] float Normalize(); // returns the previous length, which is often useful - - [[nodiscard]] constexpr T& operator[](std::size_t i) { - return *((&x) + i); - } - - [[nodiscard]] constexpr const T& operator[](std::size_t i) const { - return *((&x) + i); - } - - constexpr void SetZero() { - x = 0; - y = 0; - z = 0; - } - - // Common aliases: UVW (texel coordinates), RGB (colors), STQ (texture coordinates) - [[nodiscard]] constexpr T& u() { - return x; - } - [[nodiscard]] constexpr T& v() { - return y; - } - [[nodiscard]] constexpr T& w() { - return z; - } - - [[nodiscard]] constexpr T& r() { - return x; - } - [[nodiscard]] constexpr T& g() { - return y; - } - [[nodiscard]] constexpr T& b() { - return z; - } - - [[nodiscard]] constexpr T& s() { - return x; - } - [[nodiscard]] constexpr T& t() { - return y; - } - [[nodiscard]] constexpr T& q() { - return z; - } - - [[nodiscard]] constexpr const T& u() const { - return x; - } - [[nodiscard]] constexpr const T& v() const { - return y; - } - [[nodiscard]] constexpr const T& w() const { - return z; - } - - [[nodiscard]] constexpr const T& r() const { - return x; - } - [[nodiscard]] constexpr const T& g() const { - return y; - } - [[nodiscard]] constexpr const T& b() const { - return z; - } - - [[nodiscard]] constexpr const T& s() const { - return x; - } - [[nodiscard]] constexpr const T& t() const { - return y; - } - [[nodiscard]] constexpr const T& q() const { - return z; - } - -// swizzlers - create a subvector of specific components -// e.g. Vec2 uv() { return Vec2(x,y); } -// _DEFINE_SWIZZLER2 defines a single such function, DEFINE_SWIZZLER2 defines all of them for all -// component names (x<->r) and permutations (xy<->yx) -#define _DEFINE_SWIZZLER2(a, b, name) \ - [[nodiscard]] constexpr Vec2 name() const { return Vec2(a, b); } -#define DEFINE_SWIZZLER2(a, b, a2, b2, a3, b3, a4, b4) \ - _DEFINE_SWIZZLER2(a, b, a##b); \ - _DEFINE_SWIZZLER2(a, b, a2##b2); \ - _DEFINE_SWIZZLER2(a, b, a3##b3); \ - _DEFINE_SWIZZLER2(a, b, a4##b4); \ - _DEFINE_SWIZZLER2(b, a, b##a); \ - _DEFINE_SWIZZLER2(b, a, b2##a2); \ - _DEFINE_SWIZZLER2(b, a, b3##a3); \ - _DEFINE_SWIZZLER2(b, a, b4##a4) - - DEFINE_SWIZZLER2(x, y, r, g, u, v, s, t); - DEFINE_SWIZZLER2(x, z, r, b, u, w, s, q); - DEFINE_SWIZZLER2(y, z, g, b, v, w, t, q); -#undef DEFINE_SWIZZLER2 -#undef _DEFINE_SWIZZLER2 -}; - -template -[[nodiscard]] constexpr Vec3 operator*(const V& f, const Vec3& vec) { - using C = std::common_type_t; - - return Vec3(static_cast(static_cast(f) * static_cast(vec.x)), - static_cast(static_cast(f) * static_cast(vec.y)), - static_cast(static_cast(f) * static_cast(vec.z))); -} - -template <> -inline float Vec3::Length() const { - return std::sqrt(x * x + y * y + z * z); -} - -template <> -inline Vec3 Vec3::Normalized() const { - return *this / Length(); -} - -template <> -inline float Vec3::Normalize() { - float length = Length(); - *this /= length; - return length; -} - -using Vec3f = Vec3; - -template -class Vec4 { -public: - T x{}; - T y{}; - T z{}; - T w{}; - - constexpr Vec4() = default; - constexpr Vec4(const T& x_, const T& y_, const T& z_, const T& w_) - : x(x_), y(y_), z(z_), w(w_) {} - - template - [[nodiscard]] constexpr Vec4 Cast() const { - return Vec4(static_cast(x), static_cast(y), static_cast(z), - static_cast(w)); - } - - [[nodiscard]] static constexpr Vec4 AssignToAll(const T& f) { - return Vec4(f, f, f, f); - } - - [[nodiscard]] constexpr Vec4 operator+(const Vec4& other) const { - return {x + other.x, y + other.y, z + other.z, w + other.w}; - } - - constexpr Vec4& operator+=(const Vec4& other) { - x += other.x; - y += other.y; - z += other.z; - w += other.w; - return *this; - } - - [[nodiscard]] constexpr Vec4 operator-(const Vec4& other) const { - return {x - other.x, y - other.y, z - other.z, w - other.w}; - } - - constexpr Vec4& operator-=(const Vec4& other) { - x -= other.x; - y -= other.y; - z -= other.z; - w -= other.w; - return *this; - } - - template - [[nodiscard]] constexpr Vec4, U>> operator-() const { - return {-x, -y, -z, -w}; - } - - [[nodiscard]] constexpr Vec4 operator*(const Vec4& other) const { - return {x * other.x, y * other.y, z * other.z, w * other.w}; - } - - template - [[nodiscard]] constexpr Vec4 operator*(const V& f) const { - using TV = decltype(T{} * V{}); - using C = std::common_type_t; - - return { - static_cast(static_cast(x) * static_cast(f)), - static_cast(static_cast(y) * static_cast(f)), - static_cast(static_cast(z) * static_cast(f)), - static_cast(static_cast(w) * static_cast(f)), - }; - } - - template - constexpr Vec4& operator*=(const V& f) { - *this = *this * f; - return *this; - } - - template - [[nodiscard]] constexpr Vec4 operator/(const V& f) const { - using TV = decltype(T{} / V{}); - using C = std::common_type_t; - + [[nodiscard]] T Length() const { return T(std::sqrt(float(Length2()))); } + [[nodiscard]] Vec Normalized() const { return *this / Length(); } + [[nodiscard]] constexpr T& operator[](std::size_t i) noexcept { return elems[i]; } + [[nodiscard]] constexpr const T& operator[](std::size_t i) const noexcept { return elems[i]; } + + [[nodiscard]] std::array ToMatrix() const { + const T x2 = elems[0] * elems[0]; + const T y2 = elems[1] * elems[1]; + const T z2 = elems[2] * elems[2]; + + const T xy = elems[0] * elems[1]; + const T wz = elems[3] * elems[2]; + const T xz = elems[0] * elems[2]; + const T wy = elems[3] * elems[1]; + const T yz = elems[1] * elems[2]; + const T wx = elems[3] * elems[0]; return { - static_cast(static_cast(x) / static_cast(f)), - static_cast(static_cast(y) / static_cast(f)), - static_cast(static_cast(z) / static_cast(f)), - static_cast(static_cast(w) / static_cast(f)), + 1.0f - 2.0f * (y2 + z2), + 2.0f * (xy + wz), + 2.0f * (xz - wy), + 0.0f, + 2.0f * (xy - wz), + 1.0f - 2.0f * (x2 + z2), + 2.0f * (yz + wx), + 0.0f, + 2.0f * (xz + wy), + 2.0f * (yz - wx), + 1.0f - 2.0f * (x2 + y2), + 0.0f, + 0.0f, + 0.0f, + 0.0f, + 1.0f }; } - - template - constexpr Vec4& operator/=(const V& f) { - *this = *this / f; - return *this; - } - - [[nodiscard]] constexpr T Length2() const { - return x * x + y * y + z * z + w * w; - } - - [[nodiscard]] constexpr T& operator[](std::size_t i) { - return *((&x) + i); - } - - [[nodiscard]] constexpr const T& operator[](std::size_t i) const { - return *((&x) + i); - } - - constexpr void SetZero() { - x = 0; - y = 0; - z = 0; - w = 0; - } - - // Common alias: RGBA (colors) - [[nodiscard]] constexpr T& r() { - return x; - } - [[nodiscard]] constexpr T& g() { - return y; - } - [[nodiscard]] constexpr T& b() { - return z; - } - [[nodiscard]] constexpr T& a() { - return w; - } - - [[nodiscard]] constexpr const T& r() const { - return x; - } - [[nodiscard]] constexpr const T& g() const { - return y; - } - [[nodiscard]] constexpr const T& b() const { - return z; - } - [[nodiscard]] constexpr const T& a() const { - return w; - } - -// Swizzlers - Create a subvector of specific components -// e.g. Vec2 uv() { return Vec2(x,y); } - -// _DEFINE_SWIZZLER2 defines a single such function -// DEFINE_SWIZZLER2_COMP1 defines one-component functions for all component names (x<->r) -// DEFINE_SWIZZLER2_COMP2 defines two component functions for all component names (x<->r) and -// permutations (xy<->yx) -#define _DEFINE_SWIZZLER2(a, b, name) \ - [[nodiscard]] constexpr Vec2 name() const { return Vec2(a, b); } -#define DEFINE_SWIZZLER2_COMP1(a, a2) \ - _DEFINE_SWIZZLER2(a, a, a##a); \ - _DEFINE_SWIZZLER2(a, a, a2##a2) -#define DEFINE_SWIZZLER2_COMP2(a, b, a2, b2) \ - _DEFINE_SWIZZLER2(a, b, a##b); \ - _DEFINE_SWIZZLER2(a, b, a2##b2); \ - _DEFINE_SWIZZLER2(b, a, b##a); \ - _DEFINE_SWIZZLER2(b, a, b2##a2) - - DEFINE_SWIZZLER2_COMP2(x, y, r, g); - DEFINE_SWIZZLER2_COMP2(x, z, r, b); - DEFINE_SWIZZLER2_COMP2(x, w, r, a); - DEFINE_SWIZZLER2_COMP2(y, z, g, b); - DEFINE_SWIZZLER2_COMP2(y, w, g, a); - DEFINE_SWIZZLER2_COMP2(z, w, b, a); - DEFINE_SWIZZLER2_COMP1(x, r); - DEFINE_SWIZZLER2_COMP1(y, g); - DEFINE_SWIZZLER2_COMP1(z, b); - DEFINE_SWIZZLER2_COMP1(w, a); -#undef DEFINE_SWIZZLER2_COMP1 -#undef DEFINE_SWIZZLER2_COMP2 -#undef _DEFINE_SWIZZLER2 - -#define _DEFINE_SWIZZLER3(a, b, c, name) \ - [[nodiscard]] constexpr Vec3 name() const { return Vec3(a, b, c); } -#define DEFINE_SWIZZLER3_COMP1(a, a2) \ - _DEFINE_SWIZZLER3(a, a, a, a##a##a); \ - _DEFINE_SWIZZLER3(a, a, a, a2##a2##a2) -#define DEFINE_SWIZZLER3_COMP3(a, b, c, a2, b2, c2) \ - _DEFINE_SWIZZLER3(a, b, c, a##b##c); \ - _DEFINE_SWIZZLER3(a, c, b, a##c##b); \ - _DEFINE_SWIZZLER3(b, a, c, b##a##c); \ - _DEFINE_SWIZZLER3(b, c, a, b##c##a); \ - _DEFINE_SWIZZLER3(c, a, b, c##a##b); \ - _DEFINE_SWIZZLER3(c, b, a, c##b##a); \ - _DEFINE_SWIZZLER3(a, b, c, a2##b2##c2); \ - _DEFINE_SWIZZLER3(a, c, b, a2##c2##b2); \ - _DEFINE_SWIZZLER3(b, a, c, b2##a2##c2); \ - _DEFINE_SWIZZLER3(b, c, a, b2##c2##a2); \ - _DEFINE_SWIZZLER3(c, a, b, c2##a2##b2); \ - _DEFINE_SWIZZLER3(c, b, a, c2##b2##a2) - - DEFINE_SWIZZLER3_COMP3(x, y, z, r, g, b); - DEFINE_SWIZZLER3_COMP3(x, y, w, r, g, a); - DEFINE_SWIZZLER3_COMP3(x, z, w, r, b, a); - DEFINE_SWIZZLER3_COMP3(y, z, w, g, b, a); - DEFINE_SWIZZLER3_COMP1(x, r); - DEFINE_SWIZZLER3_COMP1(y, g); - DEFINE_SWIZZLER3_COMP1(z, b); - DEFINE_SWIZZLER3_COMP1(w, a); -#undef DEFINE_SWIZZLER3_COMP1 -#undef DEFINE_SWIZZLER3_COMP3 -#undef _DEFINE_SWIZZLER3 }; -template -[[nodiscard]] constexpr Vec4 operator*(const V& f, const Vec4& vec) { - using TV = decltype(V{} * T{}); +template +[[nodiscard]] constexpr Vec operator*(const V f, const Vec v) noexcept { using C = std::common_type_t; - - return { - static_cast(static_cast(f) * static_cast(vec.x)), - static_cast(static_cast(f) * static_cast(vec.y)), - static_cast(static_cast(f) * static_cast(vec.z)), - static_cast(static_cast(f) * static_cast(vec.w)), - }; -} - -using Vec4f = Vec4; - -template -constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec2& a, const Vec2& b) { - return a.x * b.x + a.y * b.y; -} - -template -[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec3& a, const Vec3& b) { - return a.x * b.x + a.y * b.y + a.z * b.z; -} - -template -[[nodiscard]] constexpr decltype(T{} * T{} + T{} * T{}) Dot(const Vec4& a, const Vec4& b) { - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -} - -template <> -[[nodiscard]] inline float Dot(const Vec4& a, const Vec4& b) { -#ifdef __ARM_NEON - float32x4_t va = vld1q_f32(&a.x); - float32x4_t vb = vld1q_f32(&b.x); - float32x4_t result = vmulq_f32(va, vb); -#if defined(__aarch64__) // Use vaddvq_f32 in ARMv8 architectures - return vaddvq_f32(result); -#else // Use manual addition for older architectures - float32x2_t sum2 = vadd_f32(vget_high_f32(result), vget_low_f32(result)); - return vget_lane_f32(vpadd_f32(sum2, sum2), 0); -#endif -#else - return a.x * b.x + a.y * b.y + a.z * b.z + a.w * b.w; -#endif -} - -template -[[nodiscard]] constexpr Vec3 Cross(const Vec3& a, - const Vec3& b) { - return {a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x}; -} - -// linear interpolation via float: 0.0=begin, 1.0=end -template -[[nodiscard]] constexpr decltype(X{} * float{} + X{} * float{}) Lerp(const X& begin, const X& end, - const float t) { - return begin * (1.f - t) + end * t; -} - -// linear interpolation via int: 0=begin, base=end -template -[[nodiscard]] constexpr decltype((X{} * int{} + X{} * int{}) / base) LerpInt(const X& begin, - const X& end, - const int t) { - return (begin * (base - t) + end * t) / base; -} - -// bilinear interpolation. s is for interpolating x00-x01 and x10-x11, and t is for the second -// interpolation. -template -[[nodiscard]] constexpr auto BilinearInterp(const X& x00, const X& x01, const X& x10, const X& x11, - const float s, const float t) { - auto y0 = Lerp(x00, x01, s); - auto y1 = Lerp(x10, x11, s); - return Lerp(y0, y1, t); -} - -// Utility vector factories -template -[[nodiscard]] constexpr Vec2 MakeVec(const T& x, const T& y) { - return Vec2{x, y}; -} - -template -[[nodiscard]] constexpr Vec3 MakeVec(const T& x, const T& y, const T& z) { - return Vec3{x, y, z}; -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const T& x, const T& y, const Vec2& zw) { - return MakeVec(x, y, zw[0], zw[1]); -} - -template -[[nodiscard]] constexpr Vec3 MakeVec(const Vec2& xy, const T& z) { - return MakeVec(xy[0], xy[1], z); -} - -template -[[nodiscard]] constexpr Vec3 MakeVec(const T& x, const Vec2& yz) { - return MakeVec(x, yz[0], yz[1]); -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const T& x, const T& y, const T& z, const T& w) { - return Vec4{x, y, z, w}; -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const Vec2& xy, const T& z, const T& w) { - return MakeVec(xy[0], xy[1], z, w); -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const T& x, const Vec2& yz, const T& w) { - return MakeVec(x, yz[0], yz[1], w); -} - -// NOTE: This has priority over "Vec2> MakeVec(const Vec2& x, const Vec2& y)". -// Even if someone wanted to use an odd object like Vec2>, the compiler would error -// out soon enough due to misuse of the returned structure. -template -[[nodiscard]] constexpr Vec4 MakeVec(const Vec2& xy, const Vec2& zw) { - return MakeVec(xy[0], xy[1], zw[0], zw[1]); -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const Vec3& xyz, const T& w) { - return MakeVec(xyz[0], xyz[1], xyz[2], w); -} - -template -[[nodiscard]] constexpr Vec4 MakeVec(const T& x, const Vec3& yzw) { - return MakeVec(x, yzw[0], yzw[1], yzw[2]); + Vec r{}; + for (size_t i = 0; i < N; ++i) + r.elems[i] = T(C(f) * C(v.elems[i])); + return r; } } // namespace Common diff --git a/src/core/hle/service/set/setting_formats/device_settings.h b/src/core/hle/service/set/setting_formats/device_settings.h index 2827756f6a..8dcfcd7cef 100644 --- a/src/core/hle/service/set/setting_formats/device_settings.h +++ b/src/core/hle/service/set/setting_formats/device_settings.h @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later @@ -30,15 +33,15 @@ struct DeviceSettings { INSERT_PADDING_BYTES(0x20); // Reserved // nn::settings::system::ConsoleSixAxisSensorAccelerationBias - Common::Vec3 console_six_axis_sensor_acceleration_bias; + Common::Vec console_six_axis_sensor_acceleration_bias; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias - Common::Vec3 console_six_axis_sensor_angular_velocity_bias; + Common::Vec console_six_axis_sensor_angular_velocity_bias; // nn::settings::system::ConsoleSixAxisSensorAccelerationGain std::array console_six_axis_sensor_acceleration_gain; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain std::array console_six_axis_sensor_angular_velocity_gain; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias - Common::Vec3 console_six_axis_sensor_angular_velocity_time_bias; + Common::Vec console_six_axis_sensor_angular_velocity_time_bias; // nn::settings::system::ConsoleSixAxisSensorAngularAcceleration std::array console_six_axis_sensor_angular_acceleration; }; diff --git a/src/core/hle/service/set/setting_formats/system_settings.h b/src/core/hle/service/set/setting_formats/system_settings.h index 75deb1a93f..206c81a7dd 100644 --- a/src/core/hle/service/set/setting_formats/system_settings.h +++ b/src/core/hle/service/set/setting_formats/system_settings.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2018 yuzu Emulator Project @@ -153,15 +153,15 @@ struct SystemSettings { INSERT_PADDING_BYTES(0x7FF8); // Reserved // nn::settings::system::ConsoleSixAxisSensorAccelerationBias - Common::Vec3 console_six_axis_sensor_acceleration_bias; + Common::Vec console_six_axis_sensor_acceleration_bias; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityBias - Common::Vec3 console_six_axis_sensor_angular_velocity_bias; + Common::Vec console_six_axis_sensor_angular_velocity_bias; // nn::settings::system::ConsoleSixAxisSensorAccelerationGain std::array console_six_axis_sensor_acceleration_gain; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityGain std::array console_six_axis_sensor_angular_velocity_gain; // nn::settings::system::ConsoleSixAxisSensorAngularVelocityTimeBias - Common::Vec3 console_six_axis_sensor_angular_velocity_time_bias; + Common::Vec console_six_axis_sensor_angular_velocity_time_bias; // nn::settings::system::ConsoleSixAxisSensorAngularAcceleration std::array console_six_axis_sensor_angular_velocity_acceleration; INSERT_PADDING_BYTES(0x70); // Reserved diff --git a/src/hid_core/frontend/emulated_console.cpp b/src/hid_core/frontend/emulated_console.cpp index 92e99a1f54..fd34233122 100644 --- a/src/hid_core/frontend/emulated_console.cpp +++ b/src/hid_core/frontend/emulated_console.cpp @@ -170,12 +170,12 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) { auto& emulated = console.motion_values.emulated; raw_status = TransformToMotion(callback); - emulated.SetAcceleration(Common::Vec3f{ + emulated.SetAcceleration(Common::Vec{ raw_status.accel.x.value, raw_status.accel.y.value, raw_status.accel.z.value, }); - emulated.SetGyroscope(Common::Vec3f{ + emulated.SetGyroscope(Common::Vec{ raw_status.gyro.x.value, raw_status.gyro.y.value, raw_status.gyro.z.value, diff --git a/src/hid_core/frontend/emulated_console.h b/src/hid_core/frontend/emulated_console.h index ca7d7dd8fc..9e2f7e2c1b 100644 --- a/src/hid_core/frontend/emulated_console.h +++ b/src/hid_core/frontend/emulated_console.h @@ -18,7 +18,6 @@ #include "common/input.h" #include "common/param_package.h" #include "common/point.h" -#include "common/quaternion.h" #include "common/vector_math.h" #include "hid_core/frontend/motion_input.h" #include "hid_core/hid_types.h" @@ -43,12 +42,12 @@ using TouchValues = std::array; // Contains all motion related data that is used on the services struct ConsoleMotion { - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - std::array orientation{}; - Common::Quaternion quaternion{}; - Common::Vec3f gyro_bias{}; + Common::Vec accel{}; + Common::Vec gyro{}; + Common::Vec rotation{}; + std::array, 3> orientation{}; + Common::Vec quaternion{}; + Common::Vec gyro_bias{}; f32 verticalization_error{}; bool is_at_rest{}; }; diff --git a/src/hid_core/frontend/emulated_controller.cpp b/src/hid_core/frontend/emulated_controller.cpp index 36c9a0f02f..1092970ee8 100644 --- a/src/hid_core/frontend/emulated_controller.cpp +++ b/src/hid_core/frontend/emulated_controller.cpp @@ -1051,12 +1051,12 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback auto& emulated = controller.motion_values[index].emulated; raw_status = TransformToMotion(callback); - emulated.SetAcceleration(Common::Vec3f{ + emulated.SetAcceleration(Common::Vec{ raw_status.accel.x.value, raw_status.accel.y.value, raw_status.accel.z.value, }); - emulated.SetGyroscope(Common::Vec3f{ + emulated.SetGyroscope(Common::Vec{ raw_status.gyro.x.value, raw_status.gyro.y.value, raw_status.gyro.z.value, diff --git a/src/hid_core/frontend/emulated_controller.h b/src/hid_core/frontend/emulated_controller.h index d98ed3df3c..7a2291b8a4 100644 --- a/src/hid_core/frontend/emulated_controller.h +++ b/src/hid_core/frontend/emulated_controller.h @@ -107,11 +107,11 @@ struct RingSensorForce { using NfcState = Common::Input::NfcStatus; struct ControllerMotion { - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - Common::Vec3f euler{}; - std::array orientation{}; + Common::Vec accel{}; + Common::Vec gyro{}; + Common::Vec rotation{}; + Common::Vec euler{}; + std::array, 3> orientation{}; bool is_at_rest{}; }; diff --git a/src/hid_core/frontend/motion_input.cpp b/src/hid_core/frontend/motion_input.cpp index a1e09e3ce9..1dcb910a50 100644 --- a/src/hid_core/frontend/motion_input.cpp +++ b/src/hid_core/frontend/motion_input.cpp @@ -26,20 +26,19 @@ void MotionInput::SetPID(f32 new_kp, f32 new_ki, f32 new_kd) { kd = new_kd; } -void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) { +void MotionInput::SetAcceleration(const Common::Vec& acceleration) { accel = acceleration; - - accel.x = std::clamp(accel.x, -AccelMaxValue, AccelMaxValue); - accel.y = std::clamp(accel.y, -AccelMaxValue, AccelMaxValue); - accel.z = std::clamp(accel.z, -AccelMaxValue, AccelMaxValue); + accel[0] = std::clamp(accel[0], -AccelMaxValue, AccelMaxValue); + accel[1] = std::clamp(accel[1], -AccelMaxValue, AccelMaxValue); + accel[2] = std::clamp(accel[2], -AccelMaxValue, AccelMaxValue); } -void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { +void MotionInput::SetGyroscope(const Common::Vec& gyroscope) { gyro = gyroscope - gyro_bias; - gyro.x = std::clamp(gyro.x, -GyroMaxValue, GyroMaxValue); - gyro.y = std::clamp(gyro.y, -GyroMaxValue, GyroMaxValue); - gyro.z = std::clamp(gyro.z, -GyroMaxValue, GyroMaxValue); + gyro[0] = std::clamp(gyro[0], -GyroMaxValue, GyroMaxValue); + gyro[1] = std::clamp(gyro[1], -GyroMaxValue, GyroMaxValue); + gyro[2] = std::clamp(gyro[2], -GyroMaxValue, GyroMaxValue); // Auto adjust gyro_bias to minimize drift if (!IsMoving(IsAtRestRelaxed)) { @@ -59,25 +58,25 @@ void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { } } -void MotionInput::SetQuaternion(const Common::Quaternion& quaternion) { +void MotionInput::SetQuaternion(const Common::Vec& quaternion) { quat = quaternion; } -void MotionInput::SetEulerAngles(const Common::Vec3f& euler_angles) { - const float cr = std::cos(euler_angles.x * 0.5f); - const float sr = std::sin(euler_angles.x * 0.5f); - const float cp = std::cos(euler_angles.y * 0.5f); - const float sp = std::sin(euler_angles.y * 0.5f); - const float cy = std::cos(euler_angles.z * 0.5f); - const float sy = std::sin(euler_angles.z * 0.5f); - - quat.w = cr * cp * cy + sr * sp * sy; - quat.xyz.x = sr * cp * cy - cr * sp * sy; - quat.xyz.y = cr * sp * cy + sr * cp * sy; - quat.xyz.z = cr * cp * sy - sr * sp * cy; +void MotionInput::SetEulerAngles(const Common::Vec& euler_angles) { + const float cr = std::cos(euler_angles[0] * 0.5f); + const float sr = std::sin(euler_angles[0] * 0.5f); + const float cp = std::cos(euler_angles[1] * 0.5f); + const float sp = std::sin(euler_angles[1] * 0.5f); + const float cy = std::cos(euler_angles[2] * 0.5f); + const float sy = std::sin(euler_angles[2] * 0.5f); + + quat[3] = cr * cp * cy + sr * sp * sy; + quat[0] = sr * cp * cy - cr * sp * sy; + quat[1] = cr * sp * cy + sr * cp * sy; + quat[2] = cr * cp * sy - sr * sp * cy; } -void MotionInput::SetGyroBias(const Common::Vec3f& bias) { +void MotionInput::SetGyroBias(const Common::Vec& bias) { gyro_bias = bias; } @@ -98,7 +97,7 @@ void MotionInput::ResetRotations() { } void MotionInput::ResetQuaternion() { - quat = {{0.0f, 0.0f, -1.0f}, 0.0f}; + quat = Common::Vec{0.0f, 0.0f, -1.0f, 0.0f}; } bool MotionInput::IsMoving(f32 sensitivity) const { @@ -137,10 +136,10 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { ResetOrientation(); } // Short name local variable for readability - f32 q1 = quat.w; - f32 q2 = quat.xyz[0]; - f32 q3 = quat.xyz[1]; - f32 q4 = quat.xyz[2]; + f32 q1 = quat[3]; + f32 q2 = quat[0]; + f32 q3 = quat[1]; + f32 q4 = quat[2]; const auto sample_period = static_cast(elapsed_time) / 1000000.0f; // Ignore invalid elapsed time @@ -150,23 +149,23 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { const auto normal_accel = accel.Normalized(); auto rad_gyro = gyro * std::numbers::pi_v * 2.f; - const f32 swap = rad_gyro.x; - rad_gyro.x = rad_gyro.y; - rad_gyro.y = -swap; - rad_gyro.z = -rad_gyro.z; + const f32 swap = rad_gyro[0]; + rad_gyro[0] = rad_gyro[1]; + rad_gyro[1] = -swap; + rad_gyro[2] = -rad_gyro[2]; // Clear gyro values if there is no gyro present if (only_accelerometer) { - rad_gyro.x = 0; - rad_gyro.y = 0; - rad_gyro.z = 0; + rad_gyro[0] = 0; + rad_gyro[1] = 0; + rad_gyro[2] = 0; } // Ignore drift correction if acceleration is not reliable if (accel.Length() >= 0.75f && accel.Length() <= 1.25f) { - const f32 ax = -normal_accel.x; - const f32 ay = normal_accel.y; - const f32 az = -normal_accel.z; + const f32 ax = -normal_accel[0]; + const f32 ay = normal_accel[1]; + const f32 az = -normal_accel[2]; // Estimated direction of gravity const f32 vx = 2.0f * (q2 * q4 - q1 * q3); @@ -174,7 +173,7 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; // Error is cross product between estimated direction and measured direction of gravity - const Common::Vec3f new_real_error = { + const Common::Vec new_real_error{ az * vx - ax * vz, ay * vz - az * vy, ax * vy - ay * vx, @@ -202,16 +201,16 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { rad_gyro += 10.0f * kd * derivative_error; // Emulate gyro values for games that need them - gyro.x = -rad_gyro.y; - gyro.y = rad_gyro.x; - gyro.z = -rad_gyro.z; + gyro[0] = -rad_gyro[1]; + gyro[1] = rad_gyro[0]; + gyro[2] = -rad_gyro[2]; UpdateRotation(elapsed_time); } } - const f32 gx = rad_gyro.y; - const f32 gy = rad_gyro.x; - const f32 gz = rad_gyro.z; + const f32 gx = rad_gyro[1]; + const f32 gy = rad_gyro[0]; + const f32 gz = rad_gyro[2]; // Integrate rate of change of quaternion const f32 pa = q2; @@ -222,57 +221,58 @@ void MotionInput::UpdateOrientation(u64 elapsed_time) { q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); - quat.w = q1; - quat.xyz[0] = q2; - quat.xyz[1] = q3; - quat.xyz[2] = q4; + quat[3] = q1; + quat[0] = q2; + quat[1] = q3; + quat[2] = q4; quat = quat.Normalized(); } -std::array MotionInput::GetOrientation() const { - const Common::Quaternion quad{ - .xyz = {-quat.xyz[1], -quat.xyz[0], -quat.w}, - .w = -quat.xyz[2], +std::array, 3> MotionInput::GetOrientation() const { + const Common::Vec quad{ + -quat[1], + -quat[0], + -quat[3], + -quat[2], }; - const std::array matrix4x4 = quad.ToMatrix(); - - return {Common::Vec3f(matrix4x4[0], matrix4x4[1], -matrix4x4[2]), - Common::Vec3f(matrix4x4[4], matrix4x4[5], -matrix4x4[6]), - Common::Vec3f(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])}; + const std::array matrix4x4 = quad.ToMatrix(); + return {Common::Vec(matrix4x4[0], matrix4x4[1], -matrix4x4[2]), + Common::Vec(matrix4x4[4], matrix4x4[5], -matrix4x4[6]), + Common::Vec(-matrix4x4[8], -matrix4x4[9], matrix4x4[10])}; } -Common::Vec3f MotionInput::GetAcceleration() const { +Common::Vec MotionInput::GetAcceleration() const { return accel; } -Common::Vec3f MotionInput::GetGyroscope() const { +Common::Vec MotionInput::GetGyroscope() const { return gyro; } -Common::Vec3f MotionInput::GetGyroBias() const { +Common::Vec MotionInput::GetGyroBias() const { return gyro_bias; } -Common::Quaternion MotionInput::GetQuaternion() const { +Common::Vec MotionInput::GetQuaternion() const { return quat; } -Common::Vec3f MotionInput::GetRotations() const { +Common::Vec MotionInput::GetRotations() const { return rotations; } -Common::Vec3f MotionInput::GetEulerAngles() const { +Common::Vec MotionInput::GetEulerAngles() const { // roll (x-axis rotation) - const float sinr_cosp = 2 * (quat.w * quat.xyz.x + quat.xyz.y * quat.xyz.z); - const float cosr_cosp = 1 - 2 * (quat.xyz.x * quat.xyz.x + quat.xyz.y * quat.xyz.y); + const float sinr_cosp = 2 * (quat[3] * quat[0] + quat[1] * quat[2]); + const float cosr_cosp = 1 - 2 * (quat[0] * quat[0] + quat[1] * quat[1]); // pitch (y-axis rotation) - const float sinp = std::sqrt(1 + 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); - const float cosp = std::sqrt(1 - 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); + const float sinp = std::sqrt(1 + 2 * (quat[3] * quat[1] - quat[0] * quat[2])); + const float cosp = std::sqrt(1 - 2 * (quat[3] * quat[1] - quat[0] * quat[2])); // yaw (z-axis rotation) - const float siny_cosp = 2 * (quat.w * quat.xyz.z + quat.xyz.x * quat.xyz.y); - const float cosy_cosp = 1 - 2 * (quat.xyz.y * quat.xyz.y + quat.xyz.z * quat.xyz.z); + const float siny_cosp = 2 * (quat[3] * quat[2] + quat[0] * quat[1]); + const float cosy_cosp = 1 - 2 * (quat[1] * quat[1] + quat[2] * quat[2]); return { std::atan2(sinr_cosp, cosr_cosp), @@ -285,13 +285,13 @@ void MotionInput::ResetOrientation() { if (!reset_enabled || only_accelerometer) { return; } - if (!IsMoving(IsAtRestRelaxed) && accel.z <= -0.9f) { + if (!IsMoving(IsAtRestRelaxed) && accel[2] <= -0.9f) { ++reset_counter; if (reset_counter > 900) { - quat.w = 0; - quat.xyz[0] = 0; - quat.xyz[1] = 0; - quat.xyz[2] = -1; + quat[3] = 0; + quat[0] = 0; + quat[1] = 0; + quat[2] = -1; SetOrientationFromAccelerometer(); integral_error = {}; reset_counter = 0; @@ -309,15 +309,15 @@ void MotionInput::SetOrientationFromAccelerometer() { while (!IsCalibrated(0.01f) && ++iterations < 100) { // Short name local variable for readability - f32 q1 = quat.w; - f32 q2 = quat.xyz[0]; - f32 q3 = quat.xyz[1]; - f32 q4 = quat.xyz[2]; + f32 q1 = quat[3]; + f32 q2 = quat[0]; + f32 q3 = quat[1]; + f32 q4 = quat[2]; - Common::Vec3f rad_gyro; - const f32 ax = -normal_accel.x; - const f32 ay = normal_accel.y; - const f32 az = -normal_accel.z; + Common::Vec rad_gyro; + const f32 ax = -normal_accel[0]; + const f32 ay = normal_accel[1]; + const f32 az = -normal_accel[2]; // Estimated direction of gravity const f32 vx = 2.0f * (q2 * q4 - q1 * q3); @@ -325,7 +325,7 @@ void MotionInput::SetOrientationFromAccelerometer() { const f32 vz = q1 * q1 - q2 * q2 - q3 * q3 + q4 * q4; // Error is cross product between estimated direction and measured direction of gravity - const Common::Vec3f new_real_error = { + const Common::Vec new_real_error = { az * vx - ax * vz, ay * vz - az * vy, ax * vy - ay * vx, @@ -338,9 +338,9 @@ void MotionInput::SetOrientationFromAccelerometer() { rad_gyro += 5.0f * ki * integral_error; rad_gyro += 10.0f * kd * derivative_error; - const f32 gx = rad_gyro.y; - const f32 gy = rad_gyro.x; - const f32 gz = rad_gyro.z; + const f32 gx = rad_gyro[1]; + const f32 gy = rad_gyro[0]; + const f32 gz = rad_gyro[2]; // Integrate rate of change of quaternion const f32 pa = q2; @@ -351,10 +351,10 @@ void MotionInput::SetOrientationFromAccelerometer() { q3 = pb + (q1 * gy - pa * gz + pc * gx) * (0.5f * sample_period); q4 = pc + (q1 * gz + pa * gy - pb * gx) * (0.5f * sample_period); - quat.w = q1; - quat.xyz[0] = q2; - quat.xyz[1] = q3; - quat.xyz[2] = q4; + quat[3] = q1; + quat[0] = q2; + quat[1] = q3; + quat[2] = q4; quat = quat.Normalized(); } } diff --git a/src/hid_core/frontend/motion_input.h b/src/hid_core/frontend/motion_input.h index c902a3a6e5..09dbb706d7 100644 --- a/src/hid_core/frontend/motion_input.h +++ b/src/hid_core/frontend/motion_input.h @@ -1,10 +1,12 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project // SPDX-License-Identifier: GPL-2.0-or-later #pragma once #include "common/common_types.h" -#include "common/quaternion.h" #include "common/vector_math.h" namespace Core::HID { @@ -34,11 +36,11 @@ public: MotionInput& operator=(MotionInput&&) = default; void SetPID(f32 new_kp, f32 new_ki, f32 new_kd); - void SetAcceleration(const Common::Vec3f& acceleration); - void SetGyroscope(const Common::Vec3f& gyroscope); - void SetQuaternion(const Common::Quaternion& quaternion); - void SetEulerAngles(const Common::Vec3f& euler_angles); - void SetGyroBias(const Common::Vec3f& bias); + void SetAcceleration(const Common::Vec& acceleration); + void SetGyroscope(const Common::Vec& gyroscope); + void SetQuaternion(const Common::Vec& quaternion); + void SetEulerAngles(const Common::Vec& euler_angles); + void SetGyroBias(const Common::Vec& bias); void SetGyroThreshold(f32 threshold); /// Applies a modifier on top of the normal gyro threshold @@ -53,13 +55,13 @@ public: void Calibrate(); - [[nodiscard]] std::array GetOrientation() const; - [[nodiscard]] Common::Vec3f GetAcceleration() const; - [[nodiscard]] Common::Vec3f GetGyroscope() const; - [[nodiscard]] Common::Vec3f GetGyroBias() const; - [[nodiscard]] Common::Vec3f GetRotations() const; - [[nodiscard]] Common::Quaternion GetQuaternion() const; - [[nodiscard]] Common::Vec3f GetEulerAngles() const; + [[nodiscard]] std::array, 3> GetOrientation() const; + [[nodiscard]] Common::Vec GetAcceleration() const; + [[nodiscard]] Common::Vec GetGyroscope() const; + [[nodiscard]] Common::Vec GetGyroBias() const; + [[nodiscard]] Common::Vec GetRotations() const; + [[nodiscard]] Common::Vec GetQuaternion() const; + [[nodiscard]] Common::Vec GetEulerAngles() const; [[nodiscard]] bool IsMoving(f32 sensitivity) const; [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; @@ -75,24 +77,24 @@ private: f32 kd; // PID errors - Common::Vec3f real_error; - Common::Vec3f integral_error; - Common::Vec3f derivative_error; + Common::Vec real_error; + Common::Vec integral_error; + Common::Vec derivative_error; // Quaternion containing the device orientation - Common::Quaternion quat; + Common::Vec quat; // Number of full rotations in each axis - Common::Vec3f rotations; + Common::Vec rotations; // Acceleration vector measurement in G force - Common::Vec3f accel; + Common::Vec accel; // Gyroscope vector measurement in radians/s. - Common::Vec3f gyro; + Common::Vec gyro; // Vector to be subtracted from gyro measurements - Common::Vec3f gyro_bias; + Common::Vec gyro_bias; // Minimum gyro amplitude to detect if the device is moving f32 gyro_threshold = 0.0f; diff --git a/src/hid_core/hid_types.h b/src/hid_core/hid_types.h index 66d661c80b..ae12059a92 100644 --- a/src/hid_core/hid_types.h +++ b/src/hid_core/hid_types.h @@ -609,10 +609,10 @@ static_assert(sizeof(SixAxisSensorAttribute) == 4, "SixAxisSensorAttribute is an struct SixAxisSensorState { s64 delta_time{}; s64 sampling_number{}; - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Vec3f rotation{}; - std::array orientation{}; + Common::Vec accel{}; + Common::Vec gyro{}; + Common::Vec rotation{}; + std::array, 3> orientation{}; SixAxisSensorAttribute attribute{}; INSERT_PADDING_BYTES(4); // Reserved }; diff --git a/src/hid_core/resources/shared_memory_format.h b/src/hid_core/resources/shared_memory_format.h index b9deeec302..0d74689869 100644 --- a/src/hid_core/resources/shared_memory_format.h +++ b/src/hid_core/resources/shared_memory_format.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project @@ -196,7 +196,7 @@ struct ConsoleSixAxisSensorSharedMemoryFormat { bool is_seven_six_axis_sensor_at_rest{}; INSERT_PADDING_BYTES(3); // padding f32 verticalization_error{}; - Common::Vec3f gyro_bias{}; + Common::Vec gyro_bias{}; INSERT_PADDING_BYTES(4); // padding }; static_assert(sizeof(ConsoleSixAxisSensorSharedMemoryFormat) == 0x20, diff --git a/src/hid_core/resources/six_axis/seven_six_axis.cpp b/src/hid_core/resources/six_axis/seven_six_axis.cpp index 584e6d6505..13dd5f943a 100644 --- a/src/hid_core/resources/six_axis/seven_six_axis.cpp +++ b/src/hid_core/resources/six_axis/seven_six_axis.cpp @@ -46,14 +46,11 @@ void SevenSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { next_seven_sixaxis_state.accel = motion_status.accel; next_seven_sixaxis_state.gyro = motion_status.gyro; next_seven_sixaxis_state.quaternion = { - { - motion_status.quaternion.xyz.y, - motion_status.quaternion.xyz.x, - -motion_status.quaternion.w, - }, - -motion_status.quaternion.xyz.z, + motion_status.quaternion[1], + motion_status.quaternion[0], + -motion_status.quaternion[3], + -motion_status.quaternion[2], }; - seven_sixaxis_lifo.WriteNextEntry(next_seven_sixaxis_state); transfer_memory_owner->GetMemory().WriteBlock(transfer_memory, &seven_sixaxis_lifo, sizeof(seven_sixaxis_lifo)); diff --git a/src/hid_core/resources/six_axis/seven_six_axis.h b/src/hid_core/resources/six_axis/seven_six_axis.h index 00afb8c00b..a59d697356 100644 --- a/src/hid_core/resources/six_axis/seven_six_axis.h +++ b/src/hid_core/resources/six_axis/seven_six_axis.h @@ -7,7 +7,7 @@ #pragma once #include "common/common_types.h" -#include "common/quaternion.h" +#include "common/vector_math.h" #include "common/typed_address.h" #include "hid_core/resources/controller_base.h" #include "hid_core/resources/ring_lifo.h" @@ -51,9 +51,9 @@ private: u64 timestamp{}; u64 sampling_number{}; u64 unknown{}; - Common::Vec3f accel{}; - Common::Vec3f gyro{}; - Common::Quaternion quaternion{}; + Common::Vec accel{}; + Common::Vec gyro{}; + Common::Vec quaternion{}; }; static_assert(sizeof(SevenSixAxisState) == 0x48, "SevenSixAxisState is an invalid size"); diff --git a/src/hid_core/resources/six_axis/six_axis.cpp b/src/hid_core/resources/six_axis/six_axis.cpp index b407a5c76e..53a56d2661 100644 --- a/src/hid_core/resources/six_axis/six_axis.cpp +++ b/src/hid_core/resources/six_axis/six_axis.cpp @@ -1,3 +1,6 @@ +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project +// SPDX-License-Identifier: GPL-3.0-or-later + // SPDX-FileCopyrightText: Copyright 2023 yuzu Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later @@ -93,9 +96,9 @@ void SixAxis::OnUpdate(const Core::Timing::CoreTiming& core_timing) { .accel = {0, 0, -1.0f}, .orientation = { - Common::Vec3f{1.0f, 0, 0}, - Common::Vec3f{0, 1.0f, 0}, - Common::Vec3f{0, 0, 1.0f}, + Common::Vec{1.0f, 0, 0}, + Common::Vec{0, 1.0f, 0}, + Common::Vec{0, 0, 1.0f}, }, .attribute = {1}, }; diff --git a/src/input_common/drivers/mouse.cpp b/src/input_common/drivers/mouse.cpp index 00b7220c1e..4444f0ac3b 100644 --- a/src/input_common/drivers/mouse.cpp +++ b/src/input_common/drivers/mouse.cpp @@ -88,8 +88,8 @@ void Mouse::UpdateStickInput() { last_mouse_change *= maximum_stick_range; } - SetAxis(identifier, mouse_axis_x, last_mouse_change.x); - SetAxis(identifier, mouse_axis_y, -last_mouse_change.y); + SetAxis(identifier, mouse_axis_x, last_mouse_change[0]); + SetAxis(identifier, mouse_axis_y, -last_mouse_change[1]); // Decay input over time const float clamped_length = (std::min)(1.0f, length); @@ -104,20 +104,20 @@ void Mouse::UpdateMotionInput() { const float sensitivity = IsMousePanningEnabled() ? default_motion_panning_sensitivity : default_motion_sensitivity; - const float rotation_velocity = std::sqrt(last_motion_change.x * last_motion_change.x + - last_motion_change.y * last_motion_change.y); + const float rotation_velocity = std::sqrt(last_motion_change[0] * last_motion_change[0] + + last_motion_change[1] * last_motion_change[1]); // Clamp rotation speed if (rotation_velocity > maximum_rotation_speed / sensitivity) { const float multiplier = maximum_rotation_speed / rotation_velocity / sensitivity; - last_motion_change.x = last_motion_change.x * multiplier; - last_motion_change.y = last_motion_change.y * multiplier; + last_motion_change[0] = last_motion_change[0] * multiplier; + last_motion_change[1] = last_motion_change[1] * multiplier; } const BasicMotion motion_data{ - .gyro_x = last_motion_change.x * sensitivity, - .gyro_y = last_motion_change.y * sensitivity, - .gyro_z = last_motion_change.z * sensitivity, + .gyro_x = last_motion_change[0] * sensitivity, + .gyro_y = last_motion_change[1] * sensitivity, + .gyro_z = last_motion_change[2] * sensitivity, .accel_x = 0, .accel_y = 0, .accel_z = 0, @@ -125,53 +125,46 @@ void Mouse::UpdateMotionInput() { }; if (IsMousePanningEnabled()) { - last_motion_change.x = 0; - last_motion_change.y = 0; + last_motion_change[0] = 0; + last_motion_change[1] = 0; } - last_motion_change.z = 0; + last_motion_change[2] = 0; SetMotion(motion_identifier, 0, motion_data); } void Mouse::Move(int x, int y, int center_x, int center_y) { if (IsMousePanningEnabled()) { - const auto mouse_change = - (Common::MakeVec(x, y) - Common::MakeVec(center_x, center_y)).Cast(); - const float x_sensitivity = - Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity; - const float y_sensitivity = - Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity; - const float deadzone_counterweight = - Settings::values.mouse_panning_deadzone_counterweight.GetValue() * - default_deadzone_counterweight; - - last_motion_change += {-mouse_change.y * x_sensitivity, -mouse_change.x * y_sensitivity, 0}; - last_mouse_change.x += mouse_change.x * x_sensitivity; - last_mouse_change.y += mouse_change.y * y_sensitivity; - - // Bind the mouse change to [0 <= deadzone_counterweight <= 1.0] + auto const mouse_change_int = Common::Vec(x, y) - Common::Vec(center_x, center_y); + auto const mouse_change = Common::Vec(float(mouse_change_int[0]), float(mouse_change_int[1])); + auto const x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue() * default_panning_sensitivity; + auto const y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue() * default_panning_sensitivity; + auto const deadzone_cw = Settings::values.mouse_panning_deadzone_counterweight.GetValue() * default_deadzone_counterweight; + last_motion_change += {-mouse_change[1] * x_sensitivity, -mouse_change[0] * y_sensitivity, 0}; + last_mouse_change[0] += mouse_change[0] * x_sensitivity; + last_mouse_change[1] += mouse_change[1] * y_sensitivity; + // Bind the mouse change to [0 <= deadzone_cw <= 1.0] const float length = last_mouse_change.Length(); - if (length < deadzone_counterweight && length != 0.0f) { + if (length < deadzone_cw && length != 0.0f) { last_mouse_change /= length; - last_mouse_change *= deadzone_counterweight; + last_mouse_change *= deadzone_cw; } - return; } if (button_pressed) { - const auto mouse_move = Common::MakeVec(x, y) - mouse_origin; + const auto mouse_move = Common::Vec(x, y) - mouse_origin; const float x_sensitivity = Settings::values.mouse_panning_x_sensitivity.GetValue() * default_stick_sensitivity; const float y_sensitivity = Settings::values.mouse_panning_y_sensitivity.GetValue() * default_stick_sensitivity; - SetAxis(identifier, mouse_axis_x, static_cast(mouse_move.x) * x_sensitivity); - SetAxis(identifier, mouse_axis_y, static_cast(-mouse_move.y) * y_sensitivity); + SetAxis(identifier, mouse_axis_x, float(mouse_move[0]) * x_sensitivity); + SetAxis(identifier, mouse_axis_y, float(-mouse_move[1]) * y_sensitivity); last_motion_change = { - static_cast(-mouse_move.y) * x_sensitivity, - static_cast(-mouse_move.x) * y_sensitivity, - last_motion_change.z, + float(-mouse_move[1]) * x_sensitivity, + float(-mouse_move[0]) * y_sensitivity, + last_motion_change[2], }; } } @@ -220,18 +213,18 @@ void Mouse::ReleaseButton(MouseButton button) { SetAxis(identifier, mouse_axis_y, 0); } - last_motion_change.x = 0; - last_motion_change.y = 0; + last_motion_change[0] = 0; + last_motion_change[1] = 0; button_pressed = false; } void Mouse::MouseWheelChange(int x, int y) { - wheel_position.x += x; - wheel_position.y += y; - last_motion_change.z += static_cast(y); - SetAxis(identifier, wheel_axis_x, static_cast(wheel_position.x)); - SetAxis(identifier, wheel_axis_y, static_cast(wheel_position.y)); + wheel_position[0] += x; + wheel_position[1] += y; + last_motion_change[2] += static_cast(y); + SetAxis(identifier, wheel_axis_x, static_cast(wheel_position[0])); + SetAxis(identifier, wheel_axis_y, static_cast(wheel_position[1])); } void Mouse::ReleaseAllButtons() { diff --git a/src/input_common/drivers/mouse.h b/src/input_common/drivers/mouse.h index 166168c824..25f75109b9 100644 --- a/src/input_common/drivers/mouse.h +++ b/src/input_common/drivers/mouse.h @@ -107,11 +107,11 @@ private: Common::Input::ButtonNames GetUIButtonName(const Common::ParamPackage& params) const; - Common::Vec2 mouse_origin; - Common::Vec2 last_mouse_position; - Common::Vec2 last_mouse_change; - Common::Vec3 last_motion_change; - Common::Vec2 wheel_position; + Common::Vec mouse_origin; + Common::Vec last_mouse_position; + Common::Vec last_mouse_change; + Common::Vec last_motion_change; + Common::Vec wheel_position; bool button_pressed = false; }; diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index a6be2a1dd4..faf4e021ec 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp @@ -2936,10 +2936,10 @@ void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Di } // Draw motion functions -void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, +void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec& euler, float size) { - std::array cube{ - Common::Vec3f{-0.7f, -1, -0.5f}, + std::array, 8> cube{ + Common::Vec{-0.7f, -1, -0.5f}, {-0.7f, 1, -0.5f}, {0.7f, 1, -0.5f}, {0.7f, -1, -0.5f}, @@ -2949,30 +2949,38 @@ void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common: {0.7f, -1, 0.5f}, }; - for (Common::Vec3f& point : cube) { - point.RotateFromOrigin(euler.x, euler.y, euler.z); + for (Common::Vec& point : cube) { + float temp = point[1]; + point[1] = std::cos(euler[0]) * point[1] - std::sin(euler[0]) * point[2]; + point[2] = std::sin(euler[0]) * temp + std::cos(euler[0]) * point[2]; + temp = point[0]; + point[0] = std::cos(euler[1]) * point[0] + std::sin(euler[1]) * point[2]; + point[2] = -std::sin(euler[1]) * temp + std::cos(euler[1]) * point[2]; + temp = point[0]; + point[0] = std::cos(euler[2]) * point[0] - std::sin(euler[2]) * point[1]; + point[1] = std::sin(euler[2]) * temp + std::cos(euler[2]) * point[1]; point *= size; } const std::array front_face{ - center + QPointF{cube[0].x, cube[0].y}, - center + QPointF{cube[1].x, cube[1].y}, - center + QPointF{cube[2].x, cube[2].y}, - center + QPointF{cube[3].x, cube[3].y}, + center + QPointF{cube[0][0], cube[0][1]}, + center + QPointF{cube[1][0], cube[1][1]}, + center + QPointF{cube[2][0], cube[2][1]}, + center + QPointF{cube[3][0], cube[3][1]}, }; const std::array back_face{ - center + QPointF{cube[4].x, cube[4].y}, - center + QPointF{cube[5].x, cube[5].y}, - center + QPointF{cube[6].x, cube[6].y}, - center + QPointF{cube[7].x, cube[7].y}, + center + QPointF{cube[4][0], cube[4][1]}, + center + QPointF{cube[5][0], cube[5][1]}, + center + QPointF{cube[6][0], cube[6][1]}, + center + QPointF{cube[7][0], cube[7][1]}, }; DrawPolygon(p, front_face); DrawPolygon(p, back_face); - p.drawLine(center + QPointF{cube[0].x, cube[0].y}, center + QPointF{cube[4].x, cube[4].y}); - p.drawLine(center + QPointF{cube[1].x, cube[1].y}, center + QPointF{cube[5].x, cube[5].y}); - p.drawLine(center + QPointF{cube[2].x, cube[2].y}, center + QPointF{cube[6].x, cube[6].y}); - p.drawLine(center + QPointF{cube[3].x, cube[3].y}, center + QPointF{cube[7].x, cube[7].y}); + p.drawLine(center + QPointF{cube[0][0], cube[0][1]}, center + QPointF{cube[4][0], cube[4][1]}); + p.drawLine(center + QPointF{cube[1][0], cube[1][1]}, center + QPointF{cube[5][0], cube[5][1]}); + p.drawLine(center + QPointF{cube[2][0], cube[2][1]}, center + QPointF{cube[6][0], cube[6][1]}); + p.drawLine(center + QPointF{cube[3][0], cube[3][1]}, center + QPointF{cube[7][0], cube[7][1]}); } template diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index d7ec943240..d439c718fb 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h @@ -1,4 +1,4 @@ -// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project +// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project // SPDX-License-Identifier: GPL-3.0-or-later // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project @@ -198,7 +198,7 @@ private: void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); // Draw motion functions - void Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, float size); + void Draw3dCube(QPainter& p, QPointF center, const Common::Vec& euler, float size); // Draw primitive types template