rev |
line source |
nuclear@1
|
1 #include <stdio.h>
|
nuclear@12
|
2 #include <GL/glew.h>
|
nuclear@1
|
3 #include "vr.h"
|
nuclear@1
|
4 #include "vr_impl.h"
|
nuclear@1
|
5
|
nuclear@12
|
6 static const char *sdr_src =
|
nuclear@12
|
7 "uniform sampler2D tex;\n"
|
nuclear@12
|
8 "uniform vec2 lens_center;\n"
|
nuclear@12
|
9 "uniform vec2 scr_center;\n"
|
nuclear@12
|
10 "uniform vec2 scale;\n"
|
nuclear@12
|
11 "uniform vec2 scale_in;\n"
|
nuclear@12
|
12 "uniform vec4 warp_param;\n"
|
nuclear@12
|
13 "\n"
|
nuclear@12
|
14 "vec2 warp(in vec2 pt)\n"
|
nuclear@12
|
15 "{\n"
|
nuclear@12
|
16 " vec2 theta = (pt - lens_center) * scale_in;\n"
|
nuclear@12
|
17 " float rsq = length(theta);\n"
|
nuclear@12
|
18 " vec2 rvec = theta * (warp_param.x + warp_param.y * rsq +\n"
|
nuclear@12
|
19 " warp_param.z * rsq * rsq +\n"
|
nuclear@12
|
20 " warp_param.w * rsq * rsq * rsq);\n"
|
nuclear@12
|
21 " return lens_center + scale * rvec;\n"
|
nuclear@12
|
22 "}\n"
|
nuclear@12
|
23 "\n"
|
nuclear@12
|
24 "void main()\n"
|
nuclear@12
|
25 "{\n"
|
nuclear@12
|
26 " vec2 tc = warp(gl_TexCoord[0].xy);\n"
|
nuclear@12
|
27 " gl_FragColor.rgb = texture2D(tex, tc).rgb;\n"
|
nuclear@12
|
28 " gl_FragColor.a = 1.0;\n"
|
nuclear@12
|
29 "}\n";
|
nuclear@12
|
30
|
nuclear@1
|
31 static bool init_ovr();
|
nuclear@12
|
32 static bool init_sdr();
|
nuclear@1
|
33
|
nuclear@3
|
34 VRContext vr_ctx;
|
nuclear@12
|
35 static unsigned int sdrprog;
|
nuclear@1
|
36
|
nuclear@1
|
37 extern "C" int vr_init(enum vr_init_mode mode)
|
nuclear@1
|
38 {
|
nuclear@12
|
39 glewInit();
|
nuclear@12
|
40
|
nuclear@1
|
41 if(!init_ovr()) {
|
nuclear@1
|
42 return -1;
|
nuclear@1
|
43 }
|
nuclear@12
|
44
|
nuclear@12
|
45 if(!init_sdr()) {
|
nuclear@12
|
46 return -1;
|
nuclear@12
|
47 }
|
nuclear@12
|
48
|
nuclear@1
|
49 return 0;
|
nuclear@1
|
50 }
|
nuclear@1
|
51
|
nuclear@1
|
52 extern "C" void vr_shutdown(void)
|
nuclear@1
|
53 {
|
nuclear@3
|
54 //System::Destroy();
|
nuclear@1
|
55 }
|
nuclear@1
|
56
|
nuclear@1
|
57 static bool init_ovr()
|
nuclear@1
|
58 {
|
nuclear@8
|
59 LogMaskConstants log_level = LogMask_All;
|
nuclear@1
|
60 // initialize Oculus SDK
|
nuclear@5
|
61 const char *logenv = getenv("VR_LOGLEVEL");
|
nuclear@5
|
62 if(logenv) {
|
nuclear@5
|
63 switch(atoi(logenv)) {
|
nuclear@5
|
64 case 0:
|
nuclear@5
|
65 log_level = LogMask_None;
|
nuclear@5
|
66 break;
|
nuclear@5
|
67 case 1:
|
nuclear@5
|
68 log_level = LogMask_Regular;
|
nuclear@5
|
69 break;
|
nuclear@5
|
70 case 2:
|
nuclear@5
|
71 default:
|
nuclear@5
|
72 log_level = LogMask_All;
|
nuclear@5
|
73 break;
|
nuclear@5
|
74 }
|
nuclear@5
|
75 }
|
nuclear@5
|
76
|
nuclear@5
|
77 System::Init(Log::ConfigureDefaultLog(log_level));
|
nuclear@3
|
78 if(!(vr_ctx.ovr_devman = DeviceManager::Create())) {
|
nuclear@1
|
79 fprintf(stderr, "failed to create OVR device manager\n");
|
nuclear@1
|
80 return false;
|
nuclear@1
|
81 }
|
nuclear@1
|
82
|
nuclear@1
|
83 // create the display device
|
nuclear@4
|
84 HMDInfo info;
|
nuclear@3
|
85 if(!(vr_ctx.ovr_hmd_dev = vr_ctx.ovr_devman->EnumerateDevices<HMDDevice>().CreateDevice())) {
|
nuclear@1
|
86 fprintf(stderr, "no oculus rift devices found\n");
|
nuclear@4
|
87 } else {
|
nuclear@4
|
88 if(vr_ctx.ovr_hmd_dev->GetDeviceInfo(&info)) {
|
nuclear@4
|
89 printf("oculus device info:\n");
|
nuclear@4
|
90 printf(" name: %s\n", info.DisplayDeviceName);
|
nuclear@4
|
91 printf(" ipd: %f\n", info.InterpupillaryDistance);
|
nuclear@4
|
92 printf(" distortion: %f %f %f %f\n", info.DistortionK[0],
|
nuclear@4
|
93 info.DistortionK[1], info.DistortionK[2], info.DistortionK[3]);
|
nuclear@4
|
94 }
|
nuclear@1
|
95
|
nuclear@4
|
96 // calculate and store viewing parameters
|
nuclear@4
|
97 float vhalfsz = info.VScreenSize * 0.5;
|
nuclear@4
|
98 vr_ctx.info.fov = 2.0 * atan(vhalfsz / info.EyeToScreenDistance);
|
nuclear@4
|
99
|
nuclear@4
|
100 vr_ctx.info.width = info.HResolution;
|
nuclear@4
|
101 vr_ctx.info.height = info.VResolution;
|
nuclear@4
|
102 vr_ctx.info.aspect = (float)vr_ctx.info.width / (float)vr_ctx.info.height;
|
nuclear@4
|
103
|
nuclear@4
|
104 vr_ctx.info.ipd = info.InterpupillaryDistance;
|
nuclear@4
|
105 for(int i=0; i<4; i++) {
|
nuclear@4
|
106 vr_ctx.info.distort[i] = info.DistortionK[i];
|
nuclear@4
|
107 }
|
nuclear@12
|
108
|
nuclear@12
|
109 vr_ctx.info.lens_center = info.LensSeparationDistance / info.HScreenSize;
|
nuclear@1
|
110 }
|
nuclear@1
|
111
|
nuclear@1
|
112 // get the sensor device
|
nuclear@4
|
113 if(vr_ctx.ovr_hmd_dev) {
|
nuclear@4
|
114 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_hmd_dev->GetSensor())) {
|
nuclear@4
|
115 fprintf(stderr, "failed to get oculus sensor device\n");
|
nuclear@4
|
116 }
|
nuclear@4
|
117 } else {
|
nuclear@4
|
118 if(!(vr_ctx.ovr_sensor_dev = vr_ctx.ovr_devman->EnumerateDevices<SensorDevice>().CreateDevice())) {
|
nuclear@4
|
119 fprintf(stderr, "failed to get oculus sensor device\n");
|
nuclear@4
|
120 }
|
nuclear@1
|
121 }
|
nuclear@1
|
122
|
nuclear@4
|
123 if(vr_ctx.ovr_sensor_dev) {
|
nuclear@4
|
124 SensorInfo sinfo;
|
nuclear@4
|
125 if(vr_ctx.ovr_sensor_dev->GetDeviceInfo(&sinfo)) {
|
nuclear@4
|
126 printf("oculus sensor device info:\n");
|
nuclear@4
|
127 printf(" name: %s\n", sinfo.ProductName);
|
nuclear@4
|
128 }
|
nuclear@4
|
129
|
nuclear@4
|
130 vr_ctx.ovr_sfusion.AttachToSensor(vr_ctx.ovr_sensor_dev);
|
nuclear@1
|
131 }
|
nuclear@1
|
132 return true;
|
nuclear@1
|
133 }
|
nuclear@3
|
134
|
nuclear@12
|
135 static bool init_sdr()
|
nuclear@12
|
136 {
|
nuclear@12
|
137 int status;
|
nuclear@12
|
138
|
nuclear@12
|
139 unsigned int sdr = glCreateShader(GL_FRAGMENT_SHADER);
|
nuclear@12
|
140 glShaderSource(sdr, 1, &sdr_src, 0);
|
nuclear@12
|
141 glCompileShader(sdr);
|
nuclear@12
|
142 glGetShaderiv(sdr, GL_COMPILE_STATUS, &status);
|
nuclear@12
|
143 if(!status) {
|
nuclear@12
|
144 fprintf(stderr, "failed to compile distortion shader\n");
|
nuclear@12
|
145 return false;
|
nuclear@12
|
146 }
|
nuclear@12
|
147
|
nuclear@12
|
148 sdrprog = glCreateProgram();
|
nuclear@12
|
149 glAttachShader(sdrprog, sdr);
|
nuclear@12
|
150 glLinkProgram(sdrprog);
|
nuclear@12
|
151 if(!status) {
|
nuclear@12
|
152 fprintf(stderr, "failed to link distortion shader program\n");
|
nuclear@12
|
153 glDeleteShader(sdr);
|
nuclear@12
|
154 return false;
|
nuclear@12
|
155 }
|
nuclear@12
|
156
|
nuclear@12
|
157 int loc;
|
nuclear@12
|
158
|
nuclear@12
|
159 glUseProgram(sdrprog);
|
nuclear@12
|
160
|
nuclear@12
|
161 if((loc = glGetUniformLocation(sdrprog, "tex")) != -1) {
|
nuclear@12
|
162 glUniform1i(loc, 0);
|
nuclear@12
|
163 }
|
nuclear@12
|
164 if((loc = glGetUniformLocation(sdrprog, "lens_center")) != -1) {
|
nuclear@12
|
165 glUniform2f(loc, 0.5, 0.5);
|
nuclear@12
|
166 }
|
nuclear@12
|
167 if((loc = glGetUniformLocation(sdrprog, "scr_center")) != -1) {
|
nuclear@12
|
168 glUniform2f(loc, 0, 0);
|
nuclear@12
|
169 }
|
nuclear@12
|
170 if((loc = glGetUniformLocation(sdrprog, "scale")) != -1) {
|
nuclear@12
|
171 glUniform2f(loc, 1, 1);
|
nuclear@12
|
172 }
|
nuclear@12
|
173 if((loc = glGetUniformLocation(sdrprog, "scale_in")) != -1) {
|
nuclear@12
|
174 glUniform2f(loc, 1, 1);
|
nuclear@12
|
175 }
|
nuclear@12
|
176 if((loc = glGetUniformLocation(sdrprog, "warp_param")) != -1) {
|
nuclear@12
|
177 glUniform4f(loc, vr_ctx.info.distort[0], vr_ctx.info.distort[1],
|
nuclear@12
|
178 vr_ctx.info.distort[2], vr_ctx.info.distort[3]);
|
nuclear@12
|
179 }
|
nuclear@12
|
180
|
nuclear@12
|
181 return true;
|
nuclear@12
|
182 }
|
nuclear@12
|
183
|
nuclear@3
|
184 extern "C" int vr_get_width(void)
|
nuclear@3
|
185 {
|
nuclear@3
|
186 return vr_ctx.info.width;
|
nuclear@3
|
187 }
|
nuclear@3
|
188
|
nuclear@3
|
189 extern "C" int vr_get_height(void)
|
nuclear@3
|
190 {
|
nuclear@3
|
191 return vr_ctx.info.height;
|
nuclear@3
|
192 }
|
nuclear@3
|
193
|
nuclear@3
|
194 extern "C" float vr_get_fov(void)
|
nuclear@3
|
195 {
|
nuclear@3
|
196 return vr_ctx.info.fov;
|
nuclear@3
|
197 }
|
nuclear@3
|
198
|
nuclear@3
|
199 extern "C" float vr_get_aspect(void)
|
nuclear@3
|
200 {
|
nuclear@3
|
201 return vr_ctx.info.aspect;
|
nuclear@3
|
202 }
|
nuclear@3
|
203
|
nuclear@3
|
204 extern "C" void vr_set_eyedist(float ipd)
|
nuclear@3
|
205 {
|
nuclear@3
|
206 vr_ctx.info.ipd = ipd;
|
nuclear@3
|
207 }
|
nuclear@3
|
208
|
nuclear@3
|
209 extern "C" float vr_get_eyedist(void)
|
nuclear@3
|
210 {
|
nuclear@3
|
211 return vr_ctx.info.ipd;
|
nuclear@3
|
212 }
|
nuclear@3
|
213
|
nuclear@3
|
214 extern "C" void vr_set_distort(const float *coef)
|
nuclear@3
|
215 {
|
nuclear@3
|
216 memcpy(vr_ctx.info.distort, coef, sizeof vr_ctx.info.distort);
|
nuclear@3
|
217 }
|
nuclear@3
|
218
|
nuclear@3
|
219 extern "C" void vr_get_distort(float *coef)
|
nuclear@3
|
220 {
|
nuclear@3
|
221 memcpy(coef, vr_ctx.info.distort, sizeof vr_ctx.info.distort);
|
nuclear@3
|
222 }
|
nuclear@3
|
223
|
nuclear@3
|
224 extern "C" void vr_set_prediction_sec(float dt)
|
nuclear@3
|
225 {
|
nuclear@3
|
226 vr_ctx.ovr_sfusion.SetPrediction(dt);
|
nuclear@3
|
227 }
|
nuclear@3
|
228
|
nuclear@3
|
229 extern "C" float vr_get_prediction_sec(void)
|
nuclear@3
|
230 {
|
nuclear@3
|
231 return vr_ctx.ovr_sfusion.GetPredictionDelta();
|
nuclear@3
|
232 }
|
nuclear@3
|
233
|
nuclear@3
|
234 extern "C" void vr_get_translation(float *offs)
|
nuclear@3
|
235 {
|
nuclear@3
|
236 // current oculus devkit doesn't do translation
|
nuclear@3
|
237 offs[0] = offs[1] = offs[2] = 0.0f;
|
nuclear@3
|
238 }
|
nuclear@3
|
239
|
nuclear@3
|
240 extern "C" void vr_get_rotation(float *quat)
|
nuclear@3
|
241 {
|
nuclear@3
|
242 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
|
nuclear@3
|
243 quat[0] = oq.x;
|
nuclear@3
|
244 quat[1] = oq.y;
|
nuclear@3
|
245 quat[2] = oq.z;
|
nuclear@3
|
246 quat[3] = oq.w;
|
nuclear@3
|
247 }
|
nuclear@3
|
248
|
nuclear@3
|
249 extern "C" void vr_get_rotation_euler(float *euler)
|
nuclear@3
|
250 {
|
nuclear@3
|
251 Quatf oq = vr_ctx.ovr_sfusion.GetPredictedOrientation();
|
nuclear@3
|
252 oq.GetEulerAngles<Axis_Y, Axis_X, Axis_Z>(euler + 1, euler, euler + 2);
|
nuclear@3
|
253 }
|
nuclear@12
|
254
|
nuclear@12
|
255 extern "C" void vr_draw_eye(unsigned int tex, int eye)
|
nuclear@12
|
256 {
|
nuclear@12
|
257 static const float rects[3][4] = {
|
nuclear@12
|
258 {-1, -1, 1, 1},
|
nuclear@12
|
259 {-1, -1, 0, 1},
|
nuclear@12
|
260 {0, -1, 1, 1}
|
nuclear@12
|
261 };
|
nuclear@12
|
262 static const float offs_scale[3] = {0.0, -1.0, 1.0};
|
nuclear@12
|
263
|
nuclear@12
|
264 glPushAttrib(GL_ENABLE_BIT);
|
nuclear@12
|
265 glDisable(GL_DEPTH_TEST);
|
nuclear@12
|
266 glDisable(GL_LIGHTING);
|
nuclear@12
|
267 glEnable(GL_TEXTURE_2D);
|
nuclear@12
|
268
|
nuclear@12
|
269 glMatrixMode(GL_MODELVIEW);
|
nuclear@12
|
270 glPushMatrix();
|
nuclear@12
|
271 glLoadIdentity();
|
nuclear@12
|
272
|
nuclear@12
|
273 glMatrixMode(GL_PROJECTION);
|
nuclear@12
|
274 glPushMatrix();
|
nuclear@12
|
275 glLoadIdentity();
|
nuclear@12
|
276
|
nuclear@12
|
277 glUseProgram(sdrprog);
|
nuclear@12
|
278
|
nuclear@12
|
279 int loc;
|
nuclear@12
|
280 if((loc = glGetUniformLocation(sdrprog, "lens_center")) != -1) {
|
nuclear@12
|
281 float lens_center = 0.5 - vr_ctx.info.lens_center * offs_scale[eye];
|
nuclear@12
|
282 glUniform2f(loc, lens_center, 0.5);
|
nuclear@12
|
283 printf("lens_center = %f\n", lens_center);
|
nuclear@12
|
284 }
|
nuclear@12
|
285
|
nuclear@12
|
286 glBindTexture(GL_TEXTURE_2D, tex);
|
nuclear@12
|
287 glBegin(GL_QUADS);
|
nuclear@12
|
288 glColor4f(1, 1, 1, 1);
|
nuclear@12
|
289 glTexCoord2f(0, 0); glVertex2f(rects[eye][0], rects[eye][1]);
|
nuclear@12
|
290 glTexCoord2f(1, 0); glVertex2f(rects[eye][2], rects[eye][1]);
|
nuclear@12
|
291 glTexCoord2f(1, 1); glVertex2f(rects[eye][2], rects[eye][3]);
|
nuclear@12
|
292 glTexCoord2f(0, 1); glVertex2f(rects[eye][0], rects[eye][3]);
|
nuclear@12
|
293 glEnd();
|
nuclear@12
|
294
|
nuclear@12
|
295 glUseProgram(0);
|
nuclear@12
|
296
|
nuclear@12
|
297 glPopMatrix();
|
nuclear@12
|
298 glMatrixMode(GL_MODELVIEW);
|
nuclear@12
|
299 glPopMatrix();
|
nuclear@12
|
300
|
nuclear@12
|
301 glPopAttrib();
|
nuclear@12
|
302 }
|