1
0
mirror of https://github.com/RPCS3/rpcs3.git synced 2024-11-26 04:32:35 +01:00

cellGem: implement basic ds3 cursor movement

This commit is contained in:
Megamouse 2022-07-06 19:32:19 +02:00
parent 639b8112b6
commit 3840015e7d

View File

@ -420,6 +420,78 @@ static bool check_gem_num(const u32 gem_num)
return gem_num < CELL_GEM_MAX_NUM;
}
static inline void pos_to_gem_image_state(const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
{
const auto& shared_data = g_fxo->get<gem_camera_shared>();
if (x_max <= 0) x_max = shared_data.width;
if (y_max <= 0) y_max = shared_data.height;
const f32 scaling_width = x_max / static_cast<f32>(shared_data.width);
const f32 scaling_height = y_max / static_cast<f32>(shared_data.height);
const f32 mmPerPixel = CELL_GEM_SPHERE_RADIUS_MM / controller.radius;
// Image coordinates in pixels
const f32 image_x = static_cast<f32>(x_pos) / scaling_width;
const f32 image_y = static_cast<f32>(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
// 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;
}
static inline void pos_to_gem_state(const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state, s32 x_pos, s32 y_pos, s32 x_max, s32 y_max)
{
const auto& shared_data = g_fxo->get<gem_camera_shared>();
if (x_max <= 0) x_max = shared_data.width;
if (y_max <= 0) y_max = shared_data.height;
const f32 scaling_width = x_max / static_cast<f32>(shared_data.width);
const f32 scaling_height = y_max / static_cast<f32>(shared_data.height);
const f32 mmPerPixel = CELL_GEM_SPHERE_RADIUS_MM / controller.radius;
// Image coordinates in pixels
const f32 image_x = static_cast<f32>(x_pos) / scaling_width;
const f32 image_y = static_cast<f32>(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
// 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 - 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] = static_cast<f32>(controller.distance + 10);
gem_state->handle_pos[3] = 0.f;
}
extern bool is_input_allowed();
/**
@ -502,6 +574,76 @@ static void ds3_input_to_pad(const u32 port_no, be_t<u16>& digital_buttons, be_t
}
}
constexpr u16 ds3_max_x = 255;
constexpr u16 ds3_max_y = 255;
static inline void ds3_get_stick_values(const std::shared_ptr<Pad>& pad, s32& x_pos, s32& y_pos)
{
x_pos = 0;
y_pos = 0;
for (const AnalogStick& stick : pad->m_sticks)
{
switch (stick.m_offset)
{
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_X:
x_pos = stick.m_value - 128;
break;
case CELL_PAD_BTN_OFFSET_ANALOG_LEFT_Y:
y_pos = stick.m_value - 128;
break;
default:
break;
}
}
}
static void ds3_pos_to_gem_image_state(const u32 port_no, const gem_config::gem_controller& controller, vm::ptr<CellGemImageState>& gem_image_state)
{
if (!is_input_allowed())
{
return;
}
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const auto& pad = handler->GetPads().at(port_no);
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
{
return;
}
s32 ds3_pos_x, ds3_pos_y;
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
pos_to_gem_image_state(controller, gem_image_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
}
static void ds3_pos_to_gem_state(const u32 port_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
{
if (!is_input_allowed())
{
return;
}
std::lock_guard lock(pad::g_pad_mutex);
const auto handler = pad::get_current_handler();
const auto& pad = handler->GetPads().at(port_no);
if (!(pad->m_port_status & CELL_PAD_STATUS_CONNECTED))
{
return;
}
s32 ds3_pos_x, ds3_pos_y;
ds3_get_stick_values(pad, ds3_pos_x, ds3_pos_y);
pos_to_gem_state(controller, gem_state, ds3_pos_x, ds3_pos_y, ds3_max_x, ds3_max_y);
}
/**
* \brief Maps external Move controller data to DS3 input. (This can be input from any physical pad, not just the DS3)
* Implementation detail: CellGemExtPortData's digital/analog fields map the same way as
@ -633,35 +775,8 @@ static void mouse_pos_to_gem_image_state(const u32 mouse_no, const gem_config::g
}
const auto& mouse = handler.GetMice().at(mouse_no);
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 = CELL_GEM_SPHERE_RADIUS_MM / controller.radius;
// 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;
// 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;
pos_to_gem_image_state(controller, gem_image_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
}
static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_controller& controller, vm::ptr<CellGemState>& gem_state)
@ -684,43 +799,8 @@ static void mouse_pos_to_gem_state(const u32 mouse_no, const gem_config::gem_con
}
const auto& mouse = handler.GetMice().at(mouse_no);
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 = CELL_GEM_SPHERE_RADIUS_MM / controller.radius;
// 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;
// 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;
// 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 - image_x;
gem_state->quat[1] = (mouse.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] = static_cast<f32>(controller.distance + 10);
gem_state->handle_pos[3] = 0.f;
pos_to_gem_state(controller, gem_state, mouse.x_pos, mouse.y_pos, mouse.x_max, mouse.y_max);
}
// *********************
@ -1116,10 +1196,7 @@ error_code cellGemGetImageState(u32 gem_num, vm::ptr<CellGemImageState> gem_imag
if (g_cfg.io.move == move_handler::fake)
{
gem_image_state->u = 0;
gem_image_state->v = 0;
gem_image_state->projectionx = 1;
gem_image_state->projectiony = 1;
ds3_pos_to_gem_image_state(gem_num, gem.controllers[gem_num], gem_image_state);
}
else if (g_cfg.io.move == move_handler::mouse)
{
@ -1334,6 +1411,7 @@ error_code cellGemGetState(u32 gem_num, u32 flag, u64 time_parameter, vm::ptr<Ce
if (g_cfg.io.move == move_handler::fake)
{
ds3_input_to_pad(gem_num, gem_state->pad.digitalbuttons, gem_state->pad.analog_T);
ds3_pos_to_gem_state(gem_num, gem.controllers[gem_num], gem_state);
}
else if (g_cfg.io.move == move_handler::mouse)
{