mirror of
https://github.com/RPCS3/rpcs3.git
synced 2024-12-25 00:15:18 +00:00
cellGem: implement quaternion transformation
This commit is contained in:
parent
3d11b6efa3
commit
a31ebc248e
4
.gitmodules
vendored
4
.gitmodules
vendored
@ -100,3 +100,7 @@
|
||||
path = 3rdparty/opencv/opencv
|
||||
url = ../../Megamouse/opencv_minimal.git
|
||||
ignore = dirty
|
||||
[submodule "3rdparty/fusion/fusion"]
|
||||
path = 3rdparty/fusion/fusion
|
||||
url = ../../xioTechnologies/Fusion.git
|
||||
ignore = dirty
|
||||
|
4
3rdparty/CMakeLists.txt
vendored
4
3rdparty/CMakeLists.txt
vendored
@ -346,6 +346,9 @@ add_subdirectory(rtmidi EXCLUDE_FROM_ALL)
|
||||
# OPENCV
|
||||
add_subdirectory(opencv EXCLUDE_FROM_ALL)
|
||||
|
||||
# FUSION
|
||||
add_subdirectory(fusion EXCLUDE_FROM_ALL)
|
||||
|
||||
# add nice ALIAS targets for ease of use
|
||||
if(USE_SYSTEM_LIBUSB)
|
||||
add_library(3rdparty::libusb ALIAS usb-1.0-shared)
|
||||
@ -377,3 +380,4 @@ add_library(3rdparty::sdl2 ALIAS ${SDL2_TARGET})
|
||||
add_library(3rdparty::miniupnpc ALIAS libminiupnpc-static)
|
||||
add_library(3rdparty::rtmidi ALIAS rtmidi)
|
||||
add_library(3rdparty::opencv ALIAS ${OPENCV_TARGET})
|
||||
add_library(3rdparty::fusion ALIAS Fusion)
|
||||
|
1
3rdparty/fusion/CMakeLists.txt
vendored
Normal file
1
3rdparty/fusion/CMakeLists.txt
vendored
Normal file
@ -0,0 +1 @@
|
||||
add_subdirectory(fusion EXCLUDE_FROM_ALL)
|
1
3rdparty/fusion/fusion
vendored
Submodule
1
3rdparty/fusion/fusion
vendored
Submodule
@ -0,0 +1 @@
|
||||
Subproject commit fecf2f0af3bd23cbba553ceedc2bc6c1cd410fc1
|
75
3rdparty/fusion/fusion.vcxproj
vendored
Normal file
75
3rdparty/fusion/fusion.vcxproj
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="fusion\Fusion\Fusion.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionAhrs.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionAxes.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionCalibration.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionCompass.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionConvention.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionMath.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionOffset.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="fusion\Fusion\FusionAhrs.c" />
|
||||
<ClCompile Include="fusion\Fusion\FusionCompass.c" />
|
||||
<ClCompile Include="fusion\Fusion\FusionOffset.c" />
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<RootNamespace>Fusion</RootNamespace>
|
||||
<ProjectGuid>{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}</ProjectGuid>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\common_default_macros.props" />
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>StaticLibrary</ConfigurationType>
|
||||
<CharacterSet>Unicode</CharacterSet>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<PropertyGroup>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<OutDir>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\</OutDir>
|
||||
<IntDir>$(SolutionDir)build\tmp\$(ProjectName)-$(Configuration)-$(Platform)\</IntDir>
|
||||
</PropertyGroup>
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="Shared">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_default.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_debug.props" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<Import Project="$(SolutionDir)\buildfiles\msvc\rpcs3_release.props" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
|
||||
</ClCompile>
|
||||
</ItemDefinitionGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
29
3rdparty/fusion/fusion.vcxproj.filters
vendored
Normal file
29
3rdparty/fusion/fusion.vcxproj.filters
vendored
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="fusion\Fusion\Fusion.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionAhrs.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionAxes.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionCalibration.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionCompass.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionConvention.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionMath.h" />
|
||||
<ClInclude Include="fusion\Fusion\FusionOffset.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="fusion\Fusion\FusionAhrs.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="fusion\Fusion\FusionCompass.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="fusion\Fusion\FusionOffset.c">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
</Project>
|
@ -7,6 +7,7 @@ EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "emucore", "rpcs3\emucore.vcxproj", "{C4A10229-4712-4BD2-B63E-50D93C67A038}"
|
||||
ProjectSection(ProjectDependencies) = postProject
|
||||
{2C902C67-985C-4BE0-94A3-E0FE2EB929A3} = {2C902C67-985C-4BE0-94A3-E0FE2EB929A3}
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
|
||||
{5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0} = {5228F863-E0DD-4DE7-AA7B-5C52B14CD4D0}
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {8846A9AA-5539-4C91-8301-F54260E1A07A}
|
||||
{939FE206-1182-ABC3-1234-FEAB88E98404} = {939FE206-1182-ABC3-1234-FEAB88E98404}
|
||||
@ -46,6 +47,7 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "rpcs3", "rpcs3\rpcs3.vcxpro
|
||||
{2C902C67-985C-4BE0-94A3-E0FE2EB929A3} = {2C902C67-985C-4BE0-94A3-E0FE2EB929A3}
|
||||
{3384223A-6D97-4799-9862-359F85312892} = {3384223A-6D97-4799-9862-359F85312892}
|
||||
{349EE8F9-7D25-4909-AAF5-FF3FADE72187} = {349EE8F9-7D25-4909-AAF5-FF3FADE72187}
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {3C67A2FF-4710-402A-BE3E-31B0CB0576DF}
|
||||
{3EE5F075-B546-42C4-B6A8-E3CCEF38B78D} = {3EE5F075-B546-42C4-B6A8-E3CCEF38B78D}
|
||||
{508C291A-3D18-49F5-B25D-F7C8DB92CB21} = {508C291A-3D18-49F5-B25D-F7C8DB92CB21}
|
||||
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {5B146DEA-9ACE-4D32-A7FD-3F42464DD69C}
|
||||
@ -103,6 +105,8 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "7zip", "3rdparty\7zip\7zip.
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "openal-soft", "3rdparty\openal\openal-soft.vcxproj", "{8846A9AA-5539-4C91-8301-F54260E1A07A}"
|
||||
EndProject
|
||||
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "fusion", "3rdparty\fusion\fusion.vcxproj", "{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
@ -211,6 +215,10 @@ Global
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Debug|x64.Build.0 = Debug|x64
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Release|x64.ActiveCfg = Release|x64
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A}.Release|x64.Build.0 = Release|x64
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Debug|x64.Build.0 = Debug|x64
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.ActiveCfg = Release|x64
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF}.Release|x64.Build.0 = Release|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@ -243,6 +251,7 @@ Global
|
||||
{4E52A41A-F33B-4C7A-8C36-A1A6B4F4277C} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{5B146DEA-9ACE-4D32-A7FD-3F42464DD69C} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{8846A9AA-5539-4C91-8301-F54260E1A07A} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
{3C67A2FF-4710-402A-BE3E-31B0CB0576DF} = {6C3B64A0-8F8A-4DC4-8C0B-D71EBEED7FA8}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {06CC7920-E085-4B81-9582-8DE8AAD42510}
|
||||
|
@ -82,6 +82,7 @@ target_sources(rpcs3
|
||||
Input/mm_joystick_handler.cpp
|
||||
Input/pad_thread.cpp
|
||||
Input/product_info.cpp
|
||||
Input/ps_move_calibration.cpp
|
||||
Input/ps_move_config.cpp
|
||||
Input/ps_move_handler.cpp
|
||||
Input/ps_move_tracker.cpp
|
||||
@ -110,6 +111,7 @@ target_link_libraries(rpcs3
|
||||
3rdparty::libcurl
|
||||
3rdparty::zlib
|
||||
3rdparty::opencv
|
||||
3rdparty::fusion
|
||||
${ADDITIONAL_LIBS})
|
||||
|
||||
# Unix display manager
|
||||
|
@ -903,7 +903,7 @@ static inline void pos_to_gem_image_state(u32 gem_num, const gem_config::gem_con
|
||||
}
|
||||
}
|
||||
|
||||
static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
|
||||
static inline void pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max, const ps_move_data& move_data)
|
||||
{
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
@ -932,16 +932,28 @@ static inline void pos_to_gem_state(u32 gem_num, const gem_config::gem_controlle
|
||||
gem_state->pos[2] = controller.distance_mm;
|
||||
gem_state->pos[3] = 0.f;
|
||||
|
||||
gem_state->quat[0] = 320.f - image_x;
|
||||
gem_state->quat[1] = (y_pos / scaling_width) - 180.f;
|
||||
gem_state->quat[2] = 1200.f;
|
||||
|
||||
// TODO: calculate handle position based on our world coordinate and the angles
|
||||
gem_state->handle_pos[0] = camera_x;
|
||||
gem_state->handle_pos[1] = camera_y;
|
||||
gem_state->handle_pos[2] = controller.distance_mm + 10.0f;
|
||||
gem_state->handle_pos[3] = 0.f;
|
||||
|
||||
// Calculate orientation
|
||||
if (g_cfg.io.move == move_handler::real)
|
||||
{
|
||||
gem_state->quat[0] = move_data.quaternion[1]; // x
|
||||
gem_state->quat[1] = move_data.quaternion[2]; // y
|
||||
gem_state->quat[2] = move_data.quaternion[3]; // z
|
||||
gem_state->quat[3] = move_data.quaternion[0]; // w
|
||||
}
|
||||
else
|
||||
{
|
||||
gem_state->quat[0] = 320.f - image_x;
|
||||
gem_state->quat[1] = (y_pos / scaling_width) - 180.f;
|
||||
gem_state->quat[2] = 1200.f;
|
||||
gem_state->quat[3] = 1.f;
|
||||
}
|
||||
|
||||
if (g_cfg.io.show_move_cursor)
|
||||
{
|
||||
draw_overlay_cursor(gem_num, controller, x_pos, y_pos, x_max, y_max);
|
||||
@ -1056,7 +1068,7 @@ static inline void ds3_get_stick_values(u32 gem_num, const std::shared_ptr<Pad>&
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, T& gem_state)
|
||||
static void ds3_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
@ -1078,7 +1090,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller&
|
||||
|
||||
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
|
||||
{
|
||||
pos_to_gem_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
|
||||
pos_to_gem_state(gem_num, controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y, {});
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
|
||||
{
|
||||
@ -1087,7 +1099,7 @@ static void ds3_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller&
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void ps_move_pos_to_gem_state(u32 gem_num, const gem_config::gem_controller& controller, T& gem_state)
|
||||
static void ps_move_pos_to_gem_state(u32 gem_num, gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
@ -1114,7 +1126,7 @@ static void ps_move_pos_to_gem_state(u32 gem_num, const gem_config::gem_controll
|
||||
gem_state->accel[1] = pad->move_data.accelerometer_y * 1000; // linear velocity in mm/s²
|
||||
gem_state->accel[2] = pad->move_data.accelerometer_z * 1000; // linear velocity in mm/s²
|
||||
|
||||
pos_to_gem_state(gem_num, controller, gem_state, info.x_pos, info.y_pos, info.x_max, info.y_max);
|
||||
pos_to_gem_state(gem_num, controller, gem_state, info.x_pos, info.y_pos, info.x_max, info.y_max, pad->move_data);
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
|
||||
{
|
||||
@ -1272,7 +1284,7 @@ static bool mouse_input_to_pad(u32 mouse_no, be_t<u16>& digital_buttons, be_t<u1
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void mouse_pos_to_gem_state(u32 mouse_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
static void mouse_pos_to_gem_state(u32 mouse_no, gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
{
|
||||
@ -1295,7 +1307,7 @@ static void mouse_pos_to_gem_state(u32 mouse_no, const gem_config::gem_controlle
|
||||
|
||||
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
|
||||
{
|
||||
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
|
||||
pos_to_gem_state(mouse_no, controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max, {});
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
|
||||
{
|
||||
@ -1345,7 +1357,7 @@ static bool gun_input_to_pad(u32 gem_no, be_t<u16>& digital_buttons, be_t<u16>&
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
static void gun_pos_to_gem_state(u32 gem_no, const gem_config::gem_controller& controller, T& gem_state)
|
||||
static void gun_pos_to_gem_state(u32 gem_no, gem_config::gem_controller& controller, T& gem_state)
|
||||
{
|
||||
if (!gem_state || !is_input_allowed())
|
||||
return;
|
||||
@ -1363,7 +1375,7 @@ static void gun_pos_to_gem_state(u32 gem_no, const gem_config::gem_controller& c
|
||||
|
||||
if constexpr (std::is_same_v<T, vm::ptr<CellGemState>>)
|
||||
{
|
||||
pos_to_gem_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max);
|
||||
pos_to_gem_state(gem_no, controller, gem_state, x_pos, y_pos, x_max, y_max, {});
|
||||
}
|
||||
else if constexpr (std::is_same_v<T, vm::ptr<CellGemImageState>>)
|
||||
{
|
||||
@ -1800,7 +1812,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
|
||||
if (g_cfg.io.move != move_handler::null)
|
||||
{
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
const auto& controller = gem.controllers[gem_num];
|
||||
auto& controller = gem.controllers[gem_num];
|
||||
|
||||
gem_image_state->frame_timestamp = shared_data.frame_timestamp_us.load();
|
||||
gem_image_state->timestamp = gem_image_state->frame_timestamp + 10;
|
||||
@ -2130,7 +2142,6 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
|
||||
|
||||
gem_state->timestamp = (get_guest_system_time() - gem.start_timestamp_us);
|
||||
gem_state->camera_pitch_angle = 0.f;
|
||||
gem_state->quat[3] = 1.f;
|
||||
|
||||
switch (g_cfg.io.move)
|
||||
{
|
||||
|
@ -466,12 +466,13 @@ struct ps_move_data
|
||||
bool external_device_read_requested = false;
|
||||
bool external_device_write_requested = false;
|
||||
|
||||
std::array<f32, 4> quaternion { 1.0f, 0.0f, 0.0f, 0.0f }; // quaternion orientation (x,y,z,w) of controller relative to default (facing the camera with buttons up)
|
||||
f32 accelerometer_x = 0; // linear velocity in m/s²
|
||||
f32 accelerometer_y = 0; // linear velocity in m/s²
|
||||
f32 accelerometer_z = 0; // linear velocity in m/s²
|
||||
f32 gyro_x = 0; // linear velocity in m/s²
|
||||
f32 gyro_y = 0; // linear velocity in m/s²
|
||||
f32 gyro_z = 0; // linear velocity in m/s²
|
||||
f32 gyro_x = 0; // angular velocity in rad/s
|
||||
f32 gyro_y = 0; // angular velocity in rad/s
|
||||
f32 gyro_z = 0; // angular velocity in rad/s
|
||||
s16 temperature = 0;
|
||||
};
|
||||
|
||||
|
240
rpcs3/Input/ps_move_calibration.cpp
Normal file
240
rpcs3/Input/ps_move_calibration.cpp
Normal file
@ -0,0 +1,240 @@
|
||||
#include "stdafx.h"
|
||||
#include "ps_move_calibration.h"
|
||||
|
||||
LOG_CHANNEL(move_log, "Move");
|
||||
|
||||
// This is basically the same as in ps move api
|
||||
|
||||
static inline s32 psmove_calibration_decode_16bit_unsigned(const u8* data, u32 offset)
|
||||
{
|
||||
const u8 low = data[offset] & 0xFF;
|
||||
const u8 high = (data[offset + 1]) & 0xFF;
|
||||
return (low | (high << 8)) - zero_shift;
|
||||
}
|
||||
|
||||
static inline s16 psmove_calibration_decode_16bit_signed(const u8* data, u32 offset)
|
||||
{
|
||||
const u16 low = data[offset] & 0xFF;
|
||||
const u16 high = (data[offset + 1]) & 0xFF;
|
||||
return static_cast<s16>(low | (high << 8));
|
||||
}
|
||||
|
||||
static inline u32 psmove_calibration_decode_12bits(const u8* data, u32 offset)
|
||||
{
|
||||
const u8 low = data[offset] & 0xFF;
|
||||
const u8 high = (data[offset + 1]) & 0xFF;
|
||||
return low | (high << 8);
|
||||
}
|
||||
|
||||
static inline f32 psmove_calibration_decode_float(const u8* data, u32 offset)
|
||||
{
|
||||
union
|
||||
{
|
||||
uint32_t u32;
|
||||
float f;
|
||||
} v {
|
||||
.u32 = static_cast<u32>( (data[offset] & 0xFF) |
|
||||
((data[offset + 1] & 0xFF) << 8) |
|
||||
((data[offset + 2] & 0xFF) << 16) |
|
||||
((data[offset + 3] & 0xFF) << 24))
|
||||
};
|
||||
|
||||
return v.f;
|
||||
}
|
||||
|
||||
static void psmove_dump_calibration(const reports::ps_move_calibration_blob& calibration, const ps_move_device& device)
|
||||
{
|
||||
int t, x, y, z;
|
||||
float fx, fy, fz;
|
||||
|
||||
const u8* data = calibration.data.data();
|
||||
|
||||
switch (device.model)
|
||||
{
|
||||
case ps_move_model::ZCM1:
|
||||
t = psmove_calibration_decode_12bits(data, 0x02);
|
||||
move_log.error("Temperature: 0x%04X", t);
|
||||
for (int orientation = 0; orientation < 6; orientation++)
|
||||
{
|
||||
x = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation);
|
||||
y = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation + 2);
|
||||
z = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * orientation + 4);
|
||||
move_log.error("Orientation #%d: (%5d | %5d | %5d)", orientation, x, y, z);
|
||||
}
|
||||
|
||||
t = psmove_calibration_decode_12bits(data, 0x42);
|
||||
move_log.error("Temperature: 0x%04X", t);
|
||||
for (int orientation = 0; orientation < 3; orientation++)
|
||||
{
|
||||
x = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation);
|
||||
y = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation + 2);
|
||||
z = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * orientation + 4);
|
||||
move_log.error("Gyro %c, 80 rpm: (%5d | %5d | %5d)", "XYZ"[orientation], x, y, z);
|
||||
}
|
||||
|
||||
t = psmove_calibration_decode_12bits(data, 0x28);
|
||||
x = psmove_calibration_decode_16bit_unsigned(data, 0x2a);
|
||||
y = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 2);
|
||||
z = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 4);
|
||||
move_log.error("Temperature: 0x%04X", t);
|
||||
move_log.error("Gyro, 0 rpm (@0x2a): (%5d | %5d | %5d)", x, y, z);
|
||||
|
||||
t = psmove_calibration_decode_12bits(data, 0x30);
|
||||
x = psmove_calibration_decode_16bit_unsigned(data, 0x32);
|
||||
y = psmove_calibration_decode_16bit_unsigned(data, 0x32 + 2);
|
||||
z = psmove_calibration_decode_16bit_unsigned(data, 0x32 + 4);
|
||||
move_log.error("Temperature: 0x%04X", t);
|
||||
move_log.error("Gyro, 0 rpm (@0x32): (%5d | %5d | %5d)", x, y, z);
|
||||
|
||||
t = psmove_calibration_decode_12bits(data, 0x5c);
|
||||
fx = psmove_calibration_decode_float(data, 0x5e);
|
||||
fy = psmove_calibration_decode_float(data, 0x5e + 4);
|
||||
fz = psmove_calibration_decode_float(data, 0x5e + 8);
|
||||
move_log.error("Temperature: 0x%04X", t);
|
||||
move_log.error("Vector @0x5e: (%f | %f | %f)", fx, fy, fz);
|
||||
|
||||
fx = psmove_calibration_decode_float(data, 0x6a);
|
||||
fy = psmove_calibration_decode_float(data, 0x6a + 4);
|
||||
fz = psmove_calibration_decode_float(data, 0x6a + 8);
|
||||
move_log.error("Vector @0x6a: (%f | %f | %f)", fx, fy, fz);
|
||||
|
||||
move_log.error("byte @0x3f: 0x%02x", static_cast<u8>(data[0x3f]));
|
||||
move_log.error("float @0x76: %f", psmove_calibration_decode_float(data, 0x76));
|
||||
move_log.error("float @0x7a: %f", psmove_calibration_decode_float(data, 0x7a));
|
||||
break;
|
||||
case ps_move_model::ZCM2:
|
||||
for (int orientation = 0; orientation < 6; orientation++)
|
||||
{
|
||||
x = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation);
|
||||
y = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation + 2);
|
||||
z = psmove_calibration_decode_16bit_signed(data, 0x04 + 6 * orientation + 4);
|
||||
move_log.error("Orientation #%d: (%5d | %5d | %5d)", orientation, x, y, z);
|
||||
}
|
||||
|
||||
x = psmove_calibration_decode_16bit_signed(data, 0x26);
|
||||
y = psmove_calibration_decode_16bit_signed(data, 0x26 + 2);
|
||||
z = psmove_calibration_decode_16bit_signed(data, 0x26 + 4);
|
||||
move_log.error("Gyro Bias?, 0 rpm (@0x26): (%5d | %5d | %5d)", x, y, z);
|
||||
|
||||
for (int orientation = 0; orientation < 6; orientation++)
|
||||
{
|
||||
x = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation);
|
||||
y = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation + 2);
|
||||
z = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * orientation + 4);
|
||||
move_log.error("Gyro %c, 90 rpm: (%5d | %5d | %5d)", "XYZXYZ"[orientation], x, y, z);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void psmove_calibration_get_usb_accel_values(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
|
||||
{
|
||||
const u8* data = calibration.data.data();
|
||||
|
||||
int x1 = 0, x2 = 0, y1 = 0, y2 = 0, z1 = 0, z2 = 0;
|
||||
|
||||
switch (device.model)
|
||||
{
|
||||
case ps_move_model::ZCM1:
|
||||
// Minimum (negative) value of each axis
|
||||
x1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 1);
|
||||
y1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 5 + 2);
|
||||
z1 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 2 + 4);
|
||||
|
||||
// Maximum (positive) value of each axis
|
||||
x2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 3);
|
||||
y2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 4 + 2);
|
||||
z2 = psmove_calibration_decode_16bit_unsigned(data, 0x04 + 6 * 0 + 4);
|
||||
break;
|
||||
case ps_move_model::ZCM2:
|
||||
// Minimum (negative) value of each axis
|
||||
x1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 1);
|
||||
y1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 3 + 2);
|
||||
z1 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 5 + 4);
|
||||
|
||||
// Maximum (positive) value of each axis
|
||||
x2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 0);
|
||||
y2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 2 + 2);
|
||||
z2 = psmove_calibration_decode_16bit_signed(data, 0x02 + 6 * 4 + 4);
|
||||
break;
|
||||
}
|
||||
|
||||
device.calibration.accel_x_factor = 2.0f / static_cast<float>(x2 - x1);
|
||||
device.calibration.accel_y_factor = 2.0f / static_cast<float>(y2 - y1);
|
||||
device.calibration.accel_z_factor = 2.0f / static_cast<float>(z2 - z1);
|
||||
|
||||
device.calibration.accel_x_offset = -(device.calibration.accel_x_factor * static_cast<float>(x1)) - 1.0f;
|
||||
device.calibration.accel_y_offset = -(device.calibration.accel_y_factor * static_cast<float>(x1)) - 1.0f;
|
||||
device.calibration.accel_z_offset = -(device.calibration.accel_z_factor * static_cast<float>(x1)) - 1.0f;
|
||||
}
|
||||
|
||||
void psmove_calibration_get_usb_gyro_values(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
|
||||
{
|
||||
const u8* data = calibration.data.data();
|
||||
|
||||
constexpr f32 PI = 3.14159265f;
|
||||
constexpr f32 rpm_to_rad_per_sec = (2.0f * PI) / 60.0f;
|
||||
|
||||
switch (device.model)
|
||||
{
|
||||
case ps_move_model::ZCM1:
|
||||
{
|
||||
const int bx = psmove_calibration_decode_16bit_unsigned(data, 0x2a);
|
||||
const int by = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 2);
|
||||
const int bz = psmove_calibration_decode_16bit_unsigned(data, 0x2a + 4);
|
||||
|
||||
const int x = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 0) - bx;
|
||||
const int y = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 1 + 2) - by;
|
||||
const int z = psmove_calibration_decode_16bit_unsigned(data, 0x46 + 8 * 2 + 4) - bz;
|
||||
|
||||
constexpr f32 calibration_rpm = 80.0f;
|
||||
constexpr f32 factor = calibration_rpm * rpm_to_rad_per_sec;
|
||||
|
||||
// Per frame drift taken into account using adjusted gain values
|
||||
device.calibration.gyro_x_gain = factor / static_cast<float>(x);
|
||||
device.calibration.gyro_y_gain = factor / static_cast<float>(y);
|
||||
device.calibration.gyro_z_gain = factor / static_cast<float>(z);
|
||||
device.calibration.gyro_x_offset = 0;
|
||||
device.calibration.gyro_y_offset = 0;
|
||||
device.calibration.gyro_z_offset = 0;
|
||||
break;
|
||||
}
|
||||
case ps_move_model::ZCM2:
|
||||
{
|
||||
// Minimum (negative) value of each axis
|
||||
const int x1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 3);
|
||||
const int y1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 4 + 2);
|
||||
const int z1 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 5 + 4);
|
||||
|
||||
// Maximum (positive) values of each axis
|
||||
const int x2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 0);
|
||||
const int y2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 1 + 2);
|
||||
const int z2 = psmove_calibration_decode_16bit_signed(data, 0x30 + 6 * 2 + 4);
|
||||
|
||||
const int dx = psmove_calibration_decode_16bit_signed(data, 0x26);
|
||||
const int dy = psmove_calibration_decode_16bit_signed(data, 0x26 + 2);
|
||||
const int dz = psmove_calibration_decode_16bit_signed(data, 0x26 + 4);
|
||||
|
||||
constexpr f32 calibration_rpm = 90.0f;
|
||||
constexpr f32 calibration_hi = calibration_rpm * rpm_to_rad_per_sec;
|
||||
constexpr f32 calibration_low = -calibration_rpm * rpm_to_rad_per_sec;
|
||||
constexpr f32 factor = calibration_hi - calibration_low;
|
||||
|
||||
// Compute the gain value (the slope of the gyro reading/angular speed line)
|
||||
device.calibration.gyro_x_gain = factor / static_cast<f32>(x2 - x1);
|
||||
device.calibration.gyro_y_gain = factor / static_cast<f32>(y2 - y1);
|
||||
device.calibration.gyro_z_gain = factor / static_cast<f32>(z2 - z1);
|
||||
device.calibration.gyro_x_offset = static_cast<f32>(dx);
|
||||
device.calibration.gyro_y_offset = static_cast<f32>(dy);
|
||||
device.calibration.gyro_z_offset = static_cast<f32>(dz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void psmove_parse_calibration(const reports::ps_move_calibration_blob& calibration, ps_move_device& device)
|
||||
{
|
||||
psmove_dump_calibration(calibration, device);
|
||||
psmove_calibration_get_usb_accel_values(calibration, device);
|
||||
psmove_calibration_get_usb_gyro_values(calibration, device);
|
||||
}
|
5
rpcs3/Input/ps_move_calibration.h
Normal file
5
rpcs3/Input/ps_move_calibration.h
Normal file
@ -0,0 +1,5 @@
|
||||
#pragma once
|
||||
|
||||
#include "ps_move_handler.h"
|
||||
|
||||
void psmove_parse_calibration(const reports::ps_move_calibration_blob& calibration, ps_move_device& device);
|
@ -1,5 +1,6 @@
|
||||
#include "stdafx.h"
|
||||
#include "ps_move_handler.h"
|
||||
#include "ps_move_calibration.h"
|
||||
#include "Emu/Io/pad_config.h"
|
||||
#include "Emu/System.h"
|
||||
#include "Emu/system_config.h"
|
||||
@ -57,11 +58,6 @@ namespace
|
||||
usb_charging = 0xEE,
|
||||
usb_charged = 0xEF,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
zero_shift = 0x8000,
|
||||
};
|
||||
}
|
||||
|
||||
const ps_move_input_report_common& ps_move_device::input_report_common() const
|
||||
@ -223,7 +219,7 @@ hid_device* ps_move_handler::connect_move_device(ps_move_device* device, std::st
|
||||
|
||||
if (hid_set_nonblocking(device->bt_device, 1) == -1)
|
||||
{
|
||||
move_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->bt_device));
|
||||
move_log.error("connect_move_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->bt_device));
|
||||
device->close();
|
||||
return nullptr;
|
||||
}
|
||||
@ -239,7 +235,7 @@ hid_device* ps_move_handler::connect_move_device(ps_move_device* device, std::st
|
||||
|
||||
if (hid_set_nonblocking(device->hidDevice, 1) == -1)
|
||||
{
|
||||
move_log.error("check_add_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->hidDevice));
|
||||
move_log.error("connect_move_device: hid_set_nonblocking failed! Reason: %s", hid_error(device->hidDevice));
|
||||
device->close();
|
||||
return nullptr;
|
||||
}
|
||||
@ -315,6 +311,60 @@ void ps_move_handler::check_add_device(hid_device* hidDevice, std::string_view p
|
||||
device->hidDevice = hidDevice;
|
||||
device->path = path;
|
||||
|
||||
// Get calibration
|
||||
device->calibration.is_valid = true;
|
||||
|
||||
ps_move_calibration_blob calibration {};
|
||||
|
||||
for (int i = 0; i < 2; i++)
|
||||
{
|
||||
std::array<u8, PSMOVE_CALIBRATION_SIZE> cal {};
|
||||
cal[0] = 0x10;
|
||||
const int res = hid_get_feature_report(device->hidDevice, cal.data(), cal.size());
|
||||
if (res < 0)
|
||||
{
|
||||
move_log.error("connect_move_device: hid_get_feature_report 0x10 (calibration) failed! result=%d, error=%s", res, hid_error(device->hidDevice));
|
||||
device->calibration.is_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
int src_offset = 0;
|
||||
int dest_offset = 0;
|
||||
|
||||
if ((cal[1] == 0x01 && device->model == ps_move_model::ZCM1) ||
|
||||
(cal[1] == 0x81 && device->model == ps_move_model::ZCM2))
|
||||
{
|
||||
// This is the second block
|
||||
dest_offset = PSMOVE_CALIBRATION_SIZE;
|
||||
src_offset = 2;
|
||||
}
|
||||
else if (cal[1] == 0x82 && device->model == ps_move_model::ZCM1)
|
||||
{
|
||||
// This is the third block
|
||||
dest_offset = 2 * PSMOVE_CALIBRATION_SIZE - 2;
|
||||
src_offset = 2;
|
||||
}
|
||||
else if (cal[1] != 0x00) // Check if this is the first block (offsets stay 0)
|
||||
{
|
||||
move_log.error("connect_move_device: Failed to read calibration: cal=0x%x'", cal[1]);
|
||||
device->calibration.is_valid = false;
|
||||
break;
|
||||
}
|
||||
|
||||
std::memcpy(&calibration.data[dest_offset], &cal[src_offset], cal.size() - src_offset);
|
||||
}
|
||||
|
||||
if (device->calibration.is_valid)
|
||||
{
|
||||
psmove_parse_calibration(calibration, *device);
|
||||
}
|
||||
|
||||
// Initialize Fusion
|
||||
FusionAhrsInitialise(&device->ahrs);
|
||||
device->ahrs.settings.convention = FusionConvention::FusionConventionEnu;
|
||||
FusionAhrsSetSettings(&device->ahrs, &device->ahrs.settings);
|
||||
FusionAhrsReset(&device->ahrs);
|
||||
|
||||
// Activate
|
||||
if (send_output_report(device) == -1)
|
||||
{
|
||||
@ -620,34 +670,48 @@ void ps_move_handler::get_extended_info(const pad_ensemble& binding)
|
||||
|
||||
const ps_move_input_report_common& input = dev->input_report_common();
|
||||
|
||||
constexpr f32 MOVE_ONE_G = 4096.0f; // This is just a rough estimate and probably depends on the device
|
||||
|
||||
// The default position is flat on the ground, pointing forward.
|
||||
// The accelerometers constantly measure G forces.
|
||||
// The gyros measure changes in orientation and will reset when the device isn't moved anymore.
|
||||
s16 accel_x = input.accel_x_2; // Increases if the device is rolled to the left
|
||||
s16 accel_y = input.accel_y_2; // Increases if the device is pitched upwards
|
||||
s16 accel_z = input.accel_z_2; // Increases if the device is moved upwards
|
||||
s16 gyro_x = input.gyro_x_2; // Increases if the device is pitched upwards
|
||||
s16 gyro_y = input.gyro_y_2; // Increases if the device is rolled to the right
|
||||
s16 gyro_z = input.gyro_z_2; // Increases if the device is yawed to the left
|
||||
s16 accel_x = input.accel_x_1; // Increases if the device is rolled to the left
|
||||
s16 accel_y = input.accel_y_1; // Increases if the device is pitched upwards
|
||||
s16 accel_z = input.accel_z_1; // Increases if the device is moved upwards
|
||||
s16 gyro_x = input.gyro_x_1; // Increases if the device is pitched upwards
|
||||
s16 gyro_y = input.gyro_y_1; // Increases if the device is rolled to the right
|
||||
s16 gyro_z = input.gyro_z_1; // Increases if the device is yawed to the left
|
||||
|
||||
if (dev->model == ps_move_model::ZCM1)
|
||||
{
|
||||
accel_x -= zero_shift;
|
||||
accel_y -= zero_shift;
|
||||
accel_z -= zero_shift;
|
||||
gyro_x -= zero_shift;
|
||||
gyro_y -= zero_shift;
|
||||
gyro_z -= zero_shift;
|
||||
accel_x = (input.accel_x_1 + input.accel_x_2) / 2 - zero_shift;
|
||||
accel_y = (input.accel_y_1 + input.accel_y_2) / 2 - zero_shift;
|
||||
accel_z = (input.accel_z_1 + input.accel_z_2) / 2 - zero_shift;
|
||||
gyro_x = (input.gyro_x_1 + input.gyro_x_2) / 2 - zero_shift;
|
||||
gyro_y = (input.gyro_y_1 + input.gyro_y_2) / 2 - zero_shift;
|
||||
gyro_z = (input.gyro_z_1 + input.gyro_z_2) / 2 - zero_shift;
|
||||
}
|
||||
|
||||
// Apply calibration
|
||||
if (dev->calibration.is_valid)
|
||||
{
|
||||
pad->move_data.accelerometer_x = accel_x * dev->calibration.accel_x_factor + dev->calibration.accel_x_offset;
|
||||
pad->move_data.accelerometer_y = accel_y * dev->calibration.accel_y_factor + dev->calibration.accel_y_offset;
|
||||
pad->move_data.accelerometer_z = accel_z * dev->calibration.accel_z_factor + dev->calibration.accel_z_offset;
|
||||
pad->move_data.gyro_x = (gyro_x - dev->calibration.gyro_x_offset) * dev->calibration.gyro_x_gain;
|
||||
pad->move_data.gyro_y = (gyro_y - dev->calibration.gyro_y_offset) * dev->calibration.gyro_y_gain;
|
||||
pad->move_data.gyro_z = (gyro_z - dev->calibration.gyro_z_offset) * dev->calibration.gyro_z_gain;
|
||||
}
|
||||
else
|
||||
{
|
||||
constexpr f32 MOVE_ONE_G = 4096.0f; // This is just a rough estimate and probably depends on the device
|
||||
|
||||
pad->move_data.accelerometer_x = accel_x / MOVE_ONE_G;
|
||||
pad->move_data.accelerometer_y = accel_y / MOVE_ONE_G;
|
||||
pad->move_data.accelerometer_z = accel_z / MOVE_ONE_G;
|
||||
pad->move_data.gyro_x = gyro_x / MOVE_ONE_G;
|
||||
pad->move_data.gyro_y = gyro_y / MOVE_ONE_G;
|
||||
pad->move_data.gyro_z = gyro_z / MOVE_ONE_G;
|
||||
}
|
||||
|
||||
pad->move_data.accelerometer_x = accel_x / MOVE_ONE_G;
|
||||
pad->move_data.accelerometer_y = accel_y / MOVE_ONE_G;
|
||||
pad->move_data.accelerometer_z = accel_z / MOVE_ONE_G;
|
||||
pad->move_data.gyro_x = accel_x / MOVE_ONE_G;
|
||||
pad->move_data.gyro_y = accel_y / MOVE_ONE_G;
|
||||
pad->move_data.gyro_z = accel_z / MOVE_ONE_G;
|
||||
pad->move_data.temperature = ((input.temperature << 4) | ((input.magnetometer_x & 0xF0) >> 4));
|
||||
|
||||
pad->m_sensors[0].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.accelerometer_x * -1.0f));
|
||||
@ -655,6 +719,58 @@ void ps_move_handler::get_extended_info(const pad_ensemble& binding)
|
||||
pad->m_sensors[2].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.accelerometer_z));
|
||||
pad->m_sensors[3].m_value = Clamp0To1023(512.0f + (MOTION_ONE_G * pad->move_data.gyro_z * -1.0f));
|
||||
|
||||
// Get elapsed time since last update
|
||||
const u64 now_us = get_system_time();
|
||||
const float elapsed_sec = (dev->last_ahrs_update_time_us == 0) ? 0.0f : ((now_us - dev->last_ahrs_update_time_us) / 1'000'000.0f);
|
||||
dev->last_ahrs_update_time_us = now_us;
|
||||
|
||||
// The ps move handler's axis may differ from the Fusion axis, so we have to map them correctly.
|
||||
// Don't ask how the axis work. It's basically been trial and error.
|
||||
ensure(dev->ahrs.settings.convention == FusionConvention::FusionConventionEnu); // East-North-Up
|
||||
|
||||
const FusionVector accelerometer{
|
||||
.axis {
|
||||
.x = -pad->move_data.accelerometer_x,
|
||||
.y = +pad->move_data.accelerometer_y,
|
||||
.z = +pad->move_data.accelerometer_z
|
||||
}
|
||||
};
|
||||
|
||||
static constexpr f32 PI = 3.14159265f;
|
||||
const auto rad_to_degree = [](f32 radians) -> f32 { return radians * 180.0f / PI; };
|
||||
const FusionVector gyroscope{
|
||||
.axis {
|
||||
.x = +rad_to_degree(pad->move_data.gyro_x),
|
||||
.y = +rad_to_degree(pad->move_data.gyro_z),
|
||||
.z = -rad_to_degree(pad->move_data.gyro_y)
|
||||
}
|
||||
};
|
||||
|
||||
FusionVector magnetometer {};
|
||||
|
||||
// TODO: use magnetometer if possible
|
||||
//if (dev->model == ps_move_model::ZCM1)
|
||||
//{
|
||||
// const ps_move_input_report_ZCM1& input = dev->input_report_ZCM1;
|
||||
// magnetometer = FusionVector{
|
||||
// .axis {
|
||||
// .x = input.magnetometer_x2,
|
||||
// .y = input.magnetometer_y,
|
||||
// .z = input.magnetometer_z
|
||||
// }
|
||||
// };
|
||||
//}
|
||||
|
||||
// Update Fusion
|
||||
FusionAhrsUpdate(&dev->ahrs, gyroscope, accelerometer, magnetometer, elapsed_sec);
|
||||
|
||||
// Get quaternion
|
||||
const FusionQuaternion quaternion = FusionAhrsGetQuaternion(&dev->ahrs);
|
||||
pad->move_data.quaternion[0] = quaternion.array[0];
|
||||
pad->move_data.quaternion[1] = quaternion.array[1];
|
||||
pad->move_data.quaternion[2] = quaternion.array[2];
|
||||
pad->move_data.quaternion[3] = quaternion.array[3];
|
||||
|
||||
handle_external_device(binding);
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,15 @@
|
||||
|
||||
#include "hid_pad_handler.h"
|
||||
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wold-style-cast"
|
||||
#endif
|
||||
#include "3rdparty/fusion/fusion/Fusion/Fusion.h"
|
||||
#ifndef _MSC_VER
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
namespace reports
|
||||
@ -80,14 +89,50 @@ namespace reports
|
||||
{
|
||||
std::array<u8, 4> data{}; // TODO
|
||||
};
|
||||
|
||||
// Buffer size for calibration data
|
||||
constexpr u32 PSMOVE_CALIBRATION_SIZE = 49;
|
||||
|
||||
// Three blocks, minus header (2 bytes) for blocks 2,3
|
||||
constexpr u32 PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 3 - 2 * 2;
|
||||
|
||||
// Three blocks, minus header (2 bytes) for block 2
|
||||
constexpr u32 PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE = PSMOVE_CALIBRATION_SIZE * 2 - 2 * 1;
|
||||
|
||||
struct ps_move_calibration_blob
|
||||
{
|
||||
std::array<u8, std::max(PSMOVE_ZCM1_CALIBRATION_BLOB_SIZE, PSMOVE_ZCM2_CALIBRATION_BLOB_SIZE)> data{};
|
||||
};
|
||||
}
|
||||
|
||||
enum
|
||||
{
|
||||
zero_shift = 0x8000,
|
||||
};
|
||||
|
||||
enum class ps_move_model
|
||||
{
|
||||
ZCM1, // PS3
|
||||
ZCM2, // PS4
|
||||
};
|
||||
|
||||
struct ps_move_calibration
|
||||
{
|
||||
bool is_valid = false;
|
||||
f32 accel_x_factor = 1.0f;
|
||||
f32 accel_y_factor = 1.0f;
|
||||
f32 accel_z_factor = 1.0f;
|
||||
f32 accel_x_offset = 0.0f;
|
||||
f32 accel_y_offset = 0.0f;
|
||||
f32 accel_z_offset = 0.0f;
|
||||
f32 gyro_x_gain = 1.0f;
|
||||
f32 gyro_y_gain = 1.0f;
|
||||
f32 gyro_z_gain = 1.0f;
|
||||
f32 gyro_x_offset = 0.0f;
|
||||
f32 gyro_y_offset = 0.0f;
|
||||
f32 gyro_z_offset = 0.0f;
|
||||
};
|
||||
|
||||
class ps_move_device : public HidDevice
|
||||
{
|
||||
public:
|
||||
@ -98,6 +143,10 @@ public:
|
||||
reports::ps_move_output_report last_output_report{};
|
||||
steady_clock::time_point last_output_report_time;
|
||||
u32 external_device_id = 0;
|
||||
ps_move_calibration calibration{};
|
||||
|
||||
FusionAhrs ahrs {}; // Used to calculate quaternions from sensor data
|
||||
u64 last_ahrs_update_time_us = 0; // Last ahrs update
|
||||
|
||||
const reports::ps_move_input_report_common& input_report_common() const;
|
||||
};
|
||||
|
@ -40,7 +40,7 @@
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>Use</PrecompiledHeader>
|
||||
<AdditionalIncludeDirectories>..\3rdparty\miniupnp\miniupnp\miniupnpc\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\flatbuffers\include;..\3rdparty\libusb\libusb\libusb;..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\zlib\zlib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm\include;$(VULKAN_SDK)\Include;..\3rdparty\zstd\zstd\lib</AdditionalIncludeDirectories>
|
||||
<AdditionalIncludeDirectories>..\3rdparty\miniupnp\miniupnp\miniupnpc\include;..\3rdparty\wolfssl\wolfssl;..\3rdparty\flatbuffers\include;..\3rdparty\libusb\libusb\libusb;..\3rdparty\yaml-cpp\yaml-cpp\include;..\3rdparty\SoundTouch\soundtouch\include;..\3rdparty\rtmidi\rtmidi;..\3rdparty\zlib\zlib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm_build\include;$(SolutionDir)build\lib_ext\$(Configuration)-$(Platform)\llvm\include;$(VULKAN_SDK)\Include;..\3rdparty\zstd\zstd\lib;$(SolutionDir)3rdparty\fusion\fusion\Fusion</AdditionalIncludeDirectories>
|
||||
<Optimization Condition="'$(Configuration)|$(Platform)'=='Release|x64'">MaxSpeed</Optimization>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">AL_LIBTYPE_STATIC;MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<PreprocessorDefinitions Condition="'$(Configuration)|$(Platform)'=='Release|x64'">AL_LIBTYPE_STATIC;MINIUPNP_STATICLIB;HAVE_VULKAN;HAVE_SDL2;ZLIB_CONST;%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
|
@ -62,12 +62,12 @@
|
||||
<IgnoreImportLibrary Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</IgnoreImportLibrary>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include</IncludePath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include;$(SolutionDir)3rdparty\fusion\fusion\Fusion</IncludePath>
|
||||
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<LibraryPath>$(SolutionDir)build\lib\$(Configuration)-$(Platform)\;$(UniversalCRT_LibraryPath_x64);$(LibraryPath)</LibraryPath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include</IncludePath>
|
||||
<IncludePath>$(SolutionDir)3rdparty\7zip\7zip\C;$(SolutionDir)3rdparty\hidapi\hidapi\hidapi;.\;$(SolutionDir);$(SolutionDir)3rdparty\asmjit\asmjit\src;$(SolutionDir)3rdparty\yaml-cpp\yaml-cpp\include;$(SolutionDir)3rdparty\ffmpeg\include;$(VC_IncludePath);$(WindowsSDK_IncludePath);$(UniversalCRT_IncludePath);$(SolutionDir)3rdparty\libpng\libpng;$(SolutionDir)3rdparty\GL;$(SolutionDir)3rdparty\stblib\stb;$(SolutionDir)3rdparty\openal\openal-soft\include\AL;$(SolutionDir)3rdparty\pugixml\src;$(SolutionDir)3rdparty\Optional;$(SolutionDir)3rdparty\discord-rpc\include;$(SolutionDir)3rdparty\zlib\zlib;$(SolutionDir)3rdparty\libsdl-org\SDL\include;$(SolutionDir)3rdparty\fusion\fusion\Fusion</IncludePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
@ -89,7 +89,7 @@
|
||||
<ExternalWarningLevel>TurnOffAllWarnings</ExternalWarningLevel>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslang.lib;OSDependent.lib;OGLCompiler.lib;SPIRV.lib;MachineIndependent.lib;GenericCodeGen.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Core.lib;Qt6Gui.lib;Qt6Widgets.lib;Qt6Concurrent.lib;Qt6Multimedia.lib;Qt6MultimediaWidgets.lib;Qt6Svg.lib;Qt6SvgWidgets.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)build\lib_ext\$(CONFIGURATION)-$(PLATFORM);$(SolutionDir)3rdparty\discord-rpc\lib;$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
@ -141,7 +141,7 @@
|
||||
<ProgramDataBaseFileName>$(IntDir)vc$(PlatformToolsetVersion).pdb</ProgramDataBaseFileName>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opencv_world4100.lib;DbgHelp.lib;Ole32.lib;gdi32.lib;hidapi.lib;libusb-1.0.lib;winmm.lib;miniupnpc_static.lib;rtmidi.lib;imm32.lib;ksuser.lib;version.lib;OpenAL32.lib;XAudio.lib;GLGSRender.lib;shlwapi.lib;VKGSRender.lib;vulkan-1.lib;wolfssl.lib;libcurl.lib;Wldap32.lib;glslangd.lib;OSDependentd.lib;OGLCompilerd.lib;SPIRVd.lib;MachineIndependentd.lib;GenericCodeGend.lib;Advapi32.lib;user32.lib;zlib.lib;zstd.lib;libpng16.lib;asmjit.lib;yaml-cpp.lib;discord-rpc.lib;emucore.lib;dxgi.lib;shell32.lib;Qt6Cored.lib;Qt6Guid.lib;Qt6Widgetsd.lib;Qt6Concurrentd.lib;Qt6Multimediad.lib;Qt6MultimediaWidgetsd.lib;Qt6Svgd.lib;Qt6SvgWidgetsd.lib;7zip.lib;libcubeb.lib;cubeb.lib;soundtouch.lib;Avrt.lib;SDL.lib;fusion.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>$(SolutionDir)3rdparty\opencv\opencv\opencv410\build\x64\lib;$(SolutionDir)build\lib\$(Configuration)-$(Platform)\glslang;$(SolutionDir)3rdparty\discord-rpc\lib;$(SolutionDir)build\lib\$(CONFIGURATION)-$(PLATFORM);$(QTDIR)\lib;$(VULKAN_SDK)\Lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>"/MANIFESTDEPENDENCY:type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' publicKeyToken='6595b64144ccf1df' language='*' processorArchitecture='*'" /VERBOSE %(AdditionalOptions)</AdditionalOptions>
|
||||
<DataExecutionPrevention>true</DataExecutionPrevention>
|
||||
@ -179,6 +179,7 @@
|
||||
<ClCompile Include="Input\evdev_gun_handler.cpp" />
|
||||
<ClCompile Include="Input\gui_pad_thread.cpp" />
|
||||
<ClCompile Include="Input\hid_pad_handler.cpp" />
|
||||
<ClCompile Include="Input\ps_move_calibration.cpp" />
|
||||
<ClCompile Include="Input\ps_move_config.cpp" />
|
||||
<ClCompile Include="Input\ps_move_tracker.cpp" />
|
||||
<ClCompile Include="Input\raw_mouse_config.cpp" />
|
||||
@ -971,6 +972,7 @@
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
<AdditionalInputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(QTDIR)\bin\moc.exe;%(FullPath);$(QTDIR)\bin\moc.exe;%(FullPath)</AdditionalInputs>
|
||||
</CustomBuild>
|
||||
<ClInclude Include="Input\ps_move_calibration.h" />
|
||||
<ClInclude Include="Input\ps_move_config.h" />
|
||||
<ClInclude Include="Input\ps_move_tracker.h" />
|
||||
<ClInclude Include="Input\raw_mouse_config.h" />
|
||||
|
@ -1143,6 +1143,9 @@
|
||||
<ClCompile Include="Input\ps_move_config.cpp">
|
||||
<Filter>Io\Move</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Input\ps_move_calibration.cpp">
|
||||
<Filter>Io\Move</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Input\ds4_pad_handler.h">
|
||||
@ -1343,6 +1346,9 @@
|
||||
<ClInclude Include="Input\ps_move_config.h">
|
||||
<Filter>Io\Move</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Input\ps_move_calibration.h">
|
||||
<Filter>Io\Move</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="debug\moc_predefs.h.cbt">
|
||||
|
@ -160,4 +160,5 @@ target_link_libraries(rpcs3_ui
|
||||
3rdparty::wolfssl
|
||||
3rdparty::libcurl
|
||||
3rdparty::opencv
|
||||
3rdparty::fusion
|
||||
3rdparty::rtmidi)
|
||||
|
Loading…
Reference in New Issue
Block a user