Skip to content

Commit

Permalink
Add chaperone bounds tool, fix rendering when launched minimized
Browse files Browse the repository at this point in the history
  • Loading branch information
pushrax committed Mar 3, 2019
1 parent dda68d4 commit 85c6b3c
Show file tree
Hide file tree
Showing 6 changed files with 168 additions and 8 deletions.
36 changes: 36 additions & 0 deletions OpenVR-SpaceCalibrator/Calibration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -332,6 +332,19 @@ void ScanAndApplyProfile(CalibrationContext &ctx)
};
Driver.SendBlocking(req);
}

if (ctx.chaperone.valid && ctx.chaperone.autoApply)
{
uint32_t quadCount = 0;
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &quadCount);

// Heuristic: when SteamVR resets to a blank-ish chaperone, it uses empty geometry,
// but manual adjustments (e.g. via a play space mover) will not touch geometry.
if (quadCount != ctx.chaperone.geometry.size())
{
ApplyChaperoneBounds();
}
}
}

void StartCalibration()
Expand Down Expand Up @@ -461,3 +474,26 @@ void CalibrationTick(double time)
samples.clear();
}
}

void LoadChaperoneBounds()
{
vr::VRChaperoneSetup()->RevertWorkingCopy();

uint32_t quadCount = 0;
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(nullptr, &quadCount);

CalCtx.chaperone.geometry.resize(quadCount);
vr::VRChaperoneSetup()->GetLiveCollisionBoundsInfo(&CalCtx.chaperone.geometry[0], &quadCount);
vr::VRChaperoneSetup()->GetWorkingStandingZeroPoseToRawTrackingPose(&CalCtx.chaperone.standingCenter);
vr::VRChaperoneSetup()->GetWorkingPlayAreaSize(&CalCtx.chaperone.playSpaceSize.v[0], &CalCtx.chaperone.playSpaceSize.v[1]);
CalCtx.chaperone.valid = true;
}

void ApplyChaperoneBounds()
{
vr::VRChaperoneSetup()->RevertWorkingCopy();
vr::VRChaperoneSetup()->SetWorkingCollisionBoundsInfo(&CalCtx.chaperone.geometry[0], CalCtx.chaperone.geometry.size());
vr::VRChaperoneSetup()->SetWorkingStandingZeroPoseToRawTrackingPose(&CalCtx.chaperone.standingCenter);
vr::VRChaperoneSetup()->SetWorkingPlayAreaSize(CalCtx.chaperone.playSpaceSize.v[0], CalCtx.chaperone.playSpaceSize.v[1]);
vr::VRChaperoneSetup()->CommitWorkingCopy(vr::EChaperoneConfigFile_Live);
}
14 changes: 13 additions & 1 deletion OpenVR-SpaceCalibrator/Calibration.h
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <Eigen/Core>
#include <openvr.h>
#include <vector>

enum class CalibrationState
{
Expand Down Expand Up @@ -29,6 +30,15 @@ struct CalibrationContext

vr::TrackedDevicePose_t devicePoses[vr::k_unMaxTrackedDeviceCount];

struct Chaperone
{
bool valid = false;
bool autoApply = false;
std::vector<vr::HmdQuad_t> geometry;
vr::HmdMatrix34_t standingCenter;
vr::HmdVector2_t playSpaceSize;
} chaperone;

std::string messages;

void Message(const std::string &msg)
Expand All @@ -42,4 +52,6 @@ extern CalibrationContext CalCtx;

void InitCalibrator();
void CalibrationTick(double time);
void StartCalibration();
void StartCalibration();
void LoadChaperoneBounds();
void ApplyChaperoneBounds();
69 changes: 69 additions & 0 deletions OpenVR-SpaceCalibrator/Configuration.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,29 @@ static std::string ConfigFileName()
return vrRuntimeConfigName + "\\..\\..\\..\\config\\01spacecalibrator\\calibration.json";
}

picojson::array FloatArray(const float *buf, int numFloats)
{
picojson::array arr;

for (int i = 0; i < numFloats; i++)
arr.push_back(picojson::value(double(buf[i])));

return arr;
}

void LoadFloatArray(const picojson::value &obj, float *buf, int numFloats)
{
if (!obj.is<picojson::array>())
throw std::runtime_error("expected array, got " + obj.to_str());

auto &arr = obj.get<picojson::array>();
if (arr.size() != numFloats)
throw std::runtime_error("wrong buffer size");

for (int i = 0; i < numFloats; i++)
buf[i] = (float) arr[i].get<double>();
}

void LoadProfile(CalibrationContext &ctx)
{
ctx.validProfile = false;
Expand Down Expand Up @@ -71,6 +94,33 @@ static void ParseProfileV2(CalibrationContext &ctx, std::istream &stream)
ctx.calibratedTranslation(1) = obj["y"].get<double>();
ctx.calibratedTranslation(2) = obj["z"].get<double>();

if (obj["chaperone"].is<picojson::object>())
{
auto chaperone = obj["chaperone"].get<picojson::object>();
ctx.chaperone.autoApply = chaperone["auto_apply"].get<bool>();

LoadFloatArray(chaperone["play_space_size"], ctx.chaperone.playSpaceSize.v, 2);

LoadFloatArray(
chaperone["standing_center"],
(float *) ctx.chaperone.standingCenter.m,
sizeof(ctx.chaperone.standingCenter) / sizeof(float)
);

if (!chaperone["geometry"].is<picojson::array>())
throw std::runtime_error("chaperone geometry is not an array");

auto &geometry = chaperone["geometry"].get<picojson::array>();

if (geometry.size() > 0)
{
ctx.chaperone.geometry.resize(geometry.size() * sizeof(float) / sizeof(ctx.chaperone.geometry[0]));
LoadFloatArray(chaperone["geometry"], (float *) ctx.chaperone.geometry.data(), geometry.size());

ctx.chaperone.valid = true;
}
}

ctx.validProfile = true;
}

Expand All @@ -90,6 +140,25 @@ void SaveProfile(CalibrationContext &ctx)
profile["y"].set<double>(ctx.calibratedTranslation(1));
profile["z"].set<double>(ctx.calibratedTranslation(2));

if (ctx.chaperone.valid)
{
picojson::object chaperone;
chaperone["auto_apply"].set<bool>(ctx.chaperone.autoApply);
chaperone["play_space_size"].set<picojson::array>(FloatArray(ctx.chaperone.playSpaceSize.v, 2));

chaperone["standing_center"].set<picojson::array>(
FloatArray((float *) ctx.chaperone.standingCenter.m,
sizeof(ctx.chaperone.standingCenter) / sizeof(float)
));

chaperone["geometry"].set<picojson::array>(
FloatArray((float *) ctx.chaperone.geometry.data(),
sizeof(ctx.chaperone.geometry[0]) / sizeof(float) * ctx.chaperone.geometry.size()
));

profile["chaperone"].set<picojson::object>(chaperone);
}

picojson::value profileV;
profileV.set<picojson::object>(profile);

Expand Down
26 changes: 19 additions & 7 deletions OpenVR-SpaceCalibrator/OpenVR-SpaceCalibrator.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,8 @@ void RunLoop()
}
}

ImGui::GetIO().DisplaySize = ImVec2((float) fboTextureWidth, (float) fboTextureHeight);

ImGui_ImplGlfw_SetReadMouseFromGlfw(!dashboardVisible);
ImGui_ImplOpenGL3_NewFrame();
ImGui_ImplGlfw_NewFrame();
Expand All @@ -241,16 +243,20 @@ void RunLoop()
ImGui::Render();

glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
glViewport(0, 0, width, height);
glViewport(0, 0, fboTextureWidth, fboTextureHeight);
glClearColor(0, 0, 0, 1);
glClear(GL_COLOR_BUFFER_BIT);

ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());

glBindFramebuffer(GL_FRAMEBUFFER, 0);
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboHandle);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glfwSwapBuffers(glfwWindow);

if (width && height)
{
glBindFramebuffer(GL_READ_FRAMEBUFFER, fboHandle);
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
glfwSwapBuffers(glfwWindow);
}

if (dashboardVisible)
{
Expand All @@ -264,21 +270,27 @@ void RunLoop()
#endif
fboTextureHandle;

vr::HmdVector2_t mouseScale = { (float) width, (float) height };
vr::HmdVector2_t mouseScale = { (float) fboTextureWidth, (float) fboTextureHeight };

vr::VROverlay()->SetOverlayTexture(overlayMainHandle, &vrTex);
vr::VROverlay()->SetOverlayMouseScale(overlayMainHandle, &mouseScale);
}

glfwWaitEventsTimeout(dashboardVisible ? 0.0 : CalCtx.wantedUpdateInterval);
const double dashboardInterval = 1.0 / 90.0; // fps
double waitEventsTimeout = CalCtx.wantedUpdateInterval;

if (dashboardVisible && waitEventsTimeout > dashboardInterval)
waitEventsTimeout = dashboardInterval;

glfwWaitEventsTimeout(waitEventsTimeout);
}
}

int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
{
_getcwd(cwd, MAX_PATH);
//CreateConsole();
HandleCommandLine(lpCmdLine);
//CreateConsole();

if (!glfwInit())
{
Expand Down
29 changes: 29 additions & 0 deletions OpenVR-SpaceCalibrator/UserInterface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -91,6 +91,35 @@ void BuildMainWindow(bool runningInOverlay)
CalCtx.validProfile = false;
}
}

width = ImGui::GetWindowContentRegionWidth();
scale = 1.0f;
if (CalCtx.chaperone.valid)
{
width -= style.FramePadding.x * 2.0f;
scale = 0.5;
}

ImGui::Text("");
if (ImGui::Button("Copy Chaperone Bounds to profile", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
{
LoadChaperoneBounds();
SaveProfile(CalCtx);
}

if (CalCtx.chaperone.valid)
{
ImGui::SameLine();
if (ImGui::Button("Paste Chaperone Bounds", ImVec2(width * scale, ImGui::GetTextLineHeight() * 2)))
{
ApplyChaperoneBounds();
}

if (ImGui::Checkbox(" Paste Chaperone Bounds automatically when geometry resets", &CalCtx.chaperone.autoApply))
{
SaveProfile(CalCtx);
}
}
}
else if (CalCtx.state == CalibrationState::Editing)
{
Expand Down
2 changes: 2 additions & 0 deletions lib/imgui/imgui_impl_glfw.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,13 +247,15 @@ void ImGui_ImplGlfw_NewFrame()
ImGuiIO& io = ImGui::GetIO();
IM_ASSERT(io.Fonts->IsBuilt()); // Font atlas needs to be built, call renderer _NewFrame() function e.g. ImGui_ImplOpenGL3_NewFrame()

#if false // Rendering to our own framebuffer
// Setup display size
int w, h;
int display_w, display_h;
glfwGetWindowSize(g_Window, &w, &h);
glfwGetFramebufferSize(g_Window, &display_w, &display_h);
io.DisplaySize = ImVec2((float)w, (float)h);
io.DisplayFramebufferScale = ImVec2(w > 0 ? ((float)display_w / w) : 0, h > 0 ? ((float)display_h / h) : 0);
#endif

// Setup time step
double current_time = glfwGetTime();
Expand Down

0 comments on commit 85c6b3c

Please sign in to comment.