vrchess

view src/vr/vr_libovr.c @ 10:e3f0ca1d008a

added preliminary OpenHMD module
author John Tsiombikas <nuclear@member.fsf.org>
date Fri, 22 Aug 2014 20:11:15 +0300
parents c2eecf764daa
children 5dc4e2b8f6f5
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 /* just dropping the prototype here to avoid including CAPI_HSWDisplay.h */
17 OVR_EXPORT void ovrhmd_EnableHSWDisplaySDKRender(ovrHmd hmd, ovrBool enabled);
19 static ovrHmd hmd;
20 static void *optdb;
21 static ovrEyeRenderDesc eye_render_desc[2];
22 static ovrSizei eye_res[2];
23 static ovrGLTexture eye_tex[2];
24 static ovrFovPort eye_fov[2];
25 static ovrPosef pose[2];
26 static int deferred_init_done;
28 static int init(void)
29 {
30 int i, num_hmds;
32 if(!ovr_Initialize()) {
33 return -1;
34 }
35 printf("initialized LibOVR %s\n", ovr_GetVersionString());
37 if(!(num_hmds = ovrHmd_Detect())) {
38 ovr_Shutdown();
39 return -1;
40 }
41 printf("%d Oculus HMD(s) found\n", num_hmds);
43 hmd = 0;
44 for(i=0; i<num_hmds; i++) {
45 ovrHmd h;
46 if(!(h = ovrHmd_Create(i))) {
47 break;
48 }
49 printf(" [%d]: %s - %s\n", h->Manufacturer, h->ProductName);
51 if(!hmd) {
52 hmd = h;
53 } else {
54 ovrHmd_Destroy(h);
55 }
56 }
58 if(!hmd) {
59 fprintf(stderr, "failed to initialize any Oculus HMDs\n");
60 return -1;
61 }
63 eye_fov[0] = hmd->DefaultEyeFov[0];
64 eye_fov[1] = hmd->DefaultEyeFov[1];
66 eye_res[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, eye_fov[0], 1.0);
67 eye_res[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, eye_fov[1], 1.0);
69 /* create the options database */
70 if((optdb = create_options())) {
71 set_option_int(optdb, VR_OPT_DISPLAY_WIDTH, hmd->Resolution.w);
72 set_option_int(optdb, VR_OPT_DISPLAY_HEIGHT, hmd->Resolution.h);
73 set_option_int(optdb, VR_OPT_LEYE_XRES, eye_res[0].w);
74 set_option_int(optdb, VR_OPT_LEYE_YRES, eye_res[0].h);
75 set_option_int(optdb, VR_OPT_REYE_XRES, eye_res[1].w);
76 set_option_int(optdb, VR_OPT_REYE_YRES, eye_res[1].h);
77 set_option_float(optdb, VR_OPT_EYE_HEIGHT, ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, OVR_DEFAULT_EYE_HEIGHT));
78 set_option_float(optdb, VR_OPT_IPD, ovrHmd_GetFloat(hmd, OVR_KEY_IPD, OVR_DEFAULT_IPD));
79 }
81 deferred_init_done = 0;
82 return 0;
83 }
85 static void deferred_init(void)
86 {
87 union ovrGLConfig glcfg;
88 unsigned int dcaps;
89 void *win = 0;
91 deferred_init_done = 1;
93 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0);
95 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL;
96 glcfg.OGL.Header.RTSize = hmd->Resolution;
97 glcfg.OGL.Header.Multisample = 1;
98 #ifdef WIN32
99 win = GetActiveWindow();
100 glcfg.OGL.Window = win;
101 glcfg.OGL.DC = wglGetCurrentDC();
102 assert(glcfg.OGL.Window);
103 assert(glcfg.OGL.DC);
104 #endif
106 ovrHmd_AttachToWindow(hmd, win, 0, 0);
107 /*ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction);*/
109 dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette;/* | ovrDistortionCap_TimeWarp;// |
110 ovrDistortionCap_Overdrive; */
112 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, eye_fov, eye_render_desc)) {
113 fprintf(stderr, "failed to configure LibOVR distortion renderer\n");
114 }
116 /* ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); */
117 }
119 static void cleanup(void)
120 {
121 if(hmd) {
122 ovrHmd_Destroy(hmd);
123 ovr_Shutdown();
124 }
125 }
127 static int set_option(const char *opt, enum opt_type type, void *valp)
128 {
129 switch(type) {
130 case OTYPE_INT:
131 set_option_int(optdb, opt, *(int*)valp);
132 break;
134 case OTYPE_FLOAT:
135 set_option_float(optdb, opt, *(float*)valp);
136 break;
137 }
138 return 0;
139 }
141 static int get_option(const char *opt, enum opt_type type, void *valp)
142 {
143 switch(type) {
144 case OTYPE_INT:
145 return get_option_int(optdb, opt, valp);
146 case OTYPE_FLOAT:
147 return get_option_float(optdb, opt, valp);
148 }
149 return -1;
150 }
152 static int translation(int eye, float *vec)
153 {
154 if(!hmd) {
155 vec[0] = vec[1] = vec[2] = 0;
156 return -1;
157 }
159 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
160 vec[0] = pose[eye].Position.x;
161 vec[1] = pose[eye].Position.y;
162 vec[2] = pose[eye].Position.z;
163 return 0;
164 }
166 static int rotation(int eye, float *quat)
167 {
168 if(!hmd) {
169 quat[0] = quat[1] = quat[2] = 0.0f;
170 quat[3] = 1.0f;
171 return -1;
172 }
174 pose[eye] = ovrHmd_GetEyePose(hmd, eye == VR_EYE_LEFT ? ovrEye_Left : ovrEye_Right);
175 quat[0] = pose[eye].Orientation.x;
176 quat[1] = pose[eye].Orientation.y;
177 quat[2] = pose[eye].Orientation.z;
178 quat[3] = pose[eye].Orientation.w;
179 return 0;
180 }
182 static const float idmat[] = {1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1};
184 static void proj_matrix(int eye, float znear, float zfar, float *mat)
185 {
186 ovrMatrix4f vmat;
188 if(!hmd) {
189 memcpy(mat, idmat, sizeof idmat);
190 return;
191 }
193 vmat = ovrMatrix4f_Projection(eye_render_desc[eye].Fov, znear, zfar, 1);
194 memcpy(mat, vmat.M[0], 16 * sizeof(float));
195 }
197 static int new_frame = 1;
199 static void begin(int eye)
200 {
201 if(!hmd) return;
203 if(!deferred_init_done) {
204 deferred_init();
205 }
207 if(new_frame) {
208 ovrHmd_BeginFrame(hmd, 0);
209 new_frame = 0;
210 }
211 }
213 static int present(void)
214 {
215 if(!hmd) return 0;
217 glDisable(GL_DEPTH_TEST);
219 ovrHmd_EndFrame(hmd, pose, &eye_tex[0].Texture);
220 new_frame = 1;
222 return 1;
223 }
225 static void set_eye_texture(int eye, unsigned int tex, float umin, float vmin, float umax, float vmax)
226 {
227 ovrSizei texsz;
228 ovrRecti rect;
230 glBindTexture(GL_TEXTURE_2D, tex);
231 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &texsz.w);
232 glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &texsz.h);
234 rect.Pos.x = (int)(umin * texsz.w);
235 rect.Pos.y = (int)(vmin * texsz.h);
236 rect.Size.w = (int)((umax - umin) * texsz.w);
237 rect.Size.h = (int)((vmax - vmin) * texsz.h);
239 printf("eye %d texture: %u [%g, %g] -> [%g, %g]\n", eye, tex, umin, vmin, umax, vmax);
240 printf(" pixels [%d, %d] -> [%d, %d]\n", rect.Pos.x, rect.Pos.y, rect.Pos.x + rect.Size.w, rect.Pos.y + rect.Size.h);
242 eye_tex[eye].OGL.Header.API = ovrRenderAPI_OpenGL;
243 eye_tex[eye].OGL.Header.TextureSize = texsz;
244 eye_tex[eye].OGL.Header.RenderViewport = rect;
245 eye_tex[eye].OGL.TexId = tex;
246 }
248 static void recenter(void)
249 {
250 if(hmd) {
251 ovrHmd_RecenterPose(hmd);
252 }
253 }
255 struct vr_module *vr_module_libovr(void)
256 {
257 static struct vr_module m;
259 if(!m.init) {
260 m.name = "libovr";
261 m.init = init;
262 m.cleanup = cleanup;
263 m.set_option = set_option;
264 m.get_option = get_option;
265 m.translation = translation;
266 m.rotation = rotation;
267 m.proj_matrix = proj_matrix;
268 m.begin = begin;
269 m.present = present;
270 m.set_eye_texture = set_eye_texture;
271 m.recenter = recenter;
272 }
273 return &m;
274 }
276 #else /* no libovr */
278 static int init(void)
279 {
280 return -1;
281 }
283 struct vr_module *vr_module_libovr(void)
284 {
285 static struct vr_module m;
287 if(!m.init) {
288 m.name = "libovr";
289 m.init = init;
290 }
291 return &m;
292 }
294 #endif /* USE_LIBOVR */