52 #ifdef USE_OCULUS_RIFT
54 # define GLFW_EXPOSE_NATIVE_WIN32
55 # define GLFW_EXPOSE_NATIVE_WGL
56 # include <GLFW/glfw3native.h>
59 # pragma comment(lib, "LibOVR.lib")
61 # include <OVR_CAPI_GL.h>
62 # include <Extras/OVR_Math.h>
63 # if OVR_PRODUCT_VERSION > 0
65 # pragma comment(lib, "dxgi.lib")
72 # include "imgui_impl_glfw.h"
73 # include "imgui_impl_opengl3.h"
94 std::array<GLsizei, 2> size;
97 std::array<GLsizei, 2> fboSize;
103 std::array<GLfloat, 2> velocity;
106 std::array<bool, BUTTON_COUNT> status;
112 std::array<std::array<int, 2>, 4> arrow;
115 std::array<GLfloat, 2> mouse;
118 std::array<GLfloat, 2> wheel;
121 std::array<std::array<std::array<GLfloat, 2>, 2>,
BUTTON_COUNT> location;
124 std::array<std::array<std::array<GLfloat, 3>, 2>,
BUTTON_COUNT> translation;
127 std::array<GgTrackball, BUTTON_COUNT> trackball;
139 void calcTranslation(
int button,
const std::array<GLfloat, 2>& velocity)
142 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
143 const GLfloat dx((mouse[0] - trackball[button].getStart(0)) * trackball[button].getScale(0));
144 const GLfloat dy((trackball[button].getStart(1) - mouse[1]) * trackball[button].getScale(1));
147 auto& l(location[button]);
150 l[1][0] = dx * velocity[0] + l[0][0];
151 l[1][1] = dy * velocity[1] + l[0][1];
154 auto& t(translation[button]);
157 const GLfloat d(fabs(t[1][2]));
160 t[1][0] = dx * d + t[0][0];
161 t[1][1] = dy * d + t[0][1];
164 trackball[button].motion(mouse[0], mouse[1]);
169 std::array<UserInterface, INTERFACE_COUNT> ui_data;
174 #ifdef USE_OCULUS_RIFT
186 GLfloat screen[ovrEye_Count][4];
189 GLuint oculusFbo[ovrEye_Count];
194 # if OVR_PRODUCT_VERSION > 0
197 ovrLayerEyeFov layerData;
200 long long frameIndex;
203 GLuint oculusDepth[ovrEye_Count];
206 int mirrorWidth, mirrorHeight;
209 ovrMirrorTexture mirrorTexture;
212 inline ovrGraphicsLuid GetDefaultAdapterLuid()
214 ovrGraphicsLuid luid = ovrGraphicsLuid();
217 IDXGIFactory *factory(
nullptr);
219 if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&factory))))
221 IDXGIAdapter *adapter(
nullptr);
223 if (SUCCEEDED(factory->EnumAdapters(0, &adapter)))
225 DXGI_ADAPTER_DESC desc;
227 adapter->GetDesc(&desc);
228 memcpy(&luid, &desc.AdapterLuid,
sizeof luid);
240 inline int Compare(
const ovrGraphicsLuid &lhs,
const ovrGraphicsLuid &rhs)
242 return memcmp(&lhs, &rhs,
sizeof(ovrGraphicsLuid));
248 ovrLayer_Union layerData;
251 ovrEyeRenderDesc eyeRenderDesc[ovrEye_Count];
254 ovrPosef eyePose[ovrEye_Count];
257 ovrGLTexture *mirrorTexture;
266 void (*resizeFunc)(
const Window *window,
int width,
int height);
267 void (*keyboardFunc)(
const Window *window,
int key,
int scancode,
int action,
int mods);
268 void (*mouseFunc)(
const Window *window,
int button,
int action,
int mods);
269 void (*wheelFunc)(
const Window *window,
double x,
double y);
274 static void resize(GLFWwindow *window,
int width,
int height)
277 Window *
const instance(
static_cast<Window *
>(glfwGetWindowUserPointer(window)));
282 instance->size[0] = width;
283 instance->size[1] = height;
286 for (
auto& current_if : instance->ui_data)
288 for (
auto& t : current_if.trackball)
290 t.region(width, height);
294 #ifndef USE_OCULUS_RIFT
296 instance->aspect =
static_cast<GLfloat
>(width) /
static_cast<GLfloat
>(height);
299 glfwGetFramebufferSize(window, &instance->fboSize[0], &instance->fboSize[1]);
300 glViewport(0, 0, instance->fboSize[0], instance->fboSize[1]);
304 if (instance->resizeFunc) (*instance->resizeFunc)(instance, width, height);
311 static void keyboard(GLFWwindow *window,
int key,
int scancode,
int action,
int mods)
315 if (ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow))
return;
319 Window *
const instance(
static_cast<Window *
>(glfwGetWindowUserPointer(window)));
321 if (instance && action)
324 if (instance->keyboardFunc) (*instance->keyboardFunc)(instance, key, scancode, action, mods);
327 auto& current_if(instance->ui_data[instance->ui_no]);
344 if (mods & GLFW_MOD_SHIFT)
345 current_if.arrow[1][1]++;
346 else if (mods & GLFW_MOD_CONTROL)
347 current_if.arrow[2][1]++;
348 else if (mods & GLFW_MOD_ALT)
349 current_if.arrow[3][1]++;
351 current_if.arrow[0][1]++;
356 if (mods & GLFW_MOD_SHIFT)
357 current_if.arrow[1][1]--;
358 else if (mods & GLFW_MOD_CONTROL)
359 current_if.arrow[2][1]--;
360 else if (mods & GLFW_MOD_ALT)
361 current_if.arrow[3][1]--;
363 current_if.arrow[0][1]--;
368 if (mods & GLFW_MOD_SHIFT)
369 current_if.arrow[1][0]++;
370 else if (mods & GLFW_MOD_CONTROL)
371 current_if.arrow[2][0]++;
372 else if (mods & GLFW_MOD_ALT)
373 current_if.arrow[3][0]++;
375 current_if.arrow[0][0]++;
380 if (mods & GLFW_MOD_SHIFT)
381 current_if.arrow[1][0]--;
382 else if (mods & GLFW_MOD_CONTROL)
383 current_if.arrow[2][0]--;
384 else if (mods & GLFW_MOD_ALT)
385 current_if.arrow[3][0]--;
387 current_if.arrow[0][0]--;
400 static void mouse(GLFWwindow *window,
int button,
int action,
int mods)
404 if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
return;
408 Window*
const instance(
static_cast<Window*
>(glfwGetWindowUserPointer(window)));
411 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
412 instance->status[button] = action != GLFW_RELEASE;
417 if (instance->mouseFunc) (*instance->mouseFunc)(instance, button, action, mods);
420 auto& current_if(instance->ui_data[instance->ui_no]);
423 const GLfloat x(current_if.mouse[0]);
424 const GLfloat y(current_if.mouse[1]);
426 if (x < 0 || x >= instance->size[0] || y < 0 || y >= instance->size[1])
return;
431 current_if.trackball[button].begin(x, y);
436 current_if.location[button][0] = current_if.location[button][1];
437 current_if.translation[button][0] = current_if.translation[button][1];
438 current_if.trackball[button].end(x, y);
446 static void wheel(GLFWwindow *window,
double x,
double y)
450 if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
return;
454 Window *
const instance(
static_cast<Window *
>(glfwGetWindowUserPointer(window)));
459 if (instance->wheelFunc) (*instance->wheelFunc)(instance, x, y);
462 auto& current_if(instance->ui_data[instance->ui_no]);
465 current_if.wheel[0] +=
static_cast<GLfloat
>(x);
466 current_if.wheel[1] +=
static_cast<GLfloat
>(y);
469 const GLfloat z(instance->
getWheelY() * 0.5f);
470 for (
auto& t : current_if.translation) t[1][2] = z;
474 #ifdef USE_OCULUS_RIFT
478 void terminateLibOVR()
481 if (mirrorFbo) glDeleteFramebuffers(1, &mirrorFbo);
486 # if OVR_PRODUCT_VERSION > 0
487 ovr_DestroyMirrorTexture(session, mirrorTexture);
489 glDeleteTextures(1, &mirrorTexture->OGL.TexId);
490 ovr_DestroyMirrorTexture(session,
reinterpret_cast<ovrTexture *
>(mirrorTexture));
495 glDeleteFramebuffers(ovrEye_Count, oculusFbo);
498 for (
int eye = 0; eye < ovrEye_Count; ++eye)
500 # if OVR_PRODUCT_VERSION > 0
503 if (layerData.ColorTexture[eye])
505 ovr_DestroyTextureSwapChain(session, layerData.ColorTexture[eye]);
506 layerData.ColorTexture[eye] =
nullptr;
510 glDeleteTextures(1, &oculusDepth[eye]);
511 oculusDepth[eye] = 0;
516 auto *
const colorTexture(layerData.EyeFov.ColorTexture[eye]);
517 for (
int i = 0; i < colorTexture->TextureCount; ++i)
519 const auto *
const ctex(
reinterpret_cast<ovrGLTexture *
>(&colorTexture->Textures[i]));
520 glDeleteTextures(1, &ctex->OGL.TexId);
522 ovr_DestroySwapTextureSet(session, colorTexture);
525 auto *
const depthTexture(layerData.EyeFovDepth.DepthTexture[eye]);
526 for (
int i = 0; i < depthTexture->TextureCount; ++i)
528 const auto *
const dtex(
reinterpret_cast<ovrGLTexture *
>(&depthTexture->Textures[i]));
529 glDeleteTextures(1, &dtex->OGL.TexId);
531 ovr_DestroySwapTextureSet(session, depthTexture);
537 ovr_Destroy(session);
548 static void glfwErrorCallback(
int error,
const char *description)
551 if (error == 65544)
return;
553 throw std::runtime_error(description);
561 static void init(
int major = 0,
int minor = 1)
564 static bool firstTime(
true);
567 if (!firstTime)
return;
573 glfwSetErrorCallback(glfwErrorCallback);
574 if (glfwInit() == GL_FALSE)
throw std::runtime_error(
"Can't initialize GLFW");
577 atexit(glfwTerminate);
583 glfwWindowHint(GLFW_CONTEXT_VERSION_MAJOR, major);
584 glfwWindowHint(GLFW_CONTEXT_VERSION_MINOR, minor);
586 if (major * 10 + minor >= 32)
589 glfwWindowHint(GLFW_OPENGL_FORWARD_COMPAT, GL_TRUE);
590 glfwWindowHint(GLFW_OPENGL_PROFILE, GLFW_OPENGL_CORE_PROFILE);
594 #ifdef USE_OCULUS_RIFT
596 ovrInitParams initParams = { ovrInit_RequestVersion, OVR_MINOR_VERSION, NULL, 0, 0 };
597 if (OVR_FAILURE(ovr_Initialize(&initParams)))
throw std::runtime_error(
"Can't initialize LibOVR");
600 atexit(terminateLibOVR);
603 ovrGraphicsLuid luid;
605 if (OVR_FAILURE(ovr_Create(&session, &luid)))
throw std::runtime_error(
"Can't create Oculus Rift session");
608 for (
int eye = 0; eye < ovrEye_Count; ++eye) oculusFbo[eye] = 0;
612 mirrorTexture =
nullptr;
614 # if OVR_PRODUCT_VERSION > 0
616 if (Compare(luid, GetDefaultAdapterLuid()))
throw std::runtime_error(
"Graphics adapter is not default");
622 for (
int eye = 0; eye < ovrEye_Count; ++eye) oculusDepth[eye] = 0;
626 glfwWindowHint(GLFW_DOUBLEBUFFER, GL_FALSE);
629 glfwWindowHint(GLFW_SRGB_CAPABLE, GL_TRUE);
634 IMGUI_CHECKVERSION();
637 ImGui::CreateContext();
640 atexit([] { ImGui::DestroyContext(); });
650 Window(
const char *title =
"GLFW Window",
int width = 640,
int height = 480,
651 int fullscreen = 0, GLFWwindow *share =
nullptr)
652 : window(nullptr), size{ width, height }, aspect(1.0f)
653 , velocity{ 1.0f, 1.0f }
656 , userPointer(nullptr)
657 , resizeFunc(nullptr)
658 , keyboardFunc(nullptr)
663 GLFWmonitor *monitor(
nullptr);
670 GLFWmonitor **
const monitors(glfwGetMonitors(&mcount));
673 if (fullscreen > mcount) fullscreen = mcount;
674 monitor = monitors[fullscreen - 1];
677 const GLFWvidmode *mode(glfwGetVideoMode(monitor));
681 height = mode->height;
685 window = glfwCreateWindow(width, height, title, monitor, share);
688 if (!window)
throw std::runtime_error(
"Unable to open the GLFW window.");
691 glfwMakeContextCurrent(window);
697 glfwSetWindowUserPointer(window,
this);
700 glfwSetKeyCallback(window, keyboard);
703 glfwSetMouseButtonCallback(window, mouse);
706 glfwSetScrollCallback(window, wheel);
709 glfwSetFramebufferSizeCallback(window, resize);
711 #ifdef USE_OCULUS_RIFT
713 hmdDesc = ovr_GetHmdDesc(session);
718 <<
"\nProduct name: " << hmdDesc.ProductName
719 <<
"\nResolution: " << hmdDesc.Resolution.w <<
" x " << hmdDesc.Resolution.h
720 <<
"\nDefault Fov: (" << hmdDesc.DefaultEyeFov[ovrEye_Left].LeftTan
721 <<
"," << hmdDesc.DefaultEyeFov[ovrEye_Left].DownTan
722 <<
") - (" << hmdDesc.DefaultEyeFov[ovrEye_Left].RightTan
723 <<
"," << hmdDesc.DefaultEyeFov[ovrEye_Left].UpTan
724 <<
")\n (" << hmdDesc.DefaultEyeFov[ovrEye_Right].LeftTan
725 <<
"," << hmdDesc.DefaultEyeFov[ovrEye_Right].DownTan
726 <<
") - (" << hmdDesc.DefaultEyeFov[ovrEye_Right].RightTan
727 <<
"," << hmdDesc.DefaultEyeFov[ovrEye_Right].UpTan
728 <<
")\nMaximum Fov: (" << hmdDesc.MaxEyeFov[ovrEye_Left].LeftTan
729 <<
"," << hmdDesc.MaxEyeFov[ovrEye_Left].DownTan
730 <<
") - (" << hmdDesc.MaxEyeFov[ovrEye_Left].RightTan
731 <<
"," << hmdDesc.MaxEyeFov[ovrEye_Left].UpTan
732 <<
")\n (" << hmdDesc.MaxEyeFov[ovrEye_Right].LeftTan
733 <<
"," << hmdDesc.MaxEyeFov[ovrEye_Right].DownTan
734 <<
") - (" << hmdDesc.MaxEyeFov[ovrEye_Right].RightTan
735 <<
"," << hmdDesc.MaxEyeFov[ovrEye_Right].UpTan
736 <<
")\n" << std::endl;
740 # if OVR_PRODUCT_VERSION > 0
741 layerData.Header.Type = ovrLayerType_EyeFov;
743 layerData.Header.Type = ovrLayerType_EyeFovDepth;
745 layerData.Header.Flags = ovrLayerFlag_TextureOriginAtBottomLeft;
748 for (
int eye = 0; eye < ovrEye_Count; ++eye)
751 const auto &fov(hmdDesc.DefaultEyeFov[ovrEyeType(eye)]);
754 const auto textureSize(ovr_GetFovTextureSize(session, ovrEyeType(eye), fov, 1.0f));
757 aspect =
static_cast<GLfloat
>(textureSize.w) /
static_cast<GLfloat
>(textureSize.h);
760 screen[eye][0] = -fov.LeftTan;
761 screen[eye][1] = fov.RightTan;
762 screen[eye][2] = -fov.DownTan;
763 screen[eye][3] = fov.UpTan;
765 # if OVR_PRODUCT_VERSION > 0
768 layerData.Fov[eye] = fov;
771 layerData.Viewport[eye].Pos = OVR::Vector2i(0, 0);
772 layerData.Viewport[eye].Size = textureSize;
775 const ovrTextureSwapChainDesc colorDesc =
778 OVR_FORMAT_R8G8B8A8_UNORM_SRGB,
789 layerData.ColorTexture[eye] =
nullptr;
790 if (OVR_SUCCESS(ovr_CreateTextureSwapChainGL(session, &colorDesc, &layerData.ColorTexture[eye])))
794 if (OVR_SUCCESS(ovr_GetTextureSwapChainLength(session, layerData.ColorTexture[eye], &length)))
797 for (
int i = 0; i < length; ++i)
801 ovr_GetTextureSwapChainBufferGL(session, layerData.ColorTexture[eye], i, &texId);
802 glBindTexture(GL_TEXTURE_2D, texId);
803 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
804 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
805 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
806 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
811 glGenTextures(1, &oculusDepth[eye]);
812 glBindTexture(GL_TEXTURE_2D, oculusDepth[eye]);
813 glTexImage2D(GL_TEXTURE_2D, 0, GL_DEPTH_COMPONENT32F, textureSize.w, textureSize.h, 0, GL_DEPTH_COMPONENT, GL_FLOAT, NULL);
814 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
815 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
816 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
817 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
823 layerData.EyeFov.Fov[eye] = fov;
826 layerData.EyeFov.Viewport[eye].Pos = OVR::Vector2i(0, 0);
827 layerData.EyeFov.Viewport[eye].Size = textureSize;
830 ovrSwapTextureSet *colorTexture;
831 ovr_CreateSwapTextureSetGL(session, GL_SRGB8_ALPHA8, textureSize.w, textureSize.h, &colorTexture);
832 layerData.EyeFov.ColorTexture[eye] = colorTexture;
835 ovrSwapTextureSet *depthTexture;
836 ovr_CreateSwapTextureSetGL(session, GL_DEPTH_COMPONENT32F, textureSize.w, textureSize.h, &depthTexture);
837 layerData.EyeFovDepth.DepthTexture[eye] = depthTexture;
840 eyeRenderDesc[eye] = ovr_GetRenderDesc(session, ovrEyeType(eye), fov);
845 # if OVR_PRODUCT_VERSION > 0
848 ovr_SetTrackingOriginType(session, ovrTrackingOrigin_FloorLevel);
851 const ovrMirrorTextureDesc mirrorDesc =
853 OVR_FORMAT_R8G8B8A8_UNORM_SRGB,
855 mirrorHeight = height,
860 if (OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, &mirrorDesc, &mirrorTexture)))
864 if (OVR_SUCCESS(ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId)))
867 glGenFramebuffers(1, &mirrorFbo);
868 glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo);
869 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
870 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
871 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
878 if (OVR_SUCCESS(ovr_CreateMirrorTextureGL(session, GL_SRGB8_ALPHA8, width, height,
reinterpret_cast<ovrTexture **
>(&mirrorTexture))))
880 glGenFramebuffers(1, &mirrorFbo);
881 glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo);
882 glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, mirrorTexture->OGL.TexId, 0);
883 glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
884 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
890 glGenFramebuffers(ovrEye_Count, oculusFbo);
893 glEnable(GL_FRAMEBUFFER_SRGB);
906 resize(window, width, height);
910 ImGui_ImplGlfw_InitForOpenGL(window,
true);
911 ImGui_ImplOpenGL3_Init(
nullptr);
929 ImGui_ImplOpenGL3_Shutdown();
930 ImGui_ImplGlfw_Shutdown();
934 glfwDestroyWindow(window);
937 #ifdef USE_OCULUS_RIFT
943 # if OVR_PRODUCT_VERSION > 0
946 ovrSessionStatus sessionStatus;
947 ovr_GetSessionStatus(session, &sessionStatus);
950 if (sessionStatus.ShouldQuit) setClose(GLFW_TRUE);
953 if (!sessionStatus.IsVisible)
return false;
956 if (sessionStatus.ShouldRecenter) ovr_RecenterTrackingOrigin(session);
959 const ovrEyeRenderDesc eyeRenderDesc[] =
961 ovr_GetRenderDesc(session, ovrEyeType(0), hmdDesc.DefaultEyeFov[0]),
962 ovr_GetRenderDesc(session, ovrEyeType(1), hmdDesc.DefaultEyeFov[1])
966 const ovrPosef hmdToEyePose[] =
968 eyeRenderDesc[0].HmdToEyePose,
969 eyeRenderDesc[1].HmdToEyePose
973 ovr_GetEyePoses(session, frameIndex, ovrTrue, hmdToEyePose, layerData.RenderPose, &layerData.SensorSampleTime);
978 const auto ftiming(ovr_GetPredictedDisplayTime(session, 0));
981 layerData.EyeFov.SensorSampleTime = ovr_GetTimeInSeconds();
984 const auto hmdState(ovr_GetTrackingState(session, ftiming, ovrTrue));
987 const ovrVector3f hmdToEyeViewOffset[] =
989 eyeRenderDesc[0].HmdToEyeViewOffset,
990 eyeRenderDesc[1].HmdToEyeViewOffset
994 ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewOffset, eyePose);
1006 void select(
int eye, GLfloat *screen, GLfloat *position, GLfloat *orientation)
1008 # if OVR_PRODUCT_VERSION > 0
1011 if (layerData.ColorTexture[eye])
1015 ovr_GetTextureSwapChainCurrentIndex(session, layerData.ColorTexture[eye], &curIndex);
1019 ovr_GetTextureSwapChainBufferGL(session, layerData.ColorTexture[eye], curIndex, &curTexId);
1022 glBindFramebuffer(GL_FRAMEBUFFER, oculusFbo[eye]);
1023 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, curTexId, 0);
1024 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, oculusDepth[eye], 0);
1027 const auto &vp(layerData.Viewport[eye]);
1028 glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h);
1032 const auto &p(layerData.RenderPose[eye].Position);
1033 const auto &o(layerData.RenderPose[eye].Orientation);
1038 auto *
const colorTexture(layerData.EyeFov.ColorTexture[eye]);
1039 colorTexture->CurrentIndex = (colorTexture->CurrentIndex + 1) % colorTexture->TextureCount;
1040 auto *
const depthTexture(layerData.EyeFovDepth.DepthTexture[eye]);
1041 depthTexture->CurrentIndex = (depthTexture->CurrentIndex + 1) % depthTexture->TextureCount;
1044 glBindFramebuffer(GL_FRAMEBUFFER, oculusFbo[eye]);
1045 const auto &ctex(
reinterpret_cast<ovrGLTexture *
>(&colorTexture->Textures[colorTexture->CurrentIndex]));
1046 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, ctex->OGL.TexId, 0);
1047 const auto &dtex(
reinterpret_cast<ovrGLTexture *
>(&depthTexture->Textures[depthTexture->CurrentIndex]));
1048 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, dtex->OGL.TexId, 0);
1051 const auto &vp(layerData.EyeFov.Viewport[eye]);
1052 glViewport(vp.Pos.x, vp.Pos.y, vp.Size.w, vp.Size.h);
1055 const auto &p(eyePose[eye].Position);
1056 const auto &o(eyePose[eye].Orientation);
1061 screen[0] = this->screen[eye][0];
1062 screen[1] = this->screen[eye][1];
1063 screen[2] = this->screen[eye][2];
1064 screen[3] = this->screen[eye][3];
1072 orientation[0] = o.x;
1073 orientation[1] = o.y;
1074 orientation[2] = o.z;
1075 orientation[3] = o.w;
1080 void timewarp(
const GgMatrix &projection)
1082 # if OVR_PRODUCT_VERSION < 1
1084 auto &posTimewarpProjectionDesc(layerData.EyeFovDepth.ProjectionDesc);
1085 posTimewarpProjectionDesc.Projection22 = (projection.
get()[4 * 2 + 2] + projection.
get()[4 * 3 + 2]) * 0.5f;
1086 posTimewarpProjectionDesc.Projection23 = projection.
get()[4 * 2 + 3] * 0.5f;
1087 posTimewarpProjectionDesc.Projection32 = projection.
get()[4 * 3 + 2];
1093 void commit(
int eye)
1095 # if OVR_PRODUCT_VERSION > 0
1099 glBindFramebuffer(GL_FRAMEBUFFER, oculusFbo[eye]);
1100 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, 0, 0);
1101 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_TEXTURE_2D, 0, 0);
1104 ovr_CommitTextureSwapChain(session, layerData.ColorTexture[eye]);
1110 void submit(
bool mirror =
true)
1115 # if OVR_PRODUCT_VERSION > 0
1117 const auto *
const layers(&layerData.Header);
1118 if (OVR_FAILURE(ovr_SubmitFrame(session, frameIndex++,
nullptr, &layers, 1)))
1121 ovrViewScaleDesc viewScaleDesc;
1122 viewScaleDesc.HmdSpaceToWorldScaleInMeters = 1.0f;
1123 viewScaleDesc.HmdToEyeViewOffset[0] = eyeRenderDesc[0].HmdToEyeViewOffset;
1124 viewScaleDesc.HmdToEyeViewOffset[1] = eyeRenderDesc[1].HmdToEyeViewOffset;
1127 layerData.EyeFov.RenderPose[0] = eyePose[0];
1128 layerData.EyeFov.RenderPose[1] = eyePose[1];
1131 const auto *
const layers(&layerData.Header);
1132 if (OVR_FAILURE(ovr_SubmitFrame(session, 0, &viewScaleDesc, &layers, 1)))
1137 setClose(GLFW_TRUE);
1144 glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFbo);
1145 glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
1146 # if OVR_PRODUCT_VERSION > 0
1147 glBlitFramebuffer(0, size[1], size[0], 0, 0, 0, size[0], size[1], GL_COLOR_BUFFER_BIT, GL_NEAREST);
1149 const auto w(mirrorTexture->OGL.Header.TextureSize.w);
1150 const auto h(mirrorTexture->OGL.Header.TextureSize.h);
1151 glBlitFramebuffer(0, h, w, 0, 0, 0, w, h, GL_COLOR_BUFFER_BIT, GL_NEAREST);
1153 glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
1157 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
1166 const int eyeCount = ovrEye_Count;
1171 const int eyeCount = 1;
1186 glfwSetWindowShouldClose(window, flag);
1194 return glfwWindowShouldClose(window) != GLFW_FALSE;
1205 if (shouldClose())
return false;
1208 auto& current_if(ui_data[ui_no]);
1213 ImGui_ImplOpenGL3_NewFrame();
1214 ImGui_ImplGlfw_NewFrame();
1217 if (ImGui::IsWindowHovered(ImGuiHoveredFlags_AnyWindow))
return true;
1220 const ImGuiIO &io(ImGui::GetIO());
1223 current_if.mouse = std::array<GLfloat, 2>{ io.MousePos.x, io.MousePos.y };
1229 glfwGetCursorPos(window, &x, &y);
1232 current_if.mouse = std::array<GLfloat, 2>{
static_cast<GLfloat
>(x),
static_cast<GLfloat
>(y) };
1237 for (
int button = GLFW_MOUSE_BUTTON_1; button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT; ++button)
1243 current_if.calcTranslation(button, velocity);
1255 ImGui_ImplOpenGL3_RenderDrawData(ImGui::GetDrawData());
1262 glfwSwapBuffers(window);
1290 size[0] = getWidth();
1291 size[1] = getHeight();
1304 #ifndef USE_OCULUS_RIFT
1306 glViewport(0, 0, fboSize[0], fboSize[1]);
1316 if (ImGui::IsWindowFocused(ImGuiFocusedFlags_AnyWindow))
return false;
1319 return glfwGetKey(window, key) != GLFW_RELEASE;
1326 assert(
static_cast<size_t>(no) < ui_data.size());
1335 velocity = std::array<GLfloat, 2>{ vx, vy };
1342 GLfloat
getArrow(
int direction = 0,
int mods = 0)
const
1344 const auto& current_if(ui_data[ui_no]);
1345 return static_cast<GLfloat
>(current_if.arrow[mods & 3][direction & 1]);
1353 return getArrow(0, mods);
1361 return getArrow(1, mods);
1369 arrow[0] = getArrowX(mods);
1370 arrow[1] = getArrowY(mods);
1377 return getArrow(0, 1);
1384 return getArrow(1, 1);
1391 shift_arrow[0] = getShiftArrowX();
1392 shift_arrow[1] = getShiftArrowY();
1399 return getArrow(0, 2);
1406 return getArrow(1, 2);
1413 control_arrow[0] = getControlArrowX();
1414 control_arrow[1] = getControlArrowY();
1421 return getArrow(0, 3);
1428 return getArrow(1, 3);
1435 alt_arrow[0] = getAltArrowX();
1436 alt_arrow[1] = getAltArrowY();
1443 const auto& current_if(ui_data[ui_no]);
1444 return current_if.mouse.data();
1451 const auto& current_if(ui_data[ui_no]);
1452 position[0] = current_if.mouse[0];
1453 position[1] = current_if.mouse[1];
1461 const auto& current_if(ui_data[ui_no]);
1462 return current_if.mouse[direction & 1];
1469 const auto& current_if(ui_data[ui_no]);
1470 return current_if.mouse[0];
1477 const auto& current_if(ui_data[ui_no]);
1478 return current_if.mouse[1];
1485 const auto& current_if(ui_data[ui_no]);
1486 return current_if.wheel.data();
1493 const auto& current_if(ui_data[ui_no]);
1494 rotation[0] = current_if.wheel[0];
1495 rotation[1] = current_if.wheel[1];
1503 const auto& current_if(ui_data[ui_no]);
1504 return current_if.wheel[direction & 1];
1510 const auto& current_if(ui_data[ui_no]);
1511 return current_if.wheel[0];
1517 const auto& current_if(ui_data[ui_no]);
1518 return current_if.wheel[1];
1526 const auto& current_if(ui_data[ui_no]);
1527 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
1528 return current_if.location[button][1].data();
1536 const auto& current_if(ui_data[ui_no]);
1537 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
1538 return ggTranslate(current_if.translation[button][1].data());
1546 const auto& current_if(ui_data[ui_no]);
1547 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
1548 return current_if.trackball[button].getQuaternion();
1556 const auto& current_if(ui_data[ui_no]);
1557 assert(button >= GLFW_MOUSE_BUTTON_1 && button < GLFW_MOUSE_BUTTON_1 +
BUTTON_COUNT);
1558 return current_if.trackball[button].getMatrix();
1565 for (
auto& tb : ui_data[ui_no].trackball)
1575 auto& current_if(ui_data[ui_no]);
1578 for (
auto& l : current_if.location)
1580 std::fill(l.begin(), l.end(), std::array<GLfloat, 2>{ 0.0f, 0.0f });
1584 for (
auto& t : current_if.translation)
1586 std::fill(t.begin(), t.end(), std::array<GLfloat, 3>{ 0.0f, 0.0f, 0.0f });
1590 std::fill(current_if.arrow.begin(), current_if.arrow.end(), std::array<int, 2>{ 0, 0 });
1593 std::fill(current_if.wheel.begin(), current_if.wheel.end(), 0.0f);
1603 reset_translation();
1617 userPointer = pointer;
1631 keyboardFunc = func;
constexpr int BUTTON_COUNT(3)
constexpr int INTERFACE_COUNT(3)
void reset()
トラックボール・マウスホイール・矢印キーの値を初期化する
void * getUserPointer() const
ユーザーポインタを取り出す.
GLfloat getShiftArrowX() const
SHIFT キーを押しながら矢印キーを押したときの現在の X 値を得る.
void getSize(GLsizei *size) const
ウィンドウのサイズを得る.
Window(const Window &w)=delete
コピーコンストラクタは使用禁止.
void reset_translation()
現在位置と平行移動量をリセットする
void setVelocity(GLfloat vx, GLfloat vy)
マウスの移動速度を設定する
void getMouse(GLfloat *position) const
マウスカーソルの現在位置を得る.
bool shouldClose() const
ウィンドウを閉じるべきかどうか調べる.
GLfloat getAspect() const
ウィンドウのアスペクト比を得る.
void setResizeFunc(void(*func)(const Window *window, double x, double y))
ユーザ定義の wheel 関数を設定する.
void getShiftArrow(GLfloat *shift_arrow) const
SHIFT キーを押しながら矢印キーを押したときの現在の値を得る.
GLFWwindow * get() const
ウィンドウの識別子のポインタを取得する.
void reset_trackball()
トラックボール処理をリセットする
const GLsizei * getSize() const
ウィンドウのサイズを得る.
const GLfloat getMouse(int direction) const
マウスカーソルの現在位置を得る.
const GLfloat * getWheel() const
マウスホイールの回転量を得る.
void getWheel(GLfloat *rotation) const
マウスホイールの回転量を得る.
void setResizeFunc(void(*func)(const Window *window, int width, int height))
ユーザ定義の resize 関数を設定する.
void getArrow(GLfloat *arrow, int mods=0) const
矢印キーの現在の値を得る.
const GLfloat * getMouse() const
マウスカーソルの現在位置を得る.
Window & operator=(const Window &w)=delete
代入演算子は使用禁止.
static void init(int major=0, int minor=1)
初期化, 最初に一度だけ実行する.
GLfloat getShiftArrowY() const
SHIFT キーを押しながら矢印キーを押したときの現在の Y 値を得る.
GLsizei getWidth() const
ウィンドウの横幅を得る.
GLsizei getHeight() const
ウィンドウの高さを得る.
GgQuaternion getTrackballData(int button=GLFW_MOUSE_BUTTON_1) const
トラックボールの回転変換行列を得る.
GLfloat getArrowY(int mods=0) const
矢印キーの現在の Y 値を得る.
Window(const char *title="GLFW Window", int width=640, int height=480, int fullscreen=0, GLFWwindow *share=nullptr)
コンストラクタ.
GLfloat getControlArrowY() const
CTRL キーを押しながら矢印キーを押したときの現在の Y 値を得る.
GLfloat getWheel(int direction) const
マウスホイールの回転量を得る.
void setClose(int flag=GLFW_TRUE) const
ウィンドウのクローズフラグを設定する.
GLfloat getMouseX() const
マウスカーソルの現在位置の X 座標を得る.
const GLfloat * getLocation(int button=GLFW_MOUSE_BUTTON_1) const
トラックボール処理を考慮したマウスによる現在位置のポインタを得る.
void getAltlArrow(GLfloat *alt_arrow) const
ALT キーを押しながら矢印キーを押したときの現在の値を得る.
void getControlArrow(GLfloat *control_arrow) const
CTRL キーを押しながら矢印キーを押したときの現在の値を得る.
void restoreViewport()
ビューポートをウィンドウ全体に設定する.
GLfloat getMouseY() const
マウスカーソルの現在位置の Y 座標を得る.
GgMatrix getTranslation(int button=GLFW_MOUSE_BUTTON_1) const
トラックボール処理を考慮したマウスによる平行移動の変換行列を得る.
GLfloat getArrowX(int mods=0) const
矢印キーの現在の X 値を得る.
bool getKey(int key)
キーが押されているかどうかを判定する.
GLfloat getAltArrowY() const
ALT キーを押しながら矢印キーを押したときの現在の Y 値を得る.
GLfloat getArrow(int direction=0, int mods=0) const
矢印キーの現在の値を得る.
const GLfloat getWheelX() const
マウスホイールの X 方向の回転量を得る.
const GLfloat getWheelY() const
マウスホイールの Y 方向の回転量を得る.
GLfloat getControlArrowX() const
CTRL キーを押しながら矢印キーを押したときの現在の X 値を得る.
void selectInterface(int no)
インタフェースを選択する
void setKeyboardFunc(void(*func)(const Window *window, int key, int scancode, int action, int mods))
ユーザ定義の keyboard 関数を設定する.
void setUserPointer(void *pointer)
任意のユーザポインタを保存する.
void setMouseFunc(void(*func)(const Window *window, int button, int action, int mods))
ユーザ定義の mouse 関数を設定する.
GLfloat getAltArrowX() const
ALT キーを押しながら矢印キーを押したときの現在の X 値を得る.
GgMatrix getTrackball(int button=GLFW_MOUSE_BUTTON_1) const
トラックボールの回転変換行列を得る.
void swapBuffers()
カラーバッファを入れ替える.
const GLfloat * get() const
変換行列を取り出す.
ゲームグラフィックス特論の宿題用補助プログラム GLFW3 版の宣言.
ゲームグラフィックス特論の宿題用補助プログラムの名前空間
GgMatrix ggTranslate(GLfloat x, GLfloat y, GLfloat z, GLfloat w=1.0f)
平行移動の変換行列を返す.
void ggInit()
ゲームグラフィックス特論の都合にもとづく初期化を行う.