oculus1

view src/vr.cc @ 13:464e1d135d68

hurraaaay!
author John Tsiombikas <nuclear@member.fsf.org>
date Sat, 21 Sep 2013 03:00:47 +0300
parents d797639e0234
children cceffea995a4
line source
1 #include <stdio.h>
2 #include <GL/glew.h>
3 #include "vr.h"
4 #include "vr_impl.h"
6 static const char *sdr_src =
7 "uniform sampler2D tex;\n"
8 "uniform vec2 lens_center;\n"
9 "uniform vec2 scr_center;\n"
10 "uniform vec2 scale;\n"
11 "uniform vec2 scale_in;\n"
12 "uniform vec4 warp_param;\n"
13 "\n"
14 "vec2 warp(in vec2 pt, out float dbgrad)\n"
15 "{\n"
16 " vec2 theta = (pt - lens_center) * scale_in;\n"
17 " float rsq = dot(theta, theta);\n"
18 " vec2 rvec = theta * (warp_param.x + \n"
19 " warp_param.y * rsq +\n"
20 " warp_param.z * rsq * rsq +\n"
21 " warp_param.w * rsq * rsq * rsq);\n"
22 " dbgrad = length(theta);\n"
23 " return lens_center + scale * rvec;\n"
24 "}\n"
25 "\n"
26 "void main()\n"
27 "{\n"
28 " float dbgrad;\n"
29 " vec2 tc = warp(gl_TexCoord[0].xy, dbgrad);\n"
30 " gl_FragColor.rgb = texture2D(tex, tc).rgb;\n"
31 " gl_FragColor.rgb += mix(vec3(1.0, 1.0, 0.0), vec3(0.0), smoothstep(0.01, 0.05, dbgrad));\n"
32 " gl_FragColor.a = 1.0;\n"
33 "}\n";
35 static bool init_ovr();
36 static bool init_sdr();
38 VRContext vr_ctx;
39 static unsigned int sdrprog;
41 extern "C" int vr_init(enum vr_init_mode mode)
42 {
43 glewInit();
45 if(!init_ovr()) {
46 return -1;
47 }
49 if(!init_sdr()) {
50 return -1;
51 }
53 return 0;
54 }
56 extern "C" void vr_shutdown(void)
57 {
58 //System::Destroy();
59 }
61 static bool init_ovr()
62 {
63 LogMaskConstants log_level = LogMask_All;
64 // initialize Oculus SDK
65 const char *logenv = getenv("VR_LOGLEVEL");
66 if(logenv) {
67 switch(atoi(logenv)) {
68 case 0:
69 log_level = LogMask_None;
70 break;
71 case 1:
72 log_level = LogMask_Regular;
73 break;
74 case 2:
75 default:
76 log_level = LogMask_All;
77 break;
78 }
79 }
81 System::Init(Log::ConfigureDefaultLog(log_level));
82 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
83 fprintf(stderr, "failed to create OVR device manager\n");
84 return false;
85 }
87 // create the display device
88 HMDInfo info;
89 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
90 fprintf(stderr, "no oculus rift devices found\n");
91 } else {
92 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
93 printf("oculus device info:\n");
94 printf(" name: %s\n", info.DisplayDeviceName);
95 printf(" ipd: %f\n", info.InterpupillaryDistance);
96 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
97 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
98 }
100 // calculate and store viewing parameters
101 vr_ctx.info.width = info.HResolution;
102 vr_ctx.info.height = info.VResolution;
103 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
105 vr_ctx.info.ipd = info.InterpupillaryDistance;
106 for(int i=0; i<4; i++) {
107 vr_ctx.info.distort[i] = info.DistortionK[i];
108 }
110 vr_ctx.info.scale = 1.0;
112 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
113 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
115 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
117 // calculate center of projection shift to match the lens positions
118 float center_dist_meters = info.HScreenSize * 0.25;
119 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
120 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
121 }
123 // get the sensor device
124 if(vr_ctx.ovr_hmd_dev) {
125 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
126 fprintf(stderr, "failed to get oculus sensor device\n");
127 }
128 } else {
129 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
130 fprintf(stderr, "failed to get oculus sensor device\n");
131 }
132 }
134 if(vr_ctx.ovr_sensor_dev) {
135 SensorInfo sinfo;
136 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
137 printf("oculus sensor device info:\n");
138 printf(" name: %s\n", sinfo.ProductName);
139 }
141 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
142 }
143 return true;
144 }
146 #define EXTERNAL_SHADER
148 static bool init_sdr()
149 {
150 int status;
152 #ifdef EXTERNAL_SHADER
153 FILE *fp = fopen("sdr.glsl", "rb");
154 if(!fp) {
155 perror("failed to load sdr.glsl");
156 return false;
157 }
158 fseek(fp, 0, SEEK_END);
159 long sz = ftell(fp);
160 rewind(fp);
162 char *buf = (char*)alloca(sz + 1);
163 fread(buf, 1, sz, fp);
164 buf[sz] = 0;
165 sdr_src = buf;
167 fclose(fp);
168 #endif
170 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
171 glShaderSource(sdr, 1, &sdr_src, 0);
172 glCompileShader(sdr);
173 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
174 if(!status) {
175 fprintf(stderr, "failed to compile distortion shader\n");
176 return false;
177 }
179 sdrprog = glCreateProgram();
180 glAttachShader(sdrprog, sdr);
181 glLinkProgram(sdrprog);
182 if(!status) {
183 fprintf(stderr, "failed to link distortion shader program\n");
184 glDeleteShader(sdr);
185 return false;
186 }
188 int loc;
190 glUseProgram(sdrprog);
192 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
193 glUniform1i(loc, 0);
194 }
195 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
196 glUniform1f(loc, 0);
197 }
198 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
199 glUniform2f(loc, 0, 0);
200 }
201 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
202 glUniform1f(loc, vr_ctx.info.scale);
203 }
204 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
205 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
206 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
207 }
208 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
209 glUniform2f(loc, 1, 1);
210 }
211 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
212 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
213 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
214 }
216 return true;
217 }
219 extern "C" int vr_get_width(void)
220 {
221 return vr_ctx.info.width;
222 }
224 extern "C" int vr_get_height(void)
225 {
226 return vr_ctx.info.height;
227 }
229 extern "C" float vr_get_fov(void)
230 {
231 return vr_ctx.info.fov;
232 }
234 extern "C" float vr_get_aspect(void)
235 {
236 return vr_ctx.info.aspect;
237 }
239 extern "C" void vr_set_eyedist(float ipd)
240 {
241 vr_ctx.info.ipd = ipd;
242 }
244 extern "C" float vr_get_eyedist(void)
245 {
246 return vr_ctx.info.ipd;
247 }
249 extern "C" void vr_set_distort(const float *coef)
250 {
251 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
252 }
254 extern "C" void vr_get_distort(float *coef)
255 {
256 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
257 }
259 extern "C" void vr_set_prediction_sec(float dt)
260 {
261 vr_ctx.ovr_sfusion.SetPrediction(dt);
262 }
264 extern "C" float vr_get_prediction_sec(void)
265 {
266 return vr_ctx.ovr_sfusion.GetPredictionDelta();
267 }
269 extern "C" void vr_get_view_matrix(float *res, int eye)
270 {
271 // TODO
272 }
274 extern "C" void vr_get_proj_matrix(float *res, int eye)
275 {
276 static float eye_scale[] = {0.0, 1.0, -1.0};
278 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
279 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
281 memcpy(res, proj.M[0], 16 * sizeof(float));
282 }
284 extern "C" void vr_get_translation(float *offs)
285 {
286 // current oculus devkit doesn't do translation
287 offs[0] = offs[1] = offs[2] = 0.0f;
288 }
290 extern "C" void vr_get_rotation(float *quat)
291 {
292 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
293 quat[0] = oq.x;
294 quat[1] = oq.y;
295 quat[2] = oq.z;
296 quat[3] = oq.w;
297 }
299 extern "C" void vr_get_rotation_euler(float *euler)
300 {
301 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
302 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
303 }
305 extern "C" void vr_draw_eye(unsigned int tex, int eye)
306 {
307 static const float rects[3][4] = {
308 {-1, -1, 1, 1},
309 {-1, -1, 0, 1},
310 {0, -1, 1, 1}
311 };
312 static const float offs_scale[3] = {0.0, -1.0, 1.0};
314 glPushAttrib(GL_ENABLE_BIT);
315 glDisable(GL_DEPTH_TEST);
316 glDisable(GL_LIGHTING);
317 glEnable(GL_TEXTURE_2D);
319 glMatrixMode(GL_MODELVIEW);
320 glPushMatrix();
321 glLoadIdentity();
323 glMatrixMode(GL_PROJECTION);
324 glPushMatrix();
325 glLoadIdentity();
327 glUseProgram(sdrprog);
329 if(sdrprog) {
330 int loc;
331 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
332 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
333 glUniform1f(loc, offset);
334 }
335 }
337 glBindTexture(GL_TEXTURE_2D, tex);
338 glBegin(GL_QUADS);
339 glColor4f(1, 1, 1, 1);
340 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
341 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
342 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
343 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
344 glEnd();
346 glUseProgram(0);
348 glPopMatrix();
349 glMatrixMode(GL_MODELVIEW);
350 glPopMatrix();
352 glPopAttrib();
353 }