mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-22 04:25:19 +00:00
cellGem: fix mouse positions
This commit is contained in:
parent
ccb7531289
commit
dd7f24b20e
5 changed files with 98 additions and 56 deletions
|
@ -448,6 +448,10 @@ error_code cellCameraOpenEx(s32 dev_num, vm::ptr<CellCameraInfoEx> info)
|
|||
g_camera.is_open = true;
|
||||
g_camera.info = *info;
|
||||
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
shared_data.width = info->width > 0 ? +info->width : 640;
|
||||
shared_data.height = info->height > 0 ? +info->height : 480;
|
||||
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -443,5 +443,7 @@ using camera_thread = named_thread<camera_context>;
|
|||
/// Shared data between cellGem and cellCamera
|
||||
struct gem_camera_shared
|
||||
{
|
||||
atomic_t<s64> frame_timestamp; // latest read timestamp from cellCamera (cellCameraRead(Ex))
|
||||
atomic_t<s64> frame_timestamp{}; // latest read timestamp from cellCamera (cellCameraRead(Ex))
|
||||
atomic_t<s32> width{640};
|
||||
atomic_t<s32> height{480};
|
||||
};
|
||||
|
|
|
@ -3,9 +3,10 @@
|
|||
#include "cellCamera.h"
|
||||
|
||||
#include "Emu/Cell/PPUModule.h"
|
||||
#include "Emu/Cell/timers.hpp"
|
||||
#include "Emu/Io/MouseHandler.h"
|
||||
#include "Emu/RSX/GSRender.h"
|
||||
#include "Utilities/Timer.h"
|
||||
#include "Emu/system_config.h"
|
||||
#include "Emu/IdManager.h"
|
||||
#include "Input/pad_thread.h"
|
||||
|
||||
LOG_CHANNEL(cellGem);
|
||||
|
@ -92,6 +93,10 @@ struct gem_config
|
|||
u8 rumble = 0; // Rumble intensity
|
||||
gem_color sphere_rgb = {}; // RGB color of the sphere LED
|
||||
u32 hue = 0; // Tracking hue of the motion controller
|
||||
u32 distance{1500}; // Distance from the camera in mm
|
||||
u32 radius{10}; // Radius of the sphere in camera pixels
|
||||
|
||||
static constexpr s32 diameter_mm = 45; // Physical diameter of the sphere in millimeter
|
||||
};
|
||||
|
||||
CellGemAttribute attribute = {};
|
||||
|
@ -164,9 +169,7 @@ static bool ds3_input_to_pad(const u32 port_no, be_t<u16>& digital_buttons, be_t
|
|||
std::scoped_lock lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
auto pad = pads[port_no];
|
||||
auto& pad = handler->GetPads()[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return false;
|
||||
|
@ -250,9 +253,7 @@ static bool ds3_input_to_ext(const u32 port_no, const gem_config::gem_controller
|
|||
std::scoped_lock lock(pad::g_pad_mutex);
|
||||
|
||||
const auto handler = pad::get_current_handler();
|
||||
|
||||
auto& pads = handler->GetPads();
|
||||
auto pad = pads[port_no];
|
||||
auto& pad = handler->GetPads()[port_no];
|
||||
|
||||
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
|
||||
return false;
|
||||
|
@ -313,17 +314,17 @@ static bool mouse_input_to_pad(const u32 mouse_no, be_t<u16>& digital_buttons, b
|
|||
digital_buttons |= CELL_GEM_CTRL_CROSS;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_4))
|
||||
digital_buttons |= CELL_GEM_CTRL_SELECT;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_5))
|
||||
digital_buttons |= CELL_GEM_CTRL_START;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_6) || (is_pressed(CELL_MOUSE_BUTTON_1) && is_pressed(CELL_MOUSE_BUTTON_2)))
|
||||
digital_buttons |= CELL_GEM_CTRL_CIRCLE;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_7) || (is_pressed(CELL_MOUSE_BUTTON_1) && is_pressed(CELL_MOUSE_BUTTON_3)))
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_5))
|
||||
digital_buttons |= CELL_GEM_CTRL_SQUARE;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_6) || (is_pressed(CELL_MOUSE_BUTTON_1) && is_pressed(CELL_MOUSE_BUTTON_2)))
|
||||
digital_buttons |= CELL_GEM_CTRL_SELECT;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_7) || (is_pressed(CELL_MOUSE_BUTTON_1) && is_pressed(CELL_MOUSE_BUTTON_3)))
|
||||
digital_buttons |= CELL_GEM_CTRL_START;
|
||||
|
||||
if (is_pressed(CELL_MOUSE_BUTTON_8) || (is_pressed(CELL_MOUSE_BUTTON_2) && is_pressed(CELL_MOUSE_BUTTON_3)))
|
||||
digital_buttons |= CELL_GEM_CTRL_TRIANGLE;
|
||||
|
||||
|
@ -332,7 +333,7 @@ static bool mouse_input_to_pad(const u32 mouse_no, be_t<u16>& digital_buttons, b
|
|||
return true;
|
||||
}
|
||||
|
||||
static bool mouse_pos_to_gem_image_state(const u32 mouse_no, vm::ptr<CellGemImageState>& gem_image_state)
|
||||
static bool mouse_pos_to_gem_image_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state)
|
||||
{
|
||||
auto& handler = g_fxo->get<MouseHandlerBase>();
|
||||
|
||||
|
@ -344,25 +345,40 @@ static bool mouse_pos_to_gem_image_state(const u32 mouse_no, vm::ptr<CellGemImag
|
|||
}
|
||||
|
||||
const auto& mouse = handler.GetMice().at(0);
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
const auto renderer = static_cast<GSRender*>(rsx::get_current_renderer());
|
||||
const auto width = renderer->get_frame()->client_width();
|
||||
const auto height = renderer->get_frame()->client_height();
|
||||
const f32 scaling_width = width / 640.f;
|
||||
const f32 scaling_height = height / 480.f;
|
||||
s32 mouse_width = mouse.x_max;
|
||||
if (mouse_width <= 0) mouse_width = shared_data.width;
|
||||
s32 mouse_height = mouse.y_max;
|
||||
if (mouse_height <= 0) mouse_height = shared_data.height;
|
||||
const f32 scaling_width = mouse_width / static_cast<f32>(shared_data.width);
|
||||
const f32 scaling_height = mouse_height / static_cast<f32>(shared_data.height);
|
||||
const f32 mmPerPixel = controller.diameter_mm / static_cast<f32>(controller.radius * 2);
|
||||
|
||||
const f32 x = static_cast<f32>(mouse.x_pos) / scaling_width;
|
||||
const f32 y = static_cast<f32>(mouse.y_pos) / scaling_height;
|
||||
// Image coordinates in pixels
|
||||
const f32 image_x = static_cast<f32>(mouse.x_pos) / scaling_width;
|
||||
const f32 image_y = static_cast<f32>(mouse.y_pos) / scaling_height;
|
||||
|
||||
gem_image_state->u = 133.f + (x / 1.50f);
|
||||
gem_image_state->v = 160.f + (y / 1.67f);
|
||||
gem_image_state->projectionx = x - 320.f;
|
||||
gem_image_state->projectiony = 240.f - y;
|
||||
// Centered image coordinates in pixels
|
||||
const f32 centered_x = image_x - (shared_data.width / 2.f);
|
||||
const f32 centered_y = (shared_data.height / 2.f) - image_y; // Image coordinates increase downwards, so we have to invert this
|
||||
|
||||
// Camera coordinates in mm (centered, so it's the same as world coordinates)
|
||||
const f32 camera_x = centered_x * mmPerPixel;
|
||||
const f32 camera_y = centered_y * mmPerPixel;
|
||||
|
||||
// Image coordinates in pixels
|
||||
gem_image_state->u = image_x;
|
||||
gem_image_state->v = image_y;
|
||||
|
||||
// Projected camera coordinates in mm
|
||||
gem_image_state->projectionx = camera_x / controller.distance;
|
||||
gem_image_state->projectiony = camera_y / controller.distance;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool mouse_pos_to_gem_state(const u32 mouse_no, vm::ptr<CellGemState>& gem_state)
|
||||
static bool mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
|
||||
{
|
||||
auto& handler = g_fxo->get<MouseHandlerBase>();
|
||||
|
||||
|
@ -374,28 +390,42 @@ static bool mouse_pos_to_gem_state(const u32 mouse_no, vm::ptr<CellGemState>& ge
|
|||
}
|
||||
|
||||
const auto& mouse = handler.GetMice().at(0);
|
||||
const auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
s32 mouse_width = mouse.x_max;
|
||||
if (mouse_width <= 0) mouse_width = shared_data.width;
|
||||
s32 mouse_height = mouse.y_max;
|
||||
if (mouse_height <= 0) mouse_height = shared_data.height;
|
||||
const f32 scaling_width = mouse_width / static_cast<f32>(shared_data.width);
|
||||
const f32 scaling_height = mouse_height / static_cast<f32>(shared_data.height);
|
||||
const f32 mmPerPixel = controller.diameter_mm / static_cast<f32>(controller.radius * 2);
|
||||
|
||||
const auto renderer = static_cast<GSRender*>(rsx::get_current_renderer());
|
||||
const auto width = renderer->get_frame()->client_width();
|
||||
const auto height = renderer->get_frame()->client_height();
|
||||
// Image coordinates in pixels
|
||||
const f32 image_x = static_cast<f32>(mouse.x_pos) / scaling_width;
|
||||
const f32 image_y = static_cast<f32>(mouse.y_pos) / scaling_height;
|
||||
|
||||
const f32 scaling_width = width / 640.f;
|
||||
const f32 scaling_height = height / 480.f;
|
||||
const f32 x = static_cast<f32>(mouse.x_pos) / scaling_width;
|
||||
const f32 y = static_cast<f32>(mouse.y_pos) / scaling_height;
|
||||
// Centered image coordinates in pixels
|
||||
const f32 centered_x = image_x - (shared_data.width / 2.f);
|
||||
const f32 centered_y = (shared_data.height / 2.f) - image_y; // Image coordinates increase downwards, so we have to invert this
|
||||
|
||||
gem_state->pos[0] = x;
|
||||
gem_state->pos[1] = -y;
|
||||
gem_state->pos[2] = 1500.f;
|
||||
// Camera coordinates in mm (centered, so it's the same as world coordinates)
|
||||
const f32 camera_x = centered_x * mmPerPixel;
|
||||
const f32 camera_y = centered_y * mmPerPixel;
|
||||
|
||||
// World coordinates in mm
|
||||
gem_state->pos[0] = camera_x;
|
||||
gem_state->pos[1] = camera_y;
|
||||
gem_state->pos[2] = static_cast<f32>(controller.distance);
|
||||
gem_state->pos[3] = 0.f;
|
||||
|
||||
gem_state->quat[0] = 320.f - x;
|
||||
gem_state->quat[0] = 320.f - image_x;
|
||||
gem_state->quat[1] = (mouse.y_pos / scaling_width) - 180.f;
|
||||
gem_state->quat[2] = 1200.f;
|
||||
|
||||
gem_state->handle_pos[0] = x;
|
||||
gem_state->handle_pos[1] = y;
|
||||
gem_state->handle_pos[2] = 1500.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] = static_cast<f32>(controller.distance + 10);
|
||||
gem_state->handle_pos[3] = 0.f;
|
||||
|
||||
return true;
|
||||
|
@ -749,14 +779,13 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
|
|||
return CELL_GEM_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake || g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
auto& shared_data = g_fxo->get<gem_camera_shared>();
|
||||
gem_image_state->frame_timestamp = shared_data.frame_timestamp.load();
|
||||
gem_image_state->timestamp = gem_image_state->frame_timestamp + 10;
|
||||
gem_image_state->r = 10;
|
||||
gem_image_state->distance = 2 * 1000; // 2 meters away from camera
|
||||
gem_image_state->r = gem.controllers[gem_num].radius; // Radius in camera pixels
|
||||
gem_image_state->distance = gem.controllers[gem_num].distance; // 1.5 meters away from camera
|
||||
gem_image_state->visible = gem.is_controller_ready(gem_num);
|
||||
gem_image_state->r_valid = true;
|
||||
|
||||
|
@ -769,7 +798,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
|
|||
}
|
||||
else if (g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
mouse_pos_to_gem_image_state(gem_num, gem_image_state);
|
||||
mouse_pos_to_gem_image_state(gem_num, gem.controllers[gem_num], gem_image_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -800,7 +829,7 @@ error_code cellGemGetInertialState(u32 gem_num, u32 state_flag, u64 timestamp, v
|
|||
|
||||
inertial_state->timestamp = (get_guest_system_time() - gem.start_timestamp);
|
||||
inertial_state->counter = gem.inertial_counter++;
|
||||
inertial_state->accelerometer[0] = 10;
|
||||
inertial_state->accelerometer[0] = 10; // Current gravity in m/s²
|
||||
|
||||
if (g_cfg.io.move == move_handler::fake)
|
||||
{
|
||||
|
@ -958,6 +987,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
|
|||
if (gem.controllers[gem_num].enabled_tracking)
|
||||
tracking_flags |= CELL_GEM_TRACKING_FLAG_POSITION_TRACKED;
|
||||
|
||||
*gem_state = {};
|
||||
gem_state->tracking_flags = tracking_flags;
|
||||
gem_state->timestamp = (get_guest_system_time() - gem.start_timestamp);
|
||||
gem_state->camera_pitch_angle = 0.f;
|
||||
|
@ -970,7 +1000,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
|
|||
else if (g_cfg.io.move == move_handler::mouse)
|
||||
{
|
||||
mouse_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
|
||||
mouse_pos_to_gem_state(gem_num, gem_state);
|
||||
mouse_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_state);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -115,6 +115,8 @@ struct Mouse
|
|||
{
|
||||
s32 x_pos;
|
||||
s32 y_pos;
|
||||
s32 x_max;
|
||||
s32 y_max;
|
||||
u8 buttons; // actual mouse button positions
|
||||
|
||||
MouseTabletDataList m_tablet_datalist;
|
||||
|
@ -124,6 +126,8 @@ struct Mouse
|
|||
Mouse()
|
||||
: x_pos(0)
|
||||
, y_pos(0)
|
||||
, x_max(0)
|
||||
, y_max(0)
|
||||
, buttons(0)
|
||||
{
|
||||
}
|
||||
|
@ -213,7 +217,7 @@ public:
|
|||
}
|
||||
}
|
||||
|
||||
void Move(const s32 x_pos_new, const s32 y_pos_new, const bool is_qt_fullscreen = false, s32 x_delta = 0, s32 y_delta = 0)
|
||||
void Move(s32 x_pos_new, s32 y_pos_new, s32 x_max, s32 y_max, const bool is_qt_fullscreen = false, s32 x_delta = 0, s32 y_delta = 0)
|
||||
{
|
||||
std::lock_guard lock(mutex);
|
||||
|
||||
|
@ -244,6 +248,8 @@ public:
|
|||
new_data.x_axis = static_cast<s8>(std::clamp(x_delta, -127, 128));
|
||||
new_data.y_axis = static_cast<s8>(std::clamp(y_delta, -127, 128));
|
||||
|
||||
m_mice[p].x_max = x_max;
|
||||
m_mice[p].y_max = y_max;
|
||||
m_mice[p].x_pos = x_pos_new;
|
||||
m_mice[p].y_pos = y_pos_new;
|
||||
|
||||
|
|
|
@ -122,11 +122,11 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
|
|||
{
|
||||
if (is_time_for_update())
|
||||
{
|
||||
// get the screen dimensions
|
||||
const QSize screen = m_target->size();
|
||||
|
||||
if (m_target && m_target->isActive() && get_mouse_lock_state())
|
||||
{
|
||||
// get the screen dimensions
|
||||
const QSize screen = m_target->size();
|
||||
|
||||
// get the center of the screen in global coordinates
|
||||
QPoint p_center = m_target->geometry().topLeft() + QPoint(screen.width() / 2, screen.height() / 2);
|
||||
|
||||
|
@ -147,11 +147,11 @@ void basic_mouse_handler::MouseMove(QMouseEvent* event)
|
|||
p_real.setY(std::clamp(p_real.y() + p_delta.y(), 0, screen.height()));
|
||||
|
||||
// pass the 'real' position and the current delta to the screen center
|
||||
MouseHandlerBase::Move(p_real.x(), p_real.y(), true, p_delta.x(), p_delta.y());
|
||||
MouseHandlerBase::Move(p_real.x(), p_real.y(), screen.width(), screen.height(), true, p_delta.x(), p_delta.y());
|
||||
}
|
||||
else
|
||||
{
|
||||
MouseHandlerBase::Move(event->x(), event->y());
|
||||
MouseHandlerBase::Move(event->x(), event->y(), screen.width(), screen.height());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue