libgoatvr

view src/vr_libovr.c @ 5:e63cb28fc644

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