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