goat3dgfx
view src/vr/vr.cc @ 13:25bf39105c82
lalal
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Wed, 27 Nov 2013 08:08:59 +0200 |
parents | |
children | 7d6b667821cf |
line source
1 #include <stdio.h>
2 #include <GL/glew.h>
3 #include "vr.h"
4 #include "vr_impl.h"
5 #include "vr_sdr.h"
7 #ifndef WIN32
8 #include <alloca.h>
9 #else
10 #include <malloc.h>
11 #endif
13 static void init_ctx();
14 static bool init_ovr();
15 static bool init_sdr();
17 VRContext vr_ctx;
18 static unsigned int sdrprog;
20 extern "C" int vr_init(enum vr_init_mode mode)
21 {
22 init_ctx();
24 if(!init_ovr()) {
25 return -1;
26 }
28 if(!init_sdr()) {
29 return -1;
30 }
32 return 0;
33 }
35 extern "C" void vr_shutdown(void)
36 {
37 delete [] vr_ctx.info.display;
38 //System::Destroy();
39 }
41 static void init_ctx()
42 {
43 vr_ctx.info.width = 1280;
44 vr_ctx.info.height = 800;
45 vr_ctx.info.fov = M_PI / 2.0;
46 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
47 vr_ctx.info.ipd = 0.035;
48 vr_ctx.info.scale = 1.0;
49 }
51 static bool init_ovr()
52 {
53 LogMaskConstants log_level = LogMask_All;
54 // initialize Oculus SDK
55 const char *logenv = getenv("VR_LOGLEVEL");
56 if(logenv) {
57 switch(atoi(logenv)) {
58 case 0:
59 log_level = LogMask_None;
60 break;
61 case 1:
62 log_level = LogMask_Regular;
63 break;
64 case 2:
65 default:
66 log_level = LogMask_All;
67 break;
68 }
69 }
71 System::Init(Log::ConfigureDefaultLog(log_level));
72 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
73 fprintf(stderr, "failed to create OVR device manager\n");
74 return false;
75 }
77 // create the display device
78 HMDInfo info;
79 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
80 fprintf(stderr, "no oculus rift devices found\n");
81 } else {
82 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
83 printf("oculus device info:\n");
84 printf(" name: %s\n", info.DisplayDeviceName);
85 printf(" ipd: %f\n", info.InterpupillaryDistance);
86 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
87 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
88 }
90 // calculate and store viewing parameters
91 vr_ctx.info.width = info.HResolution;
92 vr_ctx.info.height = info.VResolution;
93 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
95 vr_ctx.info.ipd = info.InterpupillaryDistance;
96 for(int i=0; i<4; i++) {
97 vr_ctx.info.distort[i] = info.DistortionK[i];
98 }
100 Util::Render::StereoConfig stereohelp;
101 stereohelp.SetFullViewport(Util::Render::Viewport(0, 0, vr_ctx.info.width, vr_ctx.info.height));
102 stereohelp.SetStereoMode(Util::Render::Stereo_LeftRight_Multipass);
103 stereohelp.SetHMDInfo(info);
104 stereohelp.SetDistortionFitPointVP(-1.0, 0.0);
106 vr_ctx.info.scale = stereohelp.GetDistortionScale();
108 float vhalfsz = vr_ctx.info.scale * info.VScreenSize * 0.5;
109 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
111 vr_ctx.info.lens_center_offset = 0.5 - info.LensSeparationDistance / info.HScreenSize;
113 // calculate center of projection shift to match the lens positions
114 float center_dist_meters = info.HScreenSize * 0.25;
115 float proj_shift = center_dist_meters - info.LensSeparationDistance * 0.5;
116 vr_ctx.info.proj_center_offset = 4.0 * proj_shift / info.HScreenSize;
118 // grab the display info
119 vr_ctx.info.display = new char[strlen(info.DisplayDeviceName) + 1];
120 strcpy(vr_ctx.info.display, info.DisplayDeviceName);
122 vr_ctx.info.display_xoffs = info.DesktopX;
123 vr_ctx.info.display_yoffs = info.DesktopY;
125 printf("display: \"%s\" offset: %+d %+d\n", vr_ctx.info.display,
126 vr_ctx.info.display_xoffs, vr_ctx.info.display_yoffs);
127 }
129 // get the sensor device
130 if(vr_ctx.ovr_hmd_dev) {
131 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
132 fprintf(stderr, "failed to get oculus sensor device\n");
133 }
134 } else {
135 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
136 fprintf(stderr, "failed to get oculus sensor device\n");
137 }
138 }
140 if(vr_ctx.ovr_sensor_dev) {
141 SensorInfo sinfo;
142 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
143 printf("oculus sensor device info:\n");
144 printf(" name: %s\n", sinfo.ProductName);
145 }
147 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
148 }
149 return true;
150 }
152 #undef EXTERNAL_SHADER
154 static bool init_sdr()
155 {
156 int status;
158 #ifdef EXTERNAL_SHADER
159 FILE *fp = fopen("sdr/sdr.glsl", "rb");
160 if(!fp) {
161 perror("failed to load sdr.glsl");
162 return false;
163 }
164 fseek(fp, 0, SEEK_END);
165 long sz = ftell(fp);
166 rewind(fp);
168 char *buf = (char*)alloca(sz + 1);
169 fread(buf, 1, sz, fp);
170 buf[sz] = 0;
171 sdr_src = buf;
173 fclose(fp);
174 #endif
176 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
177 glShaderSource(sdr, 1, &sdr_src, 0);
178 glCompileShader(sdr);
179 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
180 if(!status) {
181 fprintf(stderr, "failed to compile distortion shader\n");
183 int loglen;
184 glGetShaderiv(sdr, GL_INFO_LOG_LENGTH, &loglen);
186 if(loglen > 0) {
187 char *log = (char*)alloca(loglen);
188 glGetShaderInfoLog(sdr, loglen, &loglen, log);
189 fprintf(stderr, "%s\n", log);
190 }
192 return false;
193 }
195 sdrprog = glCreateProgram();
196 glAttachShader(sdrprog, sdr);
197 glLinkProgram(sdrprog);
198 if(!status) {
199 fprintf(stderr, "failed to link distortion shader program\n");
200 glDeleteShader(sdr);
201 return false;
202 }
204 int loc;
206 glUseProgram(sdrprog);
208 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
209 glUniform1i(loc, 0);
210 }
211 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
212 glUniform1f(loc, 0);
213 }
214 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
215 glUniform2f(loc, 0, 0);
216 }
217 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
218 glUniform1f(loc, vr_ctx.info.scale);
219 }
220 if((loc = glGetUniformLocation(sdrprog, "aspect")) != -1) {
221 printf("setting aspect: %f\n", vr_ctx.info.aspect / 2.0);
222 glUniform1f(loc, vr_ctx.info.aspect / 2.0);
223 }
224 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
225 glUniform2f(loc, 1, 1);
226 }
227 if((loc = glGetUniformLocation(sdrprog, "dist_factors")) != -1) {
228 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
229 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
230 }
232 return true;
233 }
235 extern "C" const char *vr_get_display_name(void)
236 {
237 return vr_ctx.info.display;
238 }
240 extern "C" void vr_get_display_pos(int *xptr, int *yptr)
241 {
242 *xptr = vr_ctx.info.display_xoffs;
243 *yptr = vr_ctx.info.display_yoffs;
244 }
246 extern "C" int vr_get_width(void)
247 {
248 return vr_ctx.info.width;
249 }
251 extern "C" int vr_get_height(void)
252 {
253 return vr_ctx.info.height;
254 }
256 extern "C" float vr_get_fov(void)
257 {
258 return vr_ctx.info.fov;
259 }
261 extern "C" float vr_get_aspect(void)
262 {
263 return vr_ctx.info.aspect;
264 }
266 extern "C" void vr_set_eyedist(float ipd)
267 {
268 vr_ctx.info.ipd = ipd;
269 }
271 extern "C" float vr_get_eyedist(void)
272 {
273 return vr_ctx.info.ipd;
274 }
276 extern "C" void vr_set_distort(const float *coef)
277 {
278 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
279 }
281 extern "C" void vr_get_distort(float *coef)
282 {
283 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
284 }
286 extern "C" void vr_set_prediction_sec(float dt)
287 {
288 vr_ctx.ovr_sfusion.SetPrediction(dt);
289 }
291 extern "C" float vr_get_prediction_sec(void)
292 {
293 return vr_ctx.ovr_sfusion.GetPredictionDelta();
294 }
296 extern "C" void vr_get_view_matrix(float *res, int eye)
297 {
298 // TODO
299 }
301 extern "C" void vr_get_proj_matrix(float *res, int eye)
302 {
303 static float eye_scale[] = {0.0, 1.0, -1.0};
305 Matrix4f proj = Matrix4f::PerspectiveRH(vr_ctx.info.fov, vr_ctx.info.aspect / 2.0, 0.3, 1000.0);
306 proj = Matrix4f::Translation(vr_ctx.info.proj_center_offset * eye_scale[eye], 0, 0) * proj;
308 memcpy(res, proj.M[0], 16 * sizeof(float));
309 }
311 extern "C" void vr_get_translation(float *offs)
312 {
313 // current oculus devkit doesn't do translation
314 offs[0] = offs[1] = offs[2] = 0.0f;
315 }
317 extern "C" void vr_get_rotation(float *quat)
318 {
319 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
320 quat[0] = oq.x;
321 quat[1] = oq.y;
322 quat[2] = oq.z;
323 quat[3] = oq.w;
324 }
326 extern "C" void vr_get_rotation_euler(float *euler)
327 {
328 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
329 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
330 }
332 extern "C" void vr_draw_eye(int eye, unsigned int tex, float tex_scale_x, float tex_scale_y)
333 {
334 static const float rects[3][4] = {
335 {-1, -1, 1, 1},
336 {-1, -1, 0, 1},
337 {0, -1, 1, 1}
338 };
339 static const float offs_scale[3] = {0.0, -1.0, 1.0};
341 glPushAttrib(GL_ENABLE_BIT);
342 glDisable(GL_DEPTH_TEST);
343 glDisable(GL_LIGHTING);
344 glEnable(GL_TEXTURE_2D);
346 glMatrixMode(GL_MODELVIEW);
347 glPushMatrix();
348 glLoadIdentity();
350 glMatrixMode(GL_PROJECTION);
351 glPushMatrix();
352 glLoadIdentity();
354 glUseProgram(sdrprog);
356 if(sdrprog) {
357 int loc;
358 if((loc = glGetUniformLocation(sdrprog, "lens_center_offset")) != -1) {
359 float offset = vr_ctx.info.lens_center_offset * offs_scale[eye];
360 glUniform1f(loc, offset);
361 }
363 if((loc = glGetUniformLocation(sdrprog, "tex_scale")) != -1) {
364 glUniform2f(loc, tex_scale_x, tex_scale_y);
365 }
366 }
368 glBindTexture(GL_TEXTURE_2D, tex);
369 glBegin(GL_QUADS);
370 glColor4f(1, 1, 1, 1);
371 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
372 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
373 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
374 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
375 glEnd();
377 glUseProgram(0);
379 glPopMatrix();
380 glMatrixMode(GL_MODELVIEW);
381 glPopMatrix();
383 glPopAttrib();
384 }