Extract dialog, VR, and canvas draw helpers
This commit is contained in:
141
src/platform_windows/windows_vr_shell.h
Normal file
141
src/platform_windows/windows_vr_shell.h
Normal file
@@ -0,0 +1,141 @@
|
||||
#pragma once
|
||||
|
||||
#include "app.h"
|
||||
#include "hmd.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <mutex>
|
||||
#include <thread>
|
||||
|
||||
namespace pp::platform::windows {
|
||||
|
||||
struct VrShellState final {
|
||||
std::jthread hmd_renderer;
|
||||
std::mutex hmd_render_mutex;
|
||||
std::condition_variable hmd_render_cv;
|
||||
std::unique_ptr<Vive> vive;
|
||||
std::atomic<int> vr_frames{0};
|
||||
std::atomic_bool vr_running{false};
|
||||
};
|
||||
|
||||
inline int current_vr_fps(const VrShellState& state)
|
||||
{
|
||||
return state.vr_frames.load(std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
inline void request_stop_and_join_vr_thread(VrShellState& state)
|
||||
{
|
||||
if (state.hmd_renderer.joinable())
|
||||
{
|
||||
state.hmd_renderer.request_stop();
|
||||
state.hmd_renderer.join();
|
||||
}
|
||||
}
|
||||
|
||||
inline bool start_vr_shell(VrShellState& state, bool sandboxed, std::atomic<int>& running)
|
||||
{
|
||||
if (sandboxed)
|
||||
return false;
|
||||
|
||||
state.vive = std::make_unique<Vive>();
|
||||
state.vive->on_draw = [](const glm::mat4& proj, const glm::mat4& view, const glm::mat4& pose) {
|
||||
App::I->vr_draw(proj, view, pose);
|
||||
};
|
||||
if (!state.vive->Initialize())
|
||||
{
|
||||
state.vive.reset();
|
||||
LOG("VR: failed to initialize vive");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (state.hmd_renderer.joinable())
|
||||
{
|
||||
state.hmd_renderer.request_stop();
|
||||
state.hmd_renderer.join();
|
||||
}
|
||||
|
||||
state.hmd_renderer = std::jthread([&state, &running](std::stop_token stop_token) {
|
||||
if (!state.vive)
|
||||
return;
|
||||
|
||||
BT_SetTerminate();
|
||||
LOG("start hmd render thread");
|
||||
App::I->has_vr = true;
|
||||
state.vr_running.store(true, std::memory_order_relaxed);
|
||||
|
||||
state.vive->on_analog_button = std::bind(&App::vr_analog, App::I, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
||||
state.vive->on_button = std::bind(&App::vr_digital, App::I, std::placeholders::_1,
|
||||
std::placeholders::_2, std::placeholders::_3, std::placeholders::_4);
|
||||
|
||||
App::I->render_task([] {
|
||||
App::I->vr_draw_ui();
|
||||
});
|
||||
|
||||
const float target_tick_rate = 90;
|
||||
auto t0 = GetTickCount64();
|
||||
float one_sec_timer = 0;
|
||||
int frames = 0;
|
||||
while (!stop_token.stop_requested() &&
|
||||
state.vr_running.load(std::memory_order_relaxed) &&
|
||||
running.load(std::memory_order_relaxed) == 1 &&
|
||||
state.vive->Valid())
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(state.hmd_render_mutex);
|
||||
auto t1 = GetTickCount64();
|
||||
float dt = (float)(t1 - t0) / 1000.0f;
|
||||
|
||||
one_sec_timer += dt;
|
||||
if (one_sec_timer >= 1.f)
|
||||
{
|
||||
one_sec_timer = 0;
|
||||
state.vr_frames.store(frames, std::memory_order_relaxed);
|
||||
frames = 0;
|
||||
}
|
||||
frames++;
|
||||
|
||||
state.vive->Update();
|
||||
App::I->vr_active = state.vive->m_active;
|
||||
App::I->vr_controllers[0] = state.vive->m_controllers[0];
|
||||
App::I->vr_head = state.vive->m_pose;
|
||||
App::I->vr_update(dt);
|
||||
|
||||
if (state.vr_running.load(std::memory_order_relaxed) && state.vive->m_active)
|
||||
{
|
||||
App::I->render_task([&state] {
|
||||
state.vive->Draw();
|
||||
});
|
||||
}
|
||||
|
||||
const int framerate = (1.f / target_tick_rate) * 1000;
|
||||
const int diff = framerate - (t1 - t0);
|
||||
(void)diff;
|
||||
//state.hmd_render_cv.wait_for(lock, std::chrono::milliseconds(diff));
|
||||
t0 = t1;
|
||||
}
|
||||
|
||||
App::I->vr_active = false;
|
||||
App::I->has_vr = false;
|
||||
state.vr_running.store(false, std::memory_order_relaxed);
|
||||
state.vive->Terminate();
|
||||
LOG("hmd renderer terminated");
|
||||
});
|
||||
return true;
|
||||
}
|
||||
|
||||
inline void stop_vr_shell(VrShellState& state)
|
||||
{
|
||||
if (state.vive)
|
||||
{
|
||||
state.vr_running.store(false, std::memory_order_relaxed);
|
||||
request_stop_and_join_vr_thread(state);
|
||||
state.vive->Terminate();
|
||||
state.vive.reset();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user