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