libgoatvr

view src/vr_libovr.c @ 9:d12592558809

build on macosx
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 20 Sep 2014 16:52:42 +0300
parents 6896f9cf9621
children 34d4643d61f9
line source
1 #ifdef WIN32
2 #define OVR_OS_WIN32
3 #endif
4 #ifdef __APPLE__
5 #define OVR_OS_MAC
6 #endif
8 #include "vr_impl.h"
10 #ifdef USE_LIBOVR
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <string.h>
14 #include <assert.h>
15 #include "opt.h"
17 #include <OVR_CAPI.h>
18 #include <OVR_CAPI_GL.h>
20 #define DISABLE_RETARDED_HEALTH_WARNING
22 /* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */
23 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled);
25 static ovrHmd hmd;
26 static void *optdb;
27 static ovrEyeRenderDesc eye_render_desc[2];
28 static ovrSizei eye_res[2];
29 static ovrGLTexture eye_tex[2];
30 static ovrFovPort eye_fov[2];
31 static ovrPosef pose[2];
32 static int deferred_init_done;
34 static int init(void)
35 {
36 int i, num_hmds;
37 int use_fake = 0;
39 if(!ovr_Initialize()) {
40 return -1;
41 }
42 printf("initialized LibOVR %s\n", ovr_GetVersionString());
44 if(!(num_hmds = ovrHmd_Detect())) {
45 if(getenv("VR_LIBOVR_FAKE")) {
46 use_fake = 1;
47 num_hmds = 1;
48 } else {
49 ovr_Shutdown();
50 return -1;
51 }
52 }
53 printf("%d Oculus HMD(s) found\n", num_hmds);
55 hmd = 0;
56 for(i=0; i<num_hmds; i++) {
57 ovrHmd h = use_fake ? ovrHmd_CreateDebug(ovrHmd_DK2) : ovrHmd_Create(i);
58 if(!h) {
59 break;
60 }
61 printf(" [%d]: %s - %s\n", i, h->Manufacturer, h->ProductName);
63 if(!hmd) {
64 hmd = h;
65 } else {
66 ovrHmd_Destroy(h);
67 }
68 }
70 if(!hmd) {
71 fprintf(stderr, "failed to initialize any Oculus HMDs\n");
72 return -1;
73 }
75 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0);
77 eye_fov[0] = hmd->DefaultEyeFov[0];
78 eye_fov[1] = hmd->DefaultEyeFov[1];
80 eye_res[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, eye_fov[0], 1.0);
81 eye_res[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, eye_fov[1], 1.0);
83 /* create the options database */
84 if((optdb = create_options())) {
85 set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, hmd->Resolution.w);
86 set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, hmd->Resolution.h);
87 set_option_int(optdb, VR_OPT_LEYE_XRES, eye_res[0].w);
88 set_option_int(optdb, VR_OPT_LEYE_YRES, eye_res[0].h);
89 set_option_int(optdb, VR_OPT_REYE_XRES, eye_res[1].w);
90 set_option_int(optdb, VR_OPT_REYE_YRES, eye_res[1].h);
91 set_option_float(optdb, VR_OPT_EYE_HEIGHT, ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT));
92 set_option_float(optdb, VR_OPT_IPD, ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD));
93 set_option_int(optdb, VR_OPT_WIN_XOFFS, hmd->WindowsPos.x);
94 set_option_int(optdb, VR_OPT_WIN_YOFFS, hmd->WindowsPos.y);
95 }
97 deferred_init_done = 0;
98 return 0;
99 }
101 static void deferred_init(void)
102 {
103 union ovrGLConfig glcfg;
104 unsigned int dcaps;
105 void *win = 0;
107 deferred_init_done = 1;
109 memset(&glcfg, 0, sizeof glcfg);
110 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
111 glcfg.OGL.Header.RTSize = hmd->Resolution;
112 glcfg.OGL.Header.Multisample = 1;
113 #ifdef WIN32
114 win = GetActiveWindow();
115 /*glcfg.OGL.Window = win;
116 glcfg.OGL.DC = wglGetCurrentDC();
117 assert(glcfg.OGL.Window);
118 assert(glcfg.OGL.DC);*/
119 #endif
121 if(!(hmd->HmdCaps & ovrHmdCap_ExtendDesktop)) {
122 ovrHmd_AttachToWindow(hmd, win, 0, 0);
123 printf("running in \"direct-to-rift\" mode\n");
124 } else {
125 printf("running in \"extended desktop\" mode\n");
126 }
127 ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);
129 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp |
130 ovrDistortionCap_Overdrive | ovrDistortionCap_NoRestore;
132 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) {
133 fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
134 }
136 #ifdef DISABLE_RETARDED_HEALTH_WARNING
137 ovrhmd_EnableHSWDisplaySDKRender(hmd, 0);
138 #endif
139 }
141 static void cleanup(void)
142 {
143 if(hmd) {
144 ovrHmd_Destroy(hmd);
145 ovr_Shutdown();
146 }
147 destroy_options(optdb);
148 }
150 static int set_option(const char *opt, enum opt_type type, void *valp)
151 {
152 switch(type) {
153 case OTYPE_INT:
154 set_option_int(optdb, opt, *(int*)valp);
155 break;
157 case OTYPE_FLOAT:
158 set_option_float(optdb, opt, *(float*)valp);
159 break;
160 }
161 return 0;
162 }
164 static int get_option(const char *opt, enum opt_type type, void *valp)
165 {
166 switch(type) {
167 case OTYPE_INT:
168 return get_option_int(optdb, opt, valp);
169 case OTYPE_FLOAT:
170 return get_option_float(optdb, opt, valp);
171 }
172 return -1;
173 }
175 static void translation(int eye, float *vec)
176 {
177 if(!hmd) {
178 vec[0] = vec[1] = vec[2] = 0;
179 return;
180 }
182 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
183 vec[0] = pose[eye].Position.x + eye_render_desc[eye].ViewAdjust.x;
184 vec[1] = pose[eye].Position.y + eye_render_desc[eye].ViewAdjust.y;
185 vec[2] = pose[eye].Position.z + eye_render_desc[eye].ViewAdjust.z;
186 }
188 static void rotation(int eye, float *quat)
189 {
190 if(!hmd) {
191 quat[0] = quat[1] = quat[2] = 0.0f;
192 quat[3] = 1.0f;
193 return;
194 }
196 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
197 quat[0] = pose[eye].Orientation.x;
198 quat[1] = pose[eye].Orientation.y;
199 quat[2] = pose[eye].Orientation.z;
200 quat[3] = pose[eye].Orientation.w;
201 }
203 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
205 static void proj_matrix(int eye, float znear, float zfar, float *mat)
206 {
207 int i, j;
208 ovrMatrix4f vmat;
210 if(!hmd) {
211 memcpy(mat, idmat, sizeof idmat);
212 return;
213 }
215 vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1);
217 for(i=0; i<4; i++) {
218 for(j=0; j<4; j++) {
219 *mat++ = vmat.M[j][i];
220 }
221 }
222 }
224 static int new_frame = 1;
226 static void begin(int eye)
227 {
228 if(!hmd) return;
230 if(!deferred_init_done) {
231 deferred_init();
232 }
234 if(new_frame) {
235 ovrHmd_BeginFrame(hmd, 0);
236 new_frame = 0;
237 }
238 }
240 static int present(void)
241 {
242 if(!hmd) return 0;
244 ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
245 new_frame = 1;
247 return 1;
248 }
250 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
251 {
252 ovrSizei texsz;
253 ovrRecti rect;
255 glBindTexture(GL_TEXTURE_2D, tex);
256 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w);
257 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h);
259 rect.Pos.x = (int)(umin * texsz.w);
260 rect.Pos.y = (int)((vmin + 1.0 - vmax) * texsz.h);
261 rect.Size.w = (int)((umax - umin) * texsz.w);
262 rect.Size.h = (int)((vmax - vmin) * texsz.h);
264 eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
265 eye_tex[eye].OGL.Header.TextureSize = texsz;
266 eye_tex[eye].OGL.Header.RenderViewport = rect;
267 eye_tex[eye].OGL.TexId = tex;
268 }
270 static void recenter(void)
271 {
272 if(hmd) {
273 ovrHmd_RecenterPose(hmd);
274 }
275 }
277 struct vr_module *vr_module_libovr(void)
278 {
279 static struct vr_module m;
281 if(!m.init) {
282 m.name = "libovr";
283 m.init = init;
284 m.cleanup = cleanup;
285 m.set_option = set_option;
286 m.get_option = get_option;
287 m.translation = translation;
288 m.rotation = rotation;
289 m.proj_matrix = proj_matrix;
290 m.begin = begin;
291 m.present = present;
292 m.set_eye_texture = set_eye_texture;
293 m.recenter = recenter;
294 }
295 return &m;
296 }
298 #else /* no libovr */
300 static int init(void)
301 {
302 return -1;
303 }
305 struct vr_module *vr_module_libovr(void)
306 {
307 static struct vr_module m;
309 if(!m.init) {
310 m.name = "libovr";
311 m.init = init;
312 }
313 return &m;
314 }
316 #endif /* USE_LIBOVR */