mirror of
https://github.com/hyblocker/OpenVR-SpaceCalibrator.git
synced 2026-10-26 16:01:09 +01:00
(chore): Abstract away window creation
This commit is contained in:
1 parent
0f01a0d1f9
commit
49602cedde
5 files changed
+232
-180
No files matched your search
+12
-180
@@ -2,199 +2,31 @@
|
||||
#include <windows.h>
|
||||
#include "util.h"
|
||||
#include "log.h"
|
||||
|
||||
#include <glad/glad.h>
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include <imgui/backends/imgui_impl_glfw.h>
|
||||
#include <imgui/backends/imgui_impl_opengl3.h>
|
||||
|
||||
static GLFWwindow* glfwWindow = nullptr;
|
||||
static GLuint fboHandle = 0, fboTextureHandle = 0;
|
||||
static int fboTextureWidth = 0, fboTextureHeight = 0;
|
||||
|
||||
const float MINIMIZED_MAX_FPS = 60.0f;
|
||||
#include "window.h"
|
||||
|
||||
extern "C" __declspec(dllexport) DWORD NvOptimusEnablement = 0x00000001;
|
||||
extern "C" __declspec(dllexport) DWORD AmdPowerXpressRequestHighPerformance = 0x00000001;
|
||||
|
||||
void CreateGLFWWindow()
|
||||
{
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||
|
||||
#ifdef DEBUG_LOGS
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||
#endif
|
||||
|
||||
fboTextureWidth = 1200;
|
||||
fboTextureHeight = 800;
|
||||
|
||||
glfwWindow = glfwCreateWindow(fboTextureWidth, fboTextureHeight, "Space Calibrator", nullptr, nullptr);
|
||||
if (!glfwWindow)
|
||||
throw std::runtime_error("Failed to create window");
|
||||
|
||||
glfwMakeContextCurrent(glfwWindow);
|
||||
glfwSwapInterval(1);
|
||||
gladLoadGL();
|
||||
|
||||
// Minimise the window
|
||||
glfwIconifyWindow(glfwWindow);
|
||||
HWND windowHwmd = glfwGetWin32Window(glfwWindow);
|
||||
// EnableDarkModeTopBar(windowHwmd);
|
||||
|
||||
// Load icon and set it in the window
|
||||
// GLFWimage images[1] = {};
|
||||
// std::string iconPath = cwd;
|
||||
// iconPath += "\\taskbar_icon.png";
|
||||
// images[0].pixels = stbi_load(iconPath.c_str(), &images[0].width, &images[0].height, 0, 4);
|
||||
// glfwSetWindowIcon(glfwWindow, 1, images);
|
||||
// stbi_image_free(images[0].pixels);
|
||||
|
||||
#ifdef DEBUG_LOGS
|
||||
glDebugMessageCallback(openGLDebugCallback, nullptr);
|
||||
glEnable(GL_DEBUG_OUTPUT);
|
||||
#endif
|
||||
|
||||
ImGui::CreateContext();
|
||||
// ImPlot::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
io.IniFilename = nullptr;
|
||||
// io.Fonts->AddFontFromMemoryCompressedTTF(DroidSans_compressed_data, DroidSans_compressed_size, 24.0f);
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(glfwWindow, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
glGenTextures(1, &fboTextureHandle);
|
||||
glBindTexture(GL_TEXTURE_2D, fboTextureHandle);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, fboTextureWidth, fboTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glGenFramebuffers(1, &fboHandle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, fboTextureHandle, 0);
|
||||
|
||||
GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
|
||||
glDrawBuffers(1, drawBuffers);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
// @TODO: Avoid exceptions
|
||||
throw std::runtime_error("OpenGL framebuffer incomplete");
|
||||
}
|
||||
}
|
||||
|
||||
double lastFrameStartTime = glfwGetTime();
|
||||
void RunLoop() {
|
||||
while (!glfwWindowShouldClose(glfwWindow))
|
||||
{
|
||||
double time = glfwGetTime();
|
||||
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(glfwWindow, &width, &height);
|
||||
const bool windowVisible = (width > 0 && height > 0);
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
// These change state now, so we must execute these before doing our own modifications to the io state for VR
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
io.DisplaySize = ImVec2((float)fboTextureWidth, (float)fboTextureHeight);
|
||||
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
|
||||
|
||||
io.ConfigFlags = io.ConfigFlags & ~ImGuiConfigFlags_NoMouseCursorChange;
|
||||
// if (dashboardVisible) {
|
||||
// io.ConfigFlags = io.ConfigFlags | ImGuiConfigFlags_NoMouseCursorChange;
|
||||
// }
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
ImGui::ShowDemoWindow();
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fboHandle);
|
||||
glViewport(0, 0, fboTextureWidth, fboTextureHeight);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
const double dashboardInterval = 1.0 / 90.0; // fps
|
||||
// double waitEventsTimeout = std::max(CalCtx.wantedUpdateInterval, dashboardInterval);
|
||||
double waitEventsTimeout = dashboardInterval;
|
||||
|
||||
glfwWaitEventsTimeout(waitEventsTimeout);
|
||||
|
||||
// If we're minimized rendering won't limit our frame rate so we need to do it ourselves.
|
||||
if (glfwGetWindowAttrib(glfwWindow, GLFW_ICONIFIED))
|
||||
{
|
||||
double targetFrameTime = 1 / MINIMIZED_MAX_FPS;
|
||||
double waitTime = targetFrameTime - (glfwGetTime() - lastFrameStartTime);
|
||||
if (waitTime > 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::duration<double>(waitTime));
|
||||
}
|
||||
|
||||
lastFrameStartTime += targetFrameTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
int APIENTRY wWinMain(_In_ HINSTANCE hInstance, _In_opt_ HINSTANCE hPrevInstance, _In_ LPWSTR lpCmdLine, _In_ int nCmdShow)
|
||||
{
|
||||
util::init();
|
||||
logging::Init(/* isOverlay */ true);
|
||||
|
||||
if (!glfwInit())
|
||||
{
|
||||
const char* szGlfwError = nullptr;
|
||||
glfwGetError(&szGlfwError);
|
||||
LOG_FATAL("Failed to initialise GLFW, got {}.", szGlfwError);
|
||||
MessageBoxW(nullptr, L"Failed to initialize GLFW", L"An error occured initialising Space Calibrator Nova", 0);
|
||||
return 0;
|
||||
spacecal::Window* theWindow = new spacecal::Window;
|
||||
if (!theWindow) {
|
||||
// @TODO: MessageBox
|
||||
return -1;
|
||||
}
|
||||
|
||||
CreateGLFWWindow();
|
||||
if (!theWindow->CreateNativeWindow()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
LOG_INFO("made window hiiii");
|
||||
LOG_INFO("Started Space Calibrator Nova!");
|
||||
|
||||
RunLoop();
|
||||
theWindow->RunLoop();
|
||||
|
||||
if (fboHandle)
|
||||
glDeleteFramebuffers(1, &fboHandle);
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
// ImPlot::DestroyContext();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
if (glfwWindow)
|
||||
glfwDestroyWindow(glfwWindow);
|
||||
|
||||
glfwTerminate();
|
||||
theWindow->Shutdown();
|
||||
delete theWindow;
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
#include "user_interface.h"
|
||||
|
||||
namespace spacecal {
|
||||
void DrawInterface() {
|
||||
ImGui::ShowDemoWindow();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
#pragma once
|
||||
|
||||
#include "imgui.h"
|
||||
|
||||
namespace spacecal {
|
||||
// Draws the user interface with ImGUI
|
||||
void DrawInterface();
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
#include "window.h"
|
||||
#include "log.h"
|
||||
#include "user_interface.h"
|
||||
|
||||
#include <imgui/imgui.h>
|
||||
#include <imgui/imgui_internal.h>
|
||||
#include <imgui/backends/imgui_impl_glfw.h>
|
||||
#include <imgui/backends/imgui_impl_opengl3.h>
|
||||
|
||||
namespace spacecal {
|
||||
bool Window::CreateNativeWindow() {
|
||||
if (!glfwInit())
|
||||
{
|
||||
const char* szGlfwError = nullptr;
|
||||
glfwGetError(&szGlfwError);
|
||||
LOG_FATAL("Failed to initialise GLFW, got {}.", szGlfwError);
|
||||
MessageBoxW(nullptr, L"Failed to initialize GLFW", L"An error occured initialising Space Calibrator Nova", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, 3);
|
||||
glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, 2);
|
||||
glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
|
||||
glfwWindowHint(GLFW_RESIZABLE, false);
|
||||
|
||||
#ifdef _DEBUG
|
||||
glfwWindowHint(GLFW_OPENGL_DEBUG_CONTEXT, GL_TRUE);
|
||||
#endif
|
||||
|
||||
m_glfwWindow = glfwCreateWindow(m_fboTextureWidth, m_fboTextureHeight, "Space Calibrator", nullptr, nullptr);
|
||||
if (!m_glfwWindow) {
|
||||
LOG_FATAL("Failed to create GLFW window");
|
||||
MessageBoxW(nullptr, L"Failed to create GLFW window", L"An error occured initialising Space Calibrator Nova", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
glfwMakeContextCurrent(m_glfwWindow);
|
||||
glfwSwapInterval(1);
|
||||
gladLoadGL();
|
||||
|
||||
// Minimise the window
|
||||
glfwIconifyWindow(m_glfwWindow);
|
||||
HWND windowHwmd = glfwGetWin32Window(m_glfwWindow);
|
||||
// EnableDarkModeTopBar(windowHwmd);
|
||||
|
||||
// Load icon and set it in the window
|
||||
// GLFWimage images[1] = {};
|
||||
// std::string iconPath = cwd;
|
||||
// iconPath += "\\taskbar_icon.png";
|
||||
// images[0].pixels = stbi_load(iconPath.c_str(), &images[0].width, &images[0].height, 0, 4);
|
||||
// glfwSetWindowIcon(glfwWindow, 1, images);
|
||||
// stbi_image_free(images[0].pixels);
|
||||
|
||||
#ifdef _DEBUG
|
||||
// glDebugMessageCallback(openGLDebugCallback, nullptr);
|
||||
// glEnable(GL_DEBUG_OUTPUT);
|
||||
#endif
|
||||
|
||||
ImGui::CreateContext();
|
||||
// ImPlot::CreateContext();
|
||||
ImGuiIO& io = ImGui::GetIO();
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard;
|
||||
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad;
|
||||
io.IniFilename = nullptr;
|
||||
|
||||
// load resources
|
||||
// io.Fonts->AddFontFromMemoryCompressedTTF(DroidSans_compressed_data, DroidSans_compressed_size, 24.0f);
|
||||
|
||||
ImGui_ImplGlfw_InitForOpenGL(m_glfwWindow, true);
|
||||
ImGui_ImplOpenGL3_Init("#version 330");
|
||||
|
||||
ImGui::StyleColorsDark();
|
||||
|
||||
glGenTextures(1, &m_fboTextureHandle);
|
||||
glBindTexture(GL_TEXTURE_2D, m_fboTextureHandle);
|
||||
glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA8, m_fboTextureWidth, m_fboTextureHeight, 0, GL_RGBA, GL_UNSIGNED_BYTE, 0);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
glGenFramebuffers(1, &m_fboHandle);
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fboHandle);
|
||||
glFramebufferTexture(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, m_fboTextureHandle, 0);
|
||||
|
||||
GLenum drawBuffers[1] = { GL_COLOR_ATTACHMENT0 };
|
||||
glDrawBuffers(1, drawBuffers);
|
||||
|
||||
if (glCheckFramebufferStatus(GL_FRAMEBUFFER) != GL_FRAMEBUFFER_COMPLETE)
|
||||
{
|
||||
LOG_FATAL("OpenGL framebuffer incomplete.");
|
||||
MessageBoxW(nullptr, L"OpenGL framebuffer incomplete", L"An error occured initialising Space Calibrator Nova", 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void Window::Shutdown() {
|
||||
if (m_fboHandle)
|
||||
glDeleteFramebuffers(1, &m_fboHandle);
|
||||
|
||||
ImGui_ImplOpenGL3_Shutdown();
|
||||
ImGui_ImplGlfw_Shutdown();
|
||||
// ImPlot::DestroyContext();
|
||||
ImGui::DestroyContext();
|
||||
|
||||
if (m_glfwWindow)
|
||||
glfwDestroyWindow(m_glfwWindow);
|
||||
|
||||
glfwTerminate();
|
||||
}
|
||||
|
||||
void Window::RunLoop() {
|
||||
double lastFrameStartTime = glfwGetTime();
|
||||
while (!glfwWindowShouldClose(m_glfwWindow))
|
||||
{
|
||||
double time = glfwGetTime();
|
||||
|
||||
int width, height;
|
||||
glfwGetFramebufferSize(m_glfwWindow, &width, &height);
|
||||
const bool windowVisible = (width > 0 && height > 0);
|
||||
|
||||
auto& io = ImGui::GetIO();
|
||||
|
||||
// These change state now, so we must execute these before doing our own modifications to the io state for VR
|
||||
ImGui_ImplOpenGL3_NewFrame();
|
||||
ImGui_ImplGlfw_NewFrame();
|
||||
|
||||
io.DisplaySize = ImVec2((float)m_fboTextureWidth, (float)m_fboTextureHeight);
|
||||
io.DisplayFramebufferScale = ImVec2(1.0f, 1.0f);
|
||||
|
||||
io.ConfigFlags = io.ConfigFlags & ~ImGuiConfigFlags_NoMouseCursorChange;
|
||||
// if (dashboardVisible) {
|
||||
// io.ConfigFlags = io.ConfigFlags | ImGuiConfigFlags_NoMouseCursorChange;
|
||||
// }
|
||||
|
||||
ImGui::NewFrame();
|
||||
|
||||
spacecal::DrawInterface();
|
||||
|
||||
ImGui::EndFrame();
|
||||
ImGui::Render();
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, m_fboHandle);
|
||||
glViewport(0, 0, m_fboTextureWidth, m_fboTextureHeight);
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
|
||||
ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
|
||||
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
|
||||
if (width && height)
|
||||
{
|
||||
glBindFramebuffer(GL_READ_FRAMEBUFFER, m_fboHandle);
|
||||
glBlitFramebuffer(0, 0, width, height, 0, 0, width, height, GL_COLOR_BUFFER_BIT, GL_NEAREST);
|
||||
glfwSwapBuffers(m_glfwWindow);
|
||||
}
|
||||
|
||||
|
||||
const double dashboardInterval = 1.0 / 90.0; // fps
|
||||
// double waitEventsTimeout = std::max(CalCtx.wantedUpdateInterval, dashboardInterval);
|
||||
double waitEventsTimeout = dashboardInterval;
|
||||
|
||||
glfwWaitEventsTimeout(waitEventsTimeout);
|
||||
|
||||
// If we're minimized rendering won't limit our frame rate so we need to do it ourselves.
|
||||
if (glfwGetWindowAttrib(m_glfwWindow, GLFW_ICONIFIED))
|
||||
{
|
||||
double targetFrameTime = 1 / k_MINIMIZED_MAX_FPS;
|
||||
double waitTime = targetFrameTime - (glfwGetTime() - lastFrameStartTime);
|
||||
if (waitTime > 0)
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::duration<double>(waitTime));
|
||||
}
|
||||
|
||||
lastFrameStartTime += targetFrameTime;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include <glad/glad.h>
|
||||
#define GLFW_EXPOSE_NATIVE_WIN32
|
||||
#include <GLFW/glfw3.h>
|
||||
#include <GLFW/glfw3native.h>
|
||||
|
||||
namespace spacecal {
|
||||
// handles window creation, setting the icon, and initialising a renderer for UI, also handles connecting it to SteamVR as an overlay
|
||||
class Window {
|
||||
public:
|
||||
bool CreateNativeWindow();
|
||||
void Shutdown();
|
||||
void RunLoop();
|
||||
|
||||
private:
|
||||
GLFWwindow* m_glfwWindow = nullptr;
|
||||
GLuint m_fboHandle = 0;
|
||||
GLuint m_fboTextureHandle = 0;
|
||||
int m_fboTextureWidth = 1200;
|
||||
int m_fboTextureHeight = 800;
|
||||
|
||||
const float k_MINIMIZED_MAX_FPS = 60.0f;
|
||||
};
|
||||
}
|
||||
Reference in new issue
Block a user