fixed scale in VR
[vrfileman] / src / app.cc
1 #include <stdio.h>
2 #include <assert.h>
3 #include "opengl.h"
4 #include "app.h"
5 #include "gmath/gmath.h"
6 #include "mesh.h"
7 #include "meshgen.h"
8 #include "backdrop.h"
9 #include "goatvr.h"
10 #include "opt.h"
11 #include "fs.h"
12
13 static void draw_scene();
14
15 int win_width, win_height;
16 float win_aspect;
17 long time_msec;
18 double time_sec;
19 Mat4 view_matrix;
20
21 static bool should_swap;
22
23 static float cam_theta, cam_phi;
24 static float cam_height = 1.65;
25
26 static bool bnstate[16];
27 static int prev_x, prev_y;
28
29 bool app_init(int argc, char **argv)
30 {
31         if(!init_options(argc, argv, "vrfileman.conf")) {
32                 return false;
33         }
34         app_resize(opt.width, opt.height);
35         app_fullscreen(opt.fullscreen);
36
37         if(init_opengl() == -1) {
38                 return false;
39         }
40
41         glEnable(GL_MULTISAMPLE);
42
43         int aasamples = 0;
44         glGetIntegerv(GL_SAMPLES, &aasamples);
45         printf("got %d samples per pixel\n", aasamples);
46
47         printf("Max anisotropy: %d\n", glcaps.max_aniso);
48
49         glEnable(GL_CULL_FACE);
50         glEnable(GL_DEPTH_TEST);
51
52         if(opt.srgb && GLEW_ARB_framebuffer_sRGB) {
53                 printf("enabling sRGB framebuffer\n");
54                 glEnable(GL_FRAMEBUFFER_SRGB);
55         }
56
57         if(opt.vr) {
58                 if(goatvr_init() == -1) {
59                         return false;
60                 }
61                 goatvr_set_origin_mode(GOATVR_HEAD);
62
63                 goatvr_startvr();
64                 should_swap = goatvr_should_swap() != 0;
65                 cam_height = goatvr_get_eye_height();
66         }
67
68         Mesh::use_custom_sdr_attr = false;
69
70         if(!init_backdrop()) {
71                 return false;
72         }
73
74         if(!init_fs(opt.path)) {
75                 return false;
76         }
77
78         return true;
79 }
80
81 void app_cleanup()
82 {
83         if(opt.vr) {
84                 goatvr_shutdown();
85         }
86         cleanup_backdrop();
87 }
88
89 void app_draw()
90 {
91         if(opt.vr) {
92                 // VR mode
93                 goatvr_draw_start();
94                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
95
96                 for(int i=0; i<2; i++) {
97                         goatvr_draw_eye(i);
98
99                         glMatrixMode(GL_PROJECTION);
100                         glLoadMatrixf(goatvr_projection_matrix(i, 0.1, 200.0));
101
102                         view_matrix = goatvr_view_matrix(i);
103                         view_matrix.pre_rotate_x(deg_to_rad(cam_phi));
104                         view_matrix.pre_rotate_y(deg_to_rad(cam_theta));
105                         view_matrix.pre_translate(0, -cam_height, 0);
106
107                         glMatrixMode(GL_MODELVIEW);
108                         glLoadMatrixf(view_matrix[0]);
109
110                         draw_scene();
111                 }
112                 goatvr_draw_done();
113
114                 if(should_swap) {
115                         app_swap_buffers();
116                 }
117                 app_redraw();   // in VR mode, force continuous redraw
118
119         } else {
120                 // regular monoscopic mode
121                 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
122
123                 view_matrix = Mat4::identity;
124                 view_matrix.pre_rotate_x(deg_to_rad(cam_phi));
125                 view_matrix.pre_rotate_y(deg_to_rad(cam_theta));
126                 view_matrix.pre_translate(0, -cam_height, 0);
127
128                 glMatrixMode(GL_MODELVIEW);
129                 glLoadMatrixf(view_matrix[0]);
130
131                 draw_scene();
132
133                 app_swap_buffers();
134                 app_redraw();   // since we added animation we need to redisplay even in non-VR mode
135         }
136         assert(glGetError() == GL_NO_ERROR);
137 }
138
139 static void draw_scene()
140 {
141         draw_backdrop();
142         draw_fs();
143 }
144
145 void app_reshape(int x, int y)
146 {
147         glViewport(0, 0, x, y);
148
149         Mat4 mat;
150         mat.perspective(deg_to_rad(60), win_aspect, 0.1, 200.0);
151
152         glMatrixMode(GL_PROJECTION);
153         glLoadMatrixf(mat[0]);
154
155         if(opt.vr) {
156                 goatvr_set_fb_size(x, y, 1.0);
157         }
158 }
159
160 void app_keyboard(int key, bool pressed)
161 {
162         if(pressed) {
163                 switch(key) {
164                 case 27:
165                         app_quit();
166                         break;
167
168                 case 'f':
169                         if(!opt.vr || should_swap) {
170                                 /* we take the need to swap as a signal that our window is not managed
171                                  * by some VR compositor, and therefore it's safe to fullscreen without
172                                  * upsetting the VR rendering output
173                                  */
174                                 opt.fullscreen = !opt.fullscreen;
175                                 app_fullscreen(opt.fullscreen);
176                         }
177                         break;
178
179                 case ' ':
180                         if(opt.vr) {
181                                 goatvr_recenter();
182                         }
183                         break;
184                 }
185         }
186 }
187
188 void app_mouse_button(int bn, bool pressed, int x, int y)
189 {
190         bnstate[bn] = pressed;
191         prev_x = x;
192         prev_y = y;
193 }
194
195 void app_mouse_motion(int x, int y)
196 {
197         int dx = x - prev_x;
198         int dy = y - prev_y;
199         prev_x = x;
200         prev_y = y;
201
202         if(!dx && !dy) return;
203
204         if(bnstate[0]) {
205                 cam_theta += dx * 0.5;
206
207                 if(!opt.vr || !goatvr_have_headtracking()) {
208                         cam_phi += dy * 0.5;
209
210                         if(cam_phi < -90) cam_phi = -90;
211                         if(cam_phi > 90) cam_phi = 90;
212                 }
213         }
214         app_redraw();
215 }