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