Skip to content

Commit

Permalink
IXRTrackingSystem: Rework BP structs to use reflection if possible
Browse files Browse the repository at this point in the history
  • Loading branch information
praydog committed Nov 30, 2023
1 parent 1634fc5 commit 4f2e120
Show file tree
Hide file tree
Showing 3 changed files with 107 additions and 52 deletions.
4 changes: 2 additions & 2 deletions shared/sdk/FProperty.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,12 @@ class FProperty : public FField {
}

template<typename T>
T* get_data(sdk::UObject* object) const {
T* get_data(void* object) const {
return (T*)((uintptr_t)object + get_offset());
}

template<typename T>
T* get_data(const sdk::UObject* object) const {
T* get_data(const void* object) const {
return (T*)((uintptr_t)object + get_offset());
}

Expand Down
5 changes: 5 additions & 0 deletions shared/sdk/UClass.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -461,8 +461,13 @@ void UClass::update_offsets() {
SPDLOG_INFO("[UClass] Bruteforcing offsets...");

const auto object_class = sdk::UObject::static_class();
SPDLOG_INFO("[UClass] UObject: 0x{:x}", (uintptr_t)object_class);

const auto field_class = sdk::UField::static_class();
SPDLOG_INFO("[UClass] UField: 0x{:x}", (uintptr_t)field_class);

const auto struct_class = sdk::UStruct::static_class();
SPDLOG_INFO("[UClass] UStruct: 0x{:x}", (uintptr_t)struct_class);

if (object_class == nullptr || field_class == nullptr || struct_class == nullptr) {
SPDLOG_ERROR("[UClass] Failed to find UObject/UStruct/UField!");
Expand Down
150 changes: 100 additions & 50 deletions src/mods/vr/IXRTrackingSystemHook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@
#include "utility/Logging.hpp"

#include <sdk/Utility.hpp>
#include <sdk/UObjectArray.hpp>
#include <sdk/UClass.hpp>
#include <sdk/FProperty.hpp>
#include <sdk/ScriptVector.hpp>

#include "../VR.hpp"

Expand Down Expand Up @@ -787,10 +791,7 @@ void IXRTrackingSystemHook::get_motion_controller_data(sdk::IXRTrackingSystem*,
SPDLOG_INFO_ONCE("get_motion_controller_data {:x}", (uintptr_t)_ReturnAddress());

const auto e_hand = (ue::EControllerHand)hand;
const auto data = (ue4_27::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();
Expand All @@ -801,63 +802,78 @@ void IXRTrackingSystemHook::get_motion_controller_data(sdk::IXRTrackingSystem*,
rotation_offset = glm::normalize(pre_flat_pitch * vr->get_rotation_offset());
}

switch (e_hand) {
case ue::EControllerHand::Left: {
data->bValid = true;
const auto left_aim_transform = vr->get_aim_transform(vr->get_left_controller_index());
const auto left_grip_transform = vr->get_grip_transform(vr->get_left_controller_index());
static const auto mc_data_struct = sdk::FUObjectArray::get() != nullptr ? (sdk::UScriptStruct*)sdk::find_uobject(L"ScriptStruct /Script/HeadMountedDisplay.XRMotionControllerData") : nullptr;

const auto aim_position = rotation_offset * glm::vec3{left_aim_transform[3] - vr->get_standing_origin()};
const auto aim_rotation = glm::normalize(rotation_offset * glm::quat{left_aim_transform});
const auto grip_position = rotation_offset * glm::vec3{left_grip_transform[3] - vr->get_standing_origin()};
const auto grip_rotation = glm::normalize(rotation_offset * glm::quat{left_grip_transform});
const auto aim_transform = e_hand == ue::EControllerHand::Left ? vr->get_aim_transform(vr->get_left_controller_index()) : vr->get_aim_transform(vr->get_right_controller_index());
const auto grip_transform = e_hand == ue::EControllerHand::Left ? vr->get_grip_transform(vr->get_left_controller_index()) : vr->get_grip_transform(vr->get_right_controller_index());

const auto final_aim_position = utility::math::glm_to_ue4(aim_position * world_scale);
const auto final_aim_rotation = utility::math::glm_to_ue4(aim_rotation);
const auto final_grip_position = utility::math::glm_to_ue4(grip_position * world_scale);
const auto final_grip_rotation = utility::math::glm_to_ue4(grip_rotation);
const auto aim_position = rotation_offset * glm::vec3{aim_transform[3] - vr->get_standing_origin()};
const auto aim_rotation = glm::normalize(rotation_offset * glm::quat{aim_transform});
const auto grip_position = rotation_offset * glm::vec3{grip_transform[3] - vr->get_standing_origin()};
const auto grip_rotation = glm::normalize(rotation_offset * glm::quat{grip_transform});

const auto final_aim_position = utility::math::glm_to_ue4(aim_position * world_scale);
const auto final_aim_rotation = utility::math::glm_to_ue4(aim_rotation);
const auto final_grip_position = utility::math::glm_to_ue4(grip_position * world_scale);
const auto final_grip_rotation = utility::math::glm_to_ue4(grip_rotation);

if (mc_data_struct == nullptr) {
const auto data = (ue4_27::FXRMotionControllerData*)motion_controller_data;
data->bValid = true;
data->GripRotation = { final_grip_rotation.x, final_grip_rotation.y, final_grip_rotation.z, final_grip_rotation.w };
data->GripPosition = final_grip_position;

data->AimRotation = { final_aim_rotation.x, final_aim_rotation.y, final_aim_rotation.z, final_aim_rotation.w };
data->AimPosition = final_aim_position;

break;
}
case ue::EControllerHand::Right: {
data->bValid = true;
const auto right_aim_transform = vr->get_aim_transform(vr->get_right_controller_index());
const auto right_grip_transform = vr->get_grip_transform(vr->get_right_controller_index());

const auto aim_position = rotation_offset * glm::vec3{right_aim_transform[3] - vr->get_standing_origin()};
const auto aim_rotation = glm::normalize(rotation_offset * glm::quat{right_aim_transform});
const auto grip_position = rotation_offset * glm::vec3{right_grip_transform[3] - vr->get_standing_origin()};
const auto grip_rotation = glm::normalize(rotation_offset * glm::quat{right_grip_transform});
} else {
const auto bValid_prop = mc_data_struct->find_property(L"bValid");
const auto GripRotation_prop = mc_data_struct->find_property(L"GripRotation");
const auto GripPosition_prop = mc_data_struct->find_property(L"GripPosition");
const auto AimRotation_prop = mc_data_struct->find_property(L"AimRotation");
const auto AimPosition_prop = mc_data_struct->find_property(L"AimPosition");
const auto is_ue5 = g_hook->m_stereo_hook->has_double_precision();

if (bValid_prop != nullptr) {
*bValid_prop->get_data<bool>(motion_controller_data) = true;
}

const auto final_aim_position = utility::math::glm_to_ue4(aim_position * world_scale);
const auto final_aim_rotation = utility::math::glm_to_ue4(aim_rotation);
const auto final_grip_position = utility::math::glm_to_ue4(grip_position * world_scale);
const auto final_grip_rotation = utility::math::glm_to_ue4(grip_rotation);
if (GripRotation_prop != nullptr) {
if (is_ue5) {
*GripRotation_prop->get_data<glm::vec<4, double>>(motion_controller_data) = { final_grip_rotation.x, final_grip_rotation.y, final_grip_rotation.z, final_grip_rotation.w };
} else {
*GripRotation_prop->get_data<glm::vec<4, float>>(motion_controller_data) = { final_grip_rotation.x, final_grip_rotation.y, final_grip_rotation.z, final_grip_rotation.w };
}
}

data->GripRotation = { final_grip_rotation.x, final_grip_rotation.y, final_grip_rotation.z, final_grip_rotation.w };
data->GripPosition = final_grip_position;
if (GripPosition_prop != nullptr) {
if (is_ue5) {
*GripPosition_prop->get_data<glm::vec<3, double>>(motion_controller_data) = final_grip_position;
} else {
*GripPosition_prop->get_data<glm::vec<3, float>>(motion_controller_data) = final_grip_position;
}
}

data->AimRotation = { final_aim_rotation.x, final_aim_rotation.y, final_aim_rotation.z, final_aim_rotation.w };
data->AimPosition = final_aim_position;
if (AimRotation_prop != nullptr) {
if (is_ue5) {
*AimRotation_prop->get_data<glm::vec<4, double>>(motion_controller_data) = { final_aim_rotation.x, final_aim_rotation.y, final_aim_rotation.z, final_aim_rotation.w };
} else {
*AimRotation_prop->get_data<glm::vec<4, float>>(motion_controller_data) = { final_aim_rotation.x, final_aim_rotation.y, final_aim_rotation.z, final_aim_rotation.w };
}
}

break;
}
default:
break;
if (AimPosition_prop != nullptr) {
if (is_ue5) {
*AimPosition_prop->get_data<glm::vec<3, double>>(motion_controller_data) = final_aim_position;
} else {
*AimPosition_prop->get_data<glm::vec<3, float>>(motion_controller_data) = final_aim_position;
}
}
}
}

void IXRTrackingSystemHook::get_hmd_data(sdk::IXRTrackingSystem*, void* world, void* hmd_data) {
SPDLOG_INFO_ONCE("get_hmd_data {:x}", (uintptr_t)_ReturnAddress());

const auto& vr = VR::get();
const auto data = (ue4_27::FXRHMDData*)hmd_data;
const auto world_scale = vr->get_world_to_meters();

auto rotation_offset = vr->get_rotation_offset();
Expand All @@ -868,14 +884,40 @@ void IXRTrackingSystemHook::get_hmd_data(sdk::IXRTrackingSystem*, void* world, v
rotation_offset = glm::normalize(pre_flat_pitch * vr->get_rotation_offset());
}

static const auto hmd_data_struct = sdk::FUObjectArray::get() != nullptr ? (sdk::UScriptStruct*)sdk::find_uobject(L"ScriptStruct /Script/HeadMountedDisplay.XRHMDData") : nullptr;

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
data->Position = utility::math::glm_to_ue4(position * world_scale);
if (hmd_data_struct == nullptr) {
const auto data = (ue4_27::FXRHMDData*)hmd_data;
data->Position = utility::math::glm_to_ue4(position * world_scale);

const auto q = utility::math::glm_to_ue4(rotation);
data->Rotation = { q.x, q.y, q.z, q.w };
} else {
const auto Position_prop = hmd_data_struct->find_property(L"Position");
const auto Rotation_prop = hmd_data_struct->find_property(L"Rotation");
const auto is_ue5 = g_hook->m_stereo_hook->has_double_precision();

if (Position_prop != nullptr) {
if (is_ue5) {
*Position_prop->get_data<glm::vec<3, double>>(hmd_data) = utility::math::glm_to_ue4(position * world_scale);
} else {
*Position_prop->get_data<glm::vec<3, float>>(hmd_data) = utility::math::glm_to_ue4(position * world_scale);
}
}

const auto q = utility::math::glm_to_ue4(rotation);
data->Rotation = { q.x, q.y, q.z, q.w };
if (Rotation_prop != nullptr) {
if (is_ue5) {
const auto q = utility::math::glm_to_ue4(rotation);
*Rotation_prop->get_data<glm::vec<4, double>>(hmd_data) = { q.x, q.y, q.z, q.w };
} else {
const auto q = utility::math::glm_to_ue4(rotation);
*Rotation_prop->get_data<glm::vec<4, float>>(hmd_data) = { q.x, q.y, q.z, q.w };
}
}
}
}

void IXRTrackingSystemHook::get_current_pose(sdk::IXRTrackingSystem*, int32_t device_id, Quat<float>* out_rot, glm::vec3* out_pos) {
Expand All @@ -899,11 +941,19 @@ void IXRTrackingSystemHook::get_current_pose(sdk::IXRTrackingSystem*, int32_t de
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 is_ue5 = g_hook->m_stereo_hook->has_double_precision();

const auto q = utility::math::glm_to_ue4(rotation);
*out_rot = { q.x, q.y, q.z, q.w };
if (!is_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 };
} else {
*(glm::vec<3, double>*)out_pos = utility::math::glm_to_ue4(position * world_scale);

const auto q = utility::math::glm_to_ue4(rotation);
*(glm::vec<4, double>*)out_rot = { q.x, q.y, q.z, q.w };
}

break;
}
Expand Down

0 comments on commit 4f2e120

Please sign in to comment.