spicetools/overlay/windows/vr.cpp

219 lines
8.4 KiB
C++

#include "vr.h"
#include "misc/vrutil.h"
#include "util/logging.h"
#include "games/io.h"
#include "games/drs/drs.h"
#include "avs/game.h"
#include "overlay/imgui/extensions.h"
namespace overlay::windows {
VRWindow::VRWindow(SpiceOverlay *overlay) : Window(overlay) {
this->title = "VR";
this->flags = ImGuiWindowFlags_None;
this->toggle_button = games::OverlayButtons::ToggleVRControl;
this->init_size = ImVec2(500, 800);
this->size_min = ImVec2(250, 200);
}
VRWindow::~VRWindow() {
}
void VRWindow::build_content() {
ImGui::BeginTabBar("VRTabBar");
if (ImGui::BeginTabItem("Info")) {
build_info();
ImGui::EndTabItem();
}
if (avs::game::is_model("REC")) {
if (ImGui::BeginTabItem("Dancefloor")) {
build_dancefloor();
}
}
}
void VRWindow::build_info() {
// status
auto status = vrutil::STATUS;
switch (status) {
case vrutil::VRStatus::Disabled:
ImGui::TextColored(
ImVec4(0.4f, 0.4f, 0.4f, 1.f),
"Disabled");
if (ImGui::Button("Start")) {
vrutil::init();
if (avs::game::is_model("REC")) {
games::drs::start_vr();
}
}
break;
case vrutil::VRStatus::Error:
ImGui::TextColored(
ImVec4(0.8f, 0.1f, 0.1f, 1.f),
"Error");
if (ImGui::Button("Restart")) {
vrutil::shutdown();
vrutil::init();
}
break;
case vrutil::VRStatus::Running:
ImGui::TextColored(
ImVec4(0.1f, 0.8f, 0.1f, 1.f),
"Running");
if (ImGui::Button("Stop")) {
vrutil::shutdown();
}
break;
}
// rescan
if (ImGui::Button("Rescan Devices")) {
vrutil::scan(true);
}
// data table header
ImGui::Columns(2);
ImGui::Text("Device");
ImGui::NextColumn();
ImGui::Text("Position");
ImGui::NextColumn();
ImGui::Separator();
// HMD/Left/Right data
vr::TrackedDevicePose_t hmd_pose, left_pose, right_pose;
vr::VRControllerState_t left_state, right_state;
vrutil::get_hmd_pose(&hmd_pose);
vrutil::get_con_pose(vrutil::INDEX_LEFT, &left_pose, &left_state);
vrutil::get_con_pose(vrutil::INDEX_RIGHT, &right_pose, &right_state);
auto hmd_pos = vrutil::get_translation(hmd_pose.mDeviceToAbsoluteTracking);
auto left_pos = vrutil::get_translation(left_pose.mDeviceToAbsoluteTracking);
auto right_pos = vrutil::get_translation(right_pose.mDeviceToAbsoluteTracking);
ImGui::Text("HMD");
ImGui::NextColumn();
ImGui::TextUnformatted(fmt::format(
"X={:3f} Y={:3f} Z={:3f}",
hmd_pos.x, hmd_pos.y, hmd_pos.z).c_str());
ImGui::NextColumn();
ImGui::Text("Left");
ImGui::NextColumn();
ImGui::TextUnformatted(fmt::format(
"X={:3f} Y={:3f} Z={:3f}",
left_pos.x, left_pos.y, left_pos.z).c_str());
ImGui::NextColumn();
ImGui::Text("Right");
ImGui::NextColumn();
ImGui::TextUnformatted(fmt::format(
"X={:3f} Y={:3f} Z={:3f}",
right_pos.x, right_pos.y, right_pos.z).c_str());
ImGui::NextColumn();
}
void VRWindow::build_dancefloor() {
ImGui::Separator();
// settings
ImGui::DragFloat3("Scale", &games::drs::VR_SCALE[0], 0.1f);
ImGui::DragFloat3("Offset", &games::drs::VR_OFFSET[0], 0.1f);
ImGui::DragFloat("Rotation", &games::drs::VR_ROTATION, 0.5f);
for (int i = 0; i < (int) std::size(games::drs::VR_FOOTS); ++i) {
auto &foot = games::drs::VR_FOOTS[i];
ImGui::Separator();
ImGui::PushID(&foot);
ImGui::Text("%s Foot", i == 0 ? "Left" : "Right");
ImGui::InputInt("Device Index", (int*) &foot.index, 1, 1);
ImGui::DragFloat("Length", &foot.length,
0.005f, 0.001f, 1000.f);
ImGui::DragFloat("Size Base", &foot.size_base,
0.005f, 0.001f, 1000.f);
ImGui::DragFloat("Size Scale", &foot.size_scale,
0.005f, 0.001f, 1000.f);
ImGui::DragFloat4("Rotation Quat", &foot.rotation.x, 0.001f, -1, 1);
if (ImGui::Button("Calibrate")) {
vr::TrackedDevicePose_t pose;
vr::VRControllerState_t state;
vrutil::get_con_pose(foot.get_index(), &pose, &state);
foot.length = foot.height + 0.02f;
auto pose_rot = vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m);
foot.rotation = linalg::qmul(linalg::qinv(pose_rot),
vrutil::get_rotation((float) M_PI * -0.5f, 0, 0));
}
ImGui::SameLine();
ImGui::HelpMarker("Place the controller to the lower part of your leg "
"and press this button to auto calibrate angle and length");
ImGui::PopID();
}
// prepare view
auto draw_list = ImGui::GetWindowDrawList();
auto canvas_pos = ImGui::GetCursorScreenPos();
auto canvas_size = ImGui::GetContentRegionAvail();
float offset_x = canvas_size.x * 0.5f;
float offset_y = canvas_size.y * 0.1f;
float off_x = offset_x + canvas_pos.x;
float off_y = offset_y + canvas_pos.y;
float scale = std::min(canvas_size.x, canvas_size.y) / 60;
// axis
draw_list->AddLine(
ImVec2(canvas_pos.x, off_y),
ImVec2(canvas_pos.x + canvas_size.x, off_y),
ImColor(255, 0, 0, 128));
draw_list->AddLine(
ImVec2(off_x, canvas_pos.y),
ImVec2(off_x, canvas_pos.y + canvas_size.y),
ImColor(0, 255, 0, 128));
// tiles
for (int x = 0; x < 38; x++) {
for (int y = 0; y < 49; y++) {
auto &led = games::drs::DRS_TAPELED[x + y * 38];
ImColor color((int) led[0], (int) led[1], (int) led[2]);
ImVec2 p1((x - 19) * scale + off_x, (y + 0) * scale + off_y);
ImVec2 p2((x - 18) * scale + off_x, (y + 1) * scale + off_y);
draw_list->AddRectFilled(p1, p2, color, 0.f);
}
}
// foots
const float foot_box = 2.f * scale;
for (auto &foot : games::drs::VR_FOOTS) {
vr::TrackedDevicePose_t pose;
vr::VRControllerState_t state;
vrutil::get_con_pose(foot.get_index(), &pose, &state);
if (pose.bPoseIsValid) {
// position
auto pos = vrutil::get_translation(pose.mDeviceToAbsoluteTracking);
pos = foot.to_world(pos);
pos.x -= 19;
pos *= scale;
ImColor color(255, 0, 255);
if (foot.event.type == games::drs::DRS_DOWN
|| (foot.event.type == games::drs::DRS_MOVE)) {
auto size_factor = foot.event.width / (foot.size_base + foot.size_scale);
color = ImColor((int) (size_factor * 127) + 128, 0, 0);
}
ImVec2 p1(pos.x + off_x - foot_box * 0.5f,
pos.y + off_y - foot_box * 0.5f);
ImVec2 p2(pos.x + off_x + foot_box * 0.5f,
pos.y + off_y + foot_box * 0.5f);
draw_list->AddRectFilled(p1, p2, color, 0.f);
// direction
auto direction = -linalg::qzdir(linalg::qmul(
vrutil::get_rotation(pose.mDeviceToAbsoluteTracking.m),
foot.rotation));
direction = linalg::aliases::float3 {
-direction.z, direction.x, direction.y
};
auto end = pos + direction * foot.length * scale;
draw_list->AddLine(
ImVec2(pos.x + off_x, pos.y + off_y),
ImVec2(end.x + off_x, end.y + off_y),
ImColor(0, 255, 0));
}
}
}
}