Skip to content

Commit

Permalink
Initial Blueprint functions (GetDevicePose and GetMotionControllerData)
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Apr 22, 2023
1 parent c5bc832 commit a77074f
Show file tree
Hide file tree
Showing 9 changed files with 200 additions and 11 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,7 @@ list(APPEND ue4poc_SOURCES
"src/mods/vr/runtimes/VRRuntime.hpp"
"src/mods/vr/shaders/ps.hpp"
"src/mods/vr/shaders/vs.hpp"
"src/mods/vr/structures/FXRMotionControllerData.hpp"
"src/mods/vr/vtables/IXRTrackingSystemVTables.hpp"
"src/ue4poc-imgui/font_robotomedium.hpp"
"src/ue4poc-imgui/ue4poc_imconfig.hpp"
Expand Down Expand Up @@ -889,6 +890,7 @@ list(APPEND ue4poc-nolog_SOURCES
"src/mods/vr/runtimes/VRRuntime.hpp"
"src/mods/vr/shaders/ps.hpp"
"src/mods/vr/shaders/vs.hpp"
"src/mods/vr/structures/FXRMotionControllerData.hpp"
"src/mods/vr/vtables/IXRTrackingSystemVTables.hpp"
"src/ue4poc-imgui/font_robotomedium.hpp"
"src/ue4poc-imgui/ue4poc_imconfig.hpp"
Expand Down
9 changes: 1 addition & 8 deletions shared/sdk/Math.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -39,13 +39,6 @@ static vec3 euler_angles_from_steamvr(const glm::mat4& rot) {
float pitch = 0.0f;
float yaw = 0.0f;
float roll = 0.0f;
const auto m = rot *
Matrix4x4f {
1, 0, 0, 0,
0, 0, 1, 0,
0, 1, 0, 0,
0, 0, 0, 1
};
glm::extractEulerAngleYXZ(rot, yaw, pitch, roll);

return { pitch, -yaw, -roll };
Expand All @@ -68,7 +61,7 @@ static vec3 euler_angles_from_ue4(const glm::quat q) {
}

static glm::quat glm_to_ue4(const glm::quat q) {
return glm::quat{ q.w, -q.z, q.x, q.y };
return glm::quat{ -q.w, -q.z, q.x, q.y };
}

static vec3 glm_to_ue4(const glm::vec3 v) {
Expand Down
5 changes: 5 additions & 0 deletions shared/sdk/StereoStuff.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ struct Rotator {
T pitch, yaw, roll;
};

template<typename T>
struct Quat {
T x, y, z, w;
};

struct FRHIResource {
virtual ~FRHIResource(){};

Expand Down
12 changes: 12 additions & 0 deletions src/mods/vr/Bindings.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,18 @@ std::string VR::actions_json = R"(
"name": "/actions/default/in/BButton",
"type": "boolean"
},
{
"name": "/actions/default/in/AButtonTouch",
"type": "boolean"
},
{
"name": "/actions/default/in/BButtonTouch",
"type": "boolean"
},
{
"name": "/actions/default/in/ThumbRestTouch",
"type": "boolean"
},
{
"name": "/actions/default/in/SystemButton",
"type": "boolean"
Expand Down
4 changes: 4 additions & 0 deletions src/mods/vr/FFakeStereoRenderingHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,10 @@ void FFakeStereoRenderingHook::on_draw_ui() {
m_recreate_textures_on_reset->draw("Recreate Textures on Reset");
m_frame_delay_compensation->draw("Frame Delay Compensation");

if (m_tracking_system_hook != nullptr) {
m_tracking_system_hook->on_draw_ui();
}

ImGui::Separator();
}

Expand Down
105 changes: 104 additions & 1 deletion src/mods/vr/IXRTrackingSystemHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
#include "../VR.hpp"

#include "vtables/IXRTrackingSystemVTables.hpp"
#include "structures/FXRMotionControllerData.hpp"
#include "IXRTrackingSystemHook.hpp"

detail::IXRTrackingSystemVT& get_tracking_system_vtable() {
Expand Down Expand Up @@ -322,6 +323,9 @@ IXRTrackingSystemHook::IXRTrackingSystemHook(FFakeStereoRenderingHook* stereo_ho
}
}

void IXRTrackingSystemHook::on_draw_ui() {
}

void IXRTrackingSystemHook::on_pre_engine_tick(sdk::UGameEngine* engine, float delta) {
auto& vr = VR::get();

Expand Down Expand Up @@ -381,6 +385,18 @@ void IXRTrackingSystemHook::initialize() {
} else {
SPDLOG_ERROR("IXRTrackingSystemHook::IXRTrackingSystemHook: is_head_tracking_allowed_for_world_index not implemented");
}

if (trackvt.GetMotionControllerData_index().has_value()) {
m_xrtracking_vtable[trackvt.GetMotionControllerData_index().value()] = (uintptr_t)&get_motion_controller_data;
} else {
SPDLOG_ERROR("IXRTrackingSystemHook::IXRTrackingSystemHook: get_motion_controller_data_index not implemented");
}

if (trackvt.GetCurrentPose_index().has_value()) {
m_xrtracking_vtable[trackvt.GetCurrentPose_index().value()] = (uintptr_t)&get_current_pose;
} else {
SPDLOG_ERROR("IXRTrackingSystemHook::IXRTrackingSystemHook: get_current_pose_index not implemented");
}
} else if (hmdvt.implemented()) {
SPDLOG_INFO("IXRTrackingSystemHook::IXRTrackingSystemHook: IXRTrackingSystemVT not implemented, using IHeadMountedDisplayVT");

Expand Down Expand Up @@ -590,6 +606,93 @@ IXRTrackingSystemHook::SharedPtr* IXRTrackingSystemHook::get_xr_camera(sdk::IXRT
return out;
}

void IXRTrackingSystemHook::get_motion_controller_data(sdk::IXRTrackingSystem*, void* world, uint32_t hand, void* motion_controller_data) {
SPDLOG_INFO_ONCE("get_motion_controller_data {:x}", (uintptr_t)_ReturnAddress());

const auto e_hand = (ue427::EControllerHand)hand;
const auto data = (ue427::FXRMotionControllerData*)motion_controller_data;

const auto vr = VR::get();

const auto world_scale = vr->get_world_to_meters();

auto rotation_offset = vr->get_rotation_offset();

if (vr->is_decoupled_pitch_enabled()) {
const auto pre_flat_rotation = vr->get_pre_flattened_rotation();
const auto pre_flat_pitch = utility::math::pitch_only(pre_flat_rotation);
rotation_offset = glm::normalize(pre_flat_pitch * vr->get_rotation_offset());
}

switch (e_hand) {
case ue427::EControllerHand::Left: {
data->bValid = true;
const auto position = rotation_offset * glm::vec3{vr->get_position(vr->get_left_controller_index()) - vr->get_standing_origin()};
const auto rotation = glm::normalize(rotation_offset * glm::quat{vr->get_rotation(vr->get_left_controller_index())});

const auto final_position = utility::math::glm_to_ue4(position * world_scale);
const auto final_rotation = utility::math::glm_to_ue4(rotation);
//data->GripRotation = { -final_rotation.z, final_rotation.x, final_rotation.y, -final_rotation.w };
data->GripRotation = { final_rotation.x, final_rotation.y, final_rotation.z, final_rotation.w };
data->GripPosition = final_position;

data->AimRotation = data->GripRotation;
data->AimPosition = data->GripPosition;

break;
}
case ue427::EControllerHand::Right: {
data->bValid = true;
const auto position = rotation_offset * glm::vec3{vr->get_position(vr->get_right_controller_index()) - vr->get_standing_origin()};
const auto rotation = glm::normalize(rotation_offset * glm::quat{vr->get_rotation(vr->get_right_controller_index())});

const auto final_position = utility::math::glm_to_ue4(position * world_scale);
const auto final_rotation = utility::math::glm_to_ue4(rotation);
//data->GripRotation = { -final_rotation.z, final_rotation.x, final_rotation.y, -final_rotation.w };
data->GripRotation = { final_rotation.x, final_rotation.y, final_rotation.z, final_rotation.w };
data->GripPosition = final_position;

data->AimRotation = data->GripRotation;
data->AimPosition = data->GripPosition;
break;
}
default:
break;
}
}

void IXRTrackingSystemHook::get_current_pose(sdk::IXRTrackingSystem*, int32_t device_id, Quat<float>* out_rot, glm::vec3* out_pos) {
SPDLOG_INFO_ONCE("get_current_pose {:x}", (uintptr_t)_ReturnAddress());

const auto vr = VR::get();
const auto world_scale = vr->get_world_to_meters();

auto rotation_offset = vr->get_rotation_offset();

if (vr->is_decoupled_pitch_enabled()) {
const auto pre_flat_rotation = vr->get_pre_flattened_rotation();
const auto pre_flat_pitch = utility::math::pitch_only(pre_flat_rotation);
rotation_offset = glm::normalize(pre_flat_pitch * vr->get_rotation_offset());
}

switch (device_id) {
// Todo: motion controllers? Don't know how BP can pass through a valid device id
case 0:
default: {
const auto position = rotation_offset * glm::vec3{vr->get_position(vr->get_hmd_index()) - vr->get_standing_origin()};
const auto rotation = glm::normalize(rotation_offset * glm::quat{vr->get_rotation(vr->get_hmd_index())});

// TODO: UE5
*out_pos = utility::math::glm_to_ue4(position * world_scale);

const auto q = utility::math::glm_to_ue4(rotation);
*out_rot = { q.x, q.y, q.z, q.w };

break;
}
}
}

void IXRTrackingSystemHook::apply_hmd_rotation(sdk::IXRCamera*, void* player_controller, Rotator<float>* rot) {
SPDLOG_INFO_ONCE("apply_hmd_rotation {:x}", (uintptr_t)_ReturnAddress());

Expand Down Expand Up @@ -638,7 +741,7 @@ void IXRTrackingSystemHook::apply_hmd_rotation(sdk::IXRCamera*, void* player_con
VR::get()->recenter_view();*/
}

bool IXRTrackingSystemHook::update_player_camera(sdk::IXRCamera*, glm::quat* rel_rot, glm::vec3* rel_pos) {
bool IXRTrackingSystemHook::update_player_camera(sdk::IXRCamera*, Quat<float>* rel_rot, glm::vec3* rel_pos) {
SPDLOG_INFO_ONCE("update_player_camera {:x}", (uintptr_t)_ReturnAddress());

if (VR::get()->is_hmd_active() && !g_hook->m_process_view_rotation_hook && !g_hook->m_attempted_hook_view_rotation) {
Expand Down
6 changes: 4 additions & 2 deletions src/mods/vr/IXRTrackingSystemHook.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ class IXRTrackingSystemHook : public ModComponent {
public:
IXRTrackingSystemHook(FFakeStereoRenderingHook* stereo_hook, size_t offset_in_engine);

void on_draw_ui() override;
void on_pre_engine_tick(sdk::UGameEngine* engine, float delta) override;

auto& get_process_view_rotation_data() { return m_process_view_rotation_data; }
Expand All @@ -53,10 +54,11 @@ class IXRTrackingSystemHook : public ModComponent {
static bool is_head_tracking_allowed(sdk::IXRTrackingSystem*);
static bool is_head_tracking_allowed_for_world(sdk::IXRTrackingSystem*, void* world);
static SharedPtr* get_xr_camera(sdk::IXRTrackingSystem*, SharedPtr* out, size_t device_id);
static void get_motion_controller_data(sdk::IXRTrackingSystem*, void* world, uint32_t hand, void* motion_controller_data);
static void get_current_pose(sdk::IXRTrackingSystem*, int32_t device_id, Quat<float>* out_rot, glm::vec3* out_pos);

static void apply_hmd_rotation(sdk::IXRCamera*, void* player_controller, Rotator<float>* rot);
static bool update_player_camera(sdk::IXRCamera*, glm::quat* rel_rot, glm::vec3* rel_pos);

static bool update_player_camera(sdk::IXRCamera*, Quat<float>* rel_rot, glm::vec3* rel_pos);
// This function is the precursor to actually hooking ProcessViewRotation
// Because there's a very real possibility that we can accidentally hook the wrong function
// We need to verify that arg 2 and 3 are on the stack
Expand Down
4 changes: 4 additions & 0 deletions src/mods/vr/runtimes/OpenXR.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,11 @@ struct OpenXR final : public VRRuntime {
public:
// openxr quaternions are xyzw and glm is wxyz
static glm::quat to_glm(const XrQuaternionf& q) {
#ifndef GLM_FORCE_QUAT_DATA_XYZW
return glm::quat{ q.w, q.x, q.y, q.z };
#else
return glm::quat{ q.x, q.y, q.z, q.w };
#endif
}

static XrQuaternionf to_openxr(const glm::quat& q) {
Expand Down
64 changes: 64 additions & 0 deletions src/mods/vr/structures/FXRMotionControllerData.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#pragma once

#include <cstdint>

#include <sdk/Math.hpp>

namespace ue5 {
struct FQuat {
double x{};
double y{};
double z{};
double w{};
};
}

namespace ue427 {
enum class EControllerHand : uint8_t {
Left = 0,
Right = 1,
};

enum class ETrackingStatus : uint8_t {
NotTracked = 0,
InertialOnly = 1,
Tracked = 2,
ETrackingStatus_MAX = 3,
};

struct FName {
int32_t a1{0};
int32_t a2{0};
};

struct FQuat {
float x{};
float y{};
float z{};
float w{};
};

struct FXRDeviceId {
FName SystemName{};
int32_t DeviceID{};
};

struct FXRMotionControllerData {
bool bValid; // 0x0
char pad_1[0x3];
FName DeviceName; // 0x4
char pad_c[0x10];
uint8_t DeviceVisualType; // 0x1c
EControllerHand HandIndex; // 0x1d
ETrackingStatus TrackingStatus; // 0x1e
char pad_1f[0x1];
glm::vec3 GripPosition; // 0x20
char pad_2c[0x4];
FQuat GripRotation; // 0x30
glm::vec3 AimPosition; // 0x40
char pad_4c[0x4];
FQuat AimRotation; // 0x50
char pad_60[0x30];
char pad_91[0xf];
}; // Size: 0xa0
}

0 comments on commit a77074f

Please sign in to comment.