OVR: Controller support with keyboard emulation
[mercenary-reloaded.git] / src / libovr / ovr.c
1 /* OVR handling
2  *
3  * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
4  * All Rights Reserved
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  *
19  * Based on example code:
20  * Filename    :   main.cpp
21  * Content     :   Simple minimal VR demo
22  * Created     :   December 1, 2014
23  * Author      :   Tom Heath
24  * Copyright   :   Copyright 2012 Oculus, Inc. All Rights reserved.
25  *
26  * Licensed under the Apache License, Version 2.0 (the "License");
27  * you may not use this file except in compliance with the License.
28  * You may obtain a copy of the License at
29  *
30  * http://www.apache.org/licenses/LICENSE-2.0
31  *
32  * Unless required by applicable law or agreed to in writing, software
33  * distributed under the License is distributed on an "AS IS" BASIS,
34  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
35  * See the License for the specific language governing permissions and
36  * limitations under the License.
37  */
38
39 #include <stdio.h>
40 #include <stdint.h>
41 #include <string.h>
42 #include <math.h>
43 #include <errno.h>
44 #include "../libsdl/print.h"
45 #include "ovr.h"
46
47 #include <OVR_CAPI.h>
48 #include <OVR_CAPI_GL.h>
49 #include "helper.h"
50
51 #define GL3_PROTOTYPES 1
52 #include <GL/glew.h>
53
54 #if 0
55 #if defined(_WIN32)
56     #include <dxgi.h> // for GetDefaultAdapterLuid
57     #pragma comment(lib, "dxgi.lib")
58 #endif
59
60 static ovrGraphicsLuid GetDefaultAdapterLuid()
61 {
62         ovrGraphicsLuid luid = ovrGraphicsLuid();
63
64 #if defined(_WIN32)
65         IDXGIFactory* factory = nullptr;
66
67         if (SUCCEEDED(CreateDXGIFactory(IID_PPV_ARGS(&factory)))) {
68                 IDXGIAdapter* adapter = nullptr;
69
70                 if (SUCCEEDED(factory->EnumAdapters(0, &adapter))) {
71                         DXGI_ADAPTER_DESC desc;
72
73                         adapter->GetDesc(&desc);
74                         memcpy(&luid, &desc.AdapterLuid, sizeof(luid));
75                         adapter->Release();
76                 }
77
78                 factory->Release();
79         }
80 #endif
81
82         return luid;
83 }
84
85 static int Compare(const ovrGraphicsLuid lhs, const ovrGraphicsLuid rhs)
86 {
87     return memcmp(&lhs, &rhs, sizeof(ovrGraphicsLuid));
88 }
89 #endif
90
91 static int ovr_initialized = 0;
92 static ovrSession session = NULL;
93 static ovrGraphicsLuid luid;
94 static ovrHmdDesc hmdDesc;
95 static ovrSizei TextureSize[2];
96 static ovrTextureSwapChain textureSwapChain[2] = { NULL, NULL };
97 static GLuint fboId[2] = { 0, 0 };
98 static GLuint mirrorFBO = 0;
99 static int mirror_width;
100 static int mirror_height;
101 static ovrEyeRenderDesc eyeRenderDesc[2];
102 static ovrPosef hmdToEyeViewPose[2];
103 static ovrPosef handPoses[2];
104 static ovrInputState inputState;
105 static ovrLayerEyeFov layer;
106 static int multisampling;
107 static long long frameIndex = 0;
108 static double observer_x = 0.0;
109 static double observer_x_normalize = 0.0;
110 static double hand_x_normalize = 0.0;
111 static double observer_y = 0.0;
112 static double observer_y_normalize = 0.0;
113 static double hand_y_normalize = 0.0;
114 static double observer_z = 0.0;
115 static double observer_z_normalize = 0.0;
116 static double hand_z_normalize = 0.0;
117
118 int init_ovr(int _multisampling)
119 {
120         ovrResult result;
121         int eye;
122
123         multisampling = _multisampling;
124
125         glewExperimental = GL_TRUE;
126         if (glewInit() != GLEW_OK) {
127                 print_error("Failed to init GLEW\n");
128                 goto error;
129         }
130
131         result = ovr_Initialize(NULL);
132         if (OVR_FAILURE(result)) {
133                 print_error("Failed to init OVR (is Oculus Rift service running?)\n");
134                 goto error;
135         }
136         ovr_initialized = 1;
137
138         result = ovr_Create(&session, &luid);
139         if (OVR_FAILURE(result)) {
140                 print_error("Failed to create OVR session (is the HMD connected?)\n");
141                 goto error;
142         }
143
144 #if 0
145         if (Compare(luid, GetDefaultAdapterLuid())) { // If luid that the Rift is on is not the default adapter LUID...
146                 print_error("OpenGL supports only the default graphics adapter.\n");
147                 goto error;
148         }
149 #endif
150
151         hmdDesc = ovr_GetHmdDesc(session);
152
153         memset(&layer, 0, sizeof(layer));
154         layer.Header.Type      = ovrLayerType_EyeFov;
155         layer.Header.Flags     = 0;
156
157         /* do we need this??? seems to work without */
158         if (multisampling > 1)
159                 glEnable(GL_MULTISAMPLE);
160
161         /* create render buffers */
162         for (eye = 0; eye < 2; eye++) {
163                 TextureSize[eye] = ovr_GetFovTextureSize(session, (eye == 0) ? ovrEye_Left : ovrEye_Right, hmdDesc.DefaultEyeFov[eye], 1.0);
164                 ovrTextureSwapChainDesc desc;
165                 int length, i;
166                 GLuint chainTexId;
167
168                 memset(&desc, 0, sizeof(desc));
169                 desc.Type = ovrTexture_2D;
170                 desc.ArraySize = 1;
171                 desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
172                 desc.Width = TextureSize[eye].w;
173                 desc.Height = TextureSize[eye].h;
174                 desc.MipLevels = 1;
175                 desc.SampleCount = (multisampling > 1) ? multisampling : 1;
176                 desc.StaticImage = ovrFalse;
177
178                 result = ovr_CreateTextureSwapChainGL(session, &desc, &textureSwapChain[eye]);
179                 if (OVR_FAILURE(result)) {
180                         print_error("ovr_CreateTextureSwapChainGL() failed! (error %d)\n", result);
181                         goto error;
182                 }
183
184                 ovr_GetTextureSwapChainLength(session, textureSwapChain[eye], &length);
185                 for (i = 0; i < length; i++) {
186                         ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], i, &chainTexId);
187                         glBindTexture((multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId);
188                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
189                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
190                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
191                         glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
192                 }
193
194                 glGenFramebuffers(1, &(fboId[eye]));
195
196                 eyeRenderDesc[eye] = ovr_GetRenderDesc(session, (eye == 0) ? ovrEye_Left : ovrEye_Right, hmdDesc.DefaultEyeFov[eye]);
197                 hmdToEyeViewPose[eye] = eyeRenderDesc[eye].HmdToEyePose;
198
199                 layer.ColorTexture[eye]  = textureSwapChain[eye];
200                 layer.Fov[eye]           = eyeRenderDesc[eye].Fov;
201                 layer.Viewport[eye].Pos.x = 0;
202                 layer.Viewport[eye].Pos.y = 0;
203                 layer.Viewport[eye].Size.w = TextureSize[eye].w;
204                 layer.Viewport[eye].Size.h = TextureSize[eye].h;
205         }
206
207         ovrMirrorTexture mirrorTexture = NULL;
208         ovrMirrorTextureDesc desc;
209         memset(&desc, 0, sizeof(desc));
210         desc.Width = mirror_width = TextureSize[0].w;
211         desc.Height = mirror_height = TextureSize[0].h / 2;
212         desc.Format = OVR_FORMAT_R8G8B8A8_UNORM_SRGB;
213         desc.MirrorOptions =
214                 ovrMirrorOption_PostDistortion |
215                 ovrMirrorOption_IncludeGuardian |
216                 ovrMirrorOption_IncludeNotifications |
217                 ovrMirrorOption_IncludeSystemGui;
218
219         /* Create mirror texture and an FBO used to copy mirror texture to back buffer */
220         result = ovr_CreateMirrorTextureWithOptionsGL(session, &desc, &mirrorTexture);
221         if (!OVR_SUCCESS(result)) {
222                 print_error("ovr_CreateMirrorTextureWithOptionsGL() failed! (error %d)\n", result);
223                 goto error;
224         }
225
226         /* Configure the mirror read buffer */
227         GLuint texId;
228         ovr_GetMirrorTextureBufferGL(session, mirrorTexture, &texId);
229
230         glGenFramebuffers(1, &mirrorFBO);
231         glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
232         glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texId, 0);
233         glFramebufferRenderbuffer(GL_READ_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, 0);
234
235         return 0;
236
237 error:
238         exit_ovr();
239         return -EINVAL;
240 }
241
242 void get_poses_ovr(int *button_a, int *button_b, int *button_x, int *button_y, int *button_menu, int *button_trigger, int *button_left_thumb, int *button_right_thumb, double *hand_right_x, double *hand_right_y, double *hand_right_z, double *hand_right_yaw, double *hand_right_pitch, double *hand_right_roll, double *stick_left_x, double *stick_left_y, double *stick_right_x, double *stick_right_y)
243 {       
244         ovrResult result;
245         float yaw, pitch, roll;
246         double x, y, z;
247
248         /* Get both eye poses simultaneously, with IPD offset already included. */
249         double displayMidpointSeconds = ovr_GetPredictedDisplayTime(session, frameIndex);
250         ovrTrackingState hmdState = ovr_GetTrackingState(session, displayMidpointSeconds, ovrTrue);
251         ovr_CalcEyePoses(hmdState.HeadPose.ThePose, hmdToEyeViewPose, layer.RenderPose);
252         /* Grab hand poses useful for rendering hand or controller representation */
253         handPoses[ovrHand_Left]  = hmdState.HandPoses[ovrHand_Left].ThePose;
254         handPoses[ovrHand_Right] = hmdState.HandPoses[ovrHand_Right].ThePose;
255         x = handPoses[ovrHand_Right].Position.x;
256         y = handPoses[ovrHand_Right].Position.y;
257         z = handPoses[ovrHand_Right].Position.z;
258         x += hand_x_normalize;
259         y += hand_y_normalize;
260         z += hand_z_normalize;
261         *hand_right_x = x / 0.0254;
262         *hand_right_y = y / 0.0254;
263         *hand_right_z = z / 0.0254;
264         ovrOrientation2yawpitchroll(handPoses[ovrHand_Right].Orientation, &yaw, &pitch, &roll);
265         *hand_right_yaw = yaw;
266         *hand_right_pitch = pitch;
267         *hand_right_roll = roll;
268
269         result = ovr_GetInputState(session, ovrControllerType_Touch, &inputState);
270         if (OVR_SUCCESS(result)) {
271                 if (inputState.Buttons & ovrButton_A)
272                         *button_a = 1;
273                 else
274                         *button_a = 0;
275                 if (inputState.Buttons & ovrButton_B)
276                         *button_b = 1;
277                 else
278                         *button_b = 0;
279                 if (inputState.Buttons & ovrButton_X)
280                         *button_x = 1;
281                 else
282                         *button_x = 0;
283                 if (inputState.Buttons & ovrButton_Y)
284                         *button_y = 1;
285                 else
286                         *button_y = 0;
287                 if (inputState.Buttons & ovrButton_Enter)
288                         *button_menu = 1;
289                 else
290                         *button_menu = 0;
291                 if (inputState.Buttons & ovrButton_LThumb)
292                         *button_left_thumb = 1;
293                 else
294                         *button_left_thumb = 0;
295                 if (inputState.Buttons & ovrButton_RThumb)
296                         *button_right_thumb = 1;
297                 else
298                         *button_right_thumb = 0;
299                 if (inputState.IndexTrigger[ovrHand_Right] >= 0.8)
300                         *button_trigger = 1;
301                 else
302                         *button_trigger = 0;
303                 *stick_left_x = inputState.Thumbstick[ovrHand_Left].x;
304                 *stick_left_y = inputState.Thumbstick[ovrHand_Left].y;
305                 *stick_right_x = inputState.Thumbstick[ovrHand_Right].x;
306                 *stick_right_y = inputState.Thumbstick[ovrHand_Right].y;
307         }
308 }
309
310 void begin_render_ovr(void)
311 {
312         ovrResult result;
313
314         result = ovr_WaitToBeginFrame(session, frameIndex);
315         if (!OVR_SUCCESS(result))
316                 print_info("Failed to wait to begin frame (error %d)\n", result);
317         result = ovr_BeginFrame(session, frameIndex);
318         if (!OVR_SUCCESS(result))
319                 print_info("Failed to begin frame (error %d)\n", result);
320 }
321
322 void begin_render_ovr_eye(int eye, double *camera_x, double *camera_y, double *camera_z)
323 {
324         int curIndex;
325         GLuint chainTexId;
326         float yaw, pitch, roll;
327         double x, y, z;
328
329         /* set render surface */
330         ovr_GetTextureSwapChainCurrentIndex(session, textureSwapChain[eye], &curIndex);
331         ovr_GetTextureSwapChainBufferGL(session, textureSwapChain[eye], curIndex, &chainTexId);
332         glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]);
333         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, chainTexId, 0);
334
335         glViewport(0, 0, TextureSize[eye].w, TextureSize[eye].h);
336         glMatrixMode(GL_PROJECTION);
337         glLoadIdentity();
338         glFrustum(
339                 -layer.Fov[eye].LeftTan,
340                 layer.Fov[eye].RightTan,
341                 layer.Fov[eye].UpTan,
342                 -layer.Fov[eye].DownTan,
343                 1.0, 5000000000.0);
344
345         ovrOrientation2yawpitchroll(layer.RenderPose[eye].Orientation, &yaw, &pitch, &roll);
346         x = layer.RenderPose[eye].Position.x;
347         y = layer.RenderPose[eye].Position.y;
348         z = layer.RenderPose[eye].Position.z;
349
350         /* normalize height to game's observer, if requrested by user */
351         observer_x = x;
352         x += observer_x_normalize;
353         observer_y = y;
354         y += observer_y_normalize;
355         observer_z = z;
356         z += observer_z_normalize;
357
358         glRotatef(-roll / M_PI * 180.0,0,0,1);
359         glRotatef(-pitch / M_PI * 180.0,1,0,0);
360         glRotatef(-yaw / M_PI * 180.0,0,1,0);
361
362         *camera_x = x / 0.0254;
363         *camera_y = y / 0.0254;
364         *camera_z = z / 0.0254;
365         glTranslated(-(*camera_x), -(*camera_y), -(*camera_z)); /* convert to inch */
366
367         glMatrixMode(GL_MODELVIEW);
368
369         /* DO NOT ENABLE, since our mercenary-textures are not SRGB */
370         //glEnable(GL_FRAMEBUFFER_SRGB);
371
372 }
373
374 void end_render_ovr_eye(int eye)
375 {
376         // unset render surface
377         glBindFramebuffer(GL_FRAMEBUFFER, fboId[eye]);
378         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0);
379         glFramebufferTexture2D(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, (multisampling > 1) ? GL_TEXTURE_2D_MULTISAMPLE : GL_TEXTURE_2D, 0, 0);
380         glBindFramebuffer(GL_FRAMEBUFFER, 0);
381
382         // Commit the changes to the texture swap chain
383         ovr_CommitTextureSwapChain(session, textureSwapChain[eye]);
384 }
385
386 void end_render_ovr(void)
387 {
388         ovrResult result;
389
390         const ovrLayerHeader *layers[] = { &layer.Header };
391         result = ovr_EndFrame(session, frameIndex, NULL, layers, 1);
392         if (!OVR_SUCCESS(result))
393                 print_info("Failed to submit frame (error %d)\n", result);
394         frameIndex++;
395 }
396
397 void render_mirror_ovr(int view_width, int view_height)
398 {
399         int view_x = 0, view_y = 0;
400         int new_width, new_height;
401
402         /* avoid division by zero, if one dimension is too small */
403         if (view_width < 1 || view_height < 1)
404                 return;
405
406         /* calculate a viewport that has apect of TextureSize */
407         if (view_height * mirror_width > view_width * mirror_height) {
408                 new_height = view_width * mirror_height / mirror_width;
409                 view_y = view_y + view_height / 2 - new_height / 2;
410                 view_height = new_height;
411         } else if (view_height * mirror_width < view_width * mirror_height) {
412                 new_width = view_height * mirror_width / mirror_height;
413                 view_x = view_x + view_width / 2 - new_width / 2;
414                 view_width = new_width;
415         }
416
417         /* avoid views that are too small */
418         if (view_width < 1 || view_height < 1)
419                 return;
420
421         glBindFramebuffer(GL_FRAMEBUFFER, 0);
422
423         glClearColor(0.0, 0.0, 0.0, 1.0);
424         glClear(GL_COLOR_BUFFER_BIT);
425
426         /* Blit mirror texture to back buffer */
427         glBindFramebuffer(GL_READ_FRAMEBUFFER, mirrorFBO);
428         glBindFramebuffer(GL_DRAW_FRAMEBUFFER, 0);
429         glBlitFramebuffer(0, mirror_height, mirror_width, 0,
430                 view_x, view_y, view_x + view_width, view_y + view_height,
431                 GL_COLOR_BUFFER_BIT, GL_NEAREST);
432         glBindFramebuffer(GL_READ_FRAMEBUFFER, 0);
433 }
434
435 void normalize_observer_ovr(void)
436 {
437         observer_x_normalize = -observer_x;
438         observer_y_normalize = -observer_y;
439         observer_z_normalize = -observer_z;
440         hand_x_normalize = -observer_x;
441         hand_y_normalize = -observer_y;
442         hand_z_normalize = -observer_z;
443 }
444
445 void exit_ovr(void)
446 {
447         int eye;
448
449         /* destroy render buffers */
450         for (eye = 0; eye < 2; eye++) {
451                 if (textureSwapChain[eye]) {
452                         ovr_DestroyTextureSwapChain(session, textureSwapChain[eye]);
453                         textureSwapChain[eye] = NULL;
454                 }
455                 if (fboId[eye]) {
456                         glDeleteFramebuffers(1, &fboId[eye]);
457                         fboId[eye] = 0;
458                 }
459         }
460         if (mirrorFBO) {
461                 glDeleteFramebuffers(1, &mirrorFBO);
462                 mirrorFBO = 0;
463         }
464
465         if (session) {
466                 ovr_Destroy(session);
467                 session = NULL;
468         }
469         if (ovr_initialized) {
470                 ovr_Shutdown();
471                 ovr_initialized = 0;
472         }
473 }
474