fixed 6dof camera
[o2demo] / src / demo.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <math.h>
6 #include <GL/gl.h>
7 #include <GL/glu.h>
8 #include <cgmath/cgmath.h>
9 #include "demo.h"
10 #include "screen.h"
11 #include "cfgopt.h"
12
13 static void recalc_sball_matrix(float *objmat, float *cammat);
14
15 static int console_active;
16 static int sball_update_pending;
17
18 static cgm_vec3 obj_pos, cam_pos;
19 static cgm_quat obj_rot = {0, 0, 0, 1};
20 static cgm_quat cam_rot = {0, 0, 0, 1};
21
22 int demo_init(int argc, char **argv)
23 {
24         struct screen *scr;
25         char *env;
26
27         if(load_config("demo.cfg") == -1) {
28                 return -1;
29         }
30         if((env = getenv("START_SCR"))) {
31                 opt.start_scr = env;
32         }
33         if(parse_args(argc, argv) == -1) {
34                 return -1;
35         }
36
37         glEnable(GL_DEPTH_TEST);
38         glEnable(GL_CULL_FACE);
39
40         sball_obj_matrix[0] = sball_obj_matrix[5] = sball_obj_matrix[10] = sball_obj_matrix[15] = 1.0f;
41         sball_cam_matrix[0] = sball_cam_matrix[5] = sball_cam_matrix[10] = sball_cam_matrix[15] = 1.0f;
42
43         if(scr_init() == -1) {
44                 return -1;
45         }
46         if(opt.start_scr) {
47                 scr = scr_lookup(opt.start_scr);
48         } else {
49                 scr = scr_screen(0);
50         }
51
52         if(!scr || scr_change(scr, 4000) == -1) {
53                 fprintf(stderr, "screen %s not found\n", opt.start_scr ? opt.start_scr : "0");
54                 return -1;
55         }
56
57         return 0;
58 }
59
60 void demo_cleanup(void)
61 {
62         scr_shutdown();
63 }
64
65 void demo_draw(void)
66 {
67         if(sball_update_pending) {
68                 recalc_sball_matrix(sball_obj_matrix, sball_cam_matrix);
69                 sball_update_pending = 0;
70         }
71
72         scr_update();
73         scr_draw();
74 }
75
76 void demo_reshape(int x, int y)
77 {
78         glViewport(0, 0, x, y);
79
80         glMatrixMode(GL_PROJECTION);
81         glLoadIdentity();
82         gluPerspective(50.0, win_aspect, 0.5, 500.0);
83 }
84
85 static void change_screen(int idx)
86 {
87         printf("change screen %d\n", idx);
88         scr_change(scr_screen(idx), 4000);
89 }
90
91 #define CBUF_SIZE       64
92 #define CBUF_MASK       (CBUF_SIZE - 1)
93 void demo_keyboard(int key, int pressed)
94 {
95         static char cbuf[CBUF_SIZE];
96         static int rd, wr;
97         char inp[CBUF_SIZE + 1], *dptr;
98         int i, nscr;
99
100         if(pressed) {
101                 switch(key) {
102                 case 27:
103                         demo_quit();
104                         break;
105
106                 case '`':
107                         console_active = !console_active;
108                         if(console_active) {
109                                 printf("> ");
110                                 fflush(stdout);
111                         } else {
112                                 putchar('\n');
113                         }
114                         return;
115
116                 case '\b':
117                         if(console_active) {
118                                 if(wr != rd) {
119                                         printf("\b \b");
120                                         fflush(stdout);
121                                         wr = (wr + CBUF_SIZE - 1) & CBUF_MASK;
122                                 }
123                                 return;
124                         }
125                         break;
126
127                 case '\n':
128                 case '\r':
129                         if(console_active) {
130                                 dptr = inp;
131                                 while(rd != wr) {
132                                         *dptr++ = cbuf[rd];
133                                         rd = (rd + 1) & CBUF_MASK;
134                                 }
135                                 *dptr = 0;
136                                 if(inp[0]) {
137                                         printf("\ntrying to match: %s\n", inp);
138                                         nscr = scr_num_screens();
139                                         for(i=0; i<nscr; i++) {
140                                                 if(strstr(scr_screen(i)->name, inp)) {
141                                                         change_screen(i);
142                                                         break;
143                                                 }
144                                         }
145                                 }
146                                 console_active = 0;
147                                 return;
148                         }
149                         break;
150
151                 default:
152                         if(key >= '1' && key <= '9' && key <= '1' + scr_num_screens()) {
153                                 change_screen(key - '1');
154                         } else if(key == '0' && scr_num_screens() >= 10) {
155                                 change_screen(9);
156                         }
157
158                         if(console_active) {
159                                 if(key < 256 && isprint(key)) {
160                                         putchar(key);
161                                         fflush(stdout);
162
163                                         cbuf[wr] = key;
164                                         wr = (wr + 1) & CBUF_MASK;
165                                         if(wr == rd) { /* overflow */
166                                                 rd = (rd + 1) & CBUF_MASK;
167                                         }
168                                 }
169                                 return;
170                         }
171                         break;
172                 }
173
174                 scr_keypress(key);
175         }
176 }
177
178 void demo_mbutton(int bn, int pressed, int x, int y)
179 {
180 }
181
182 void demo_mmotion(int x, int y)
183 {
184 }
185
186 void demo_sball_motion(int x, int y, int z)
187 {
188         cgm_vec3 dir;
189         dir.x = (float)x * 0.001;
190         dir.y = (float)y * 0.001;
191         dir.z = (float)-z * 0.001;
192         cgm_vadd(&obj_pos, &dir);
193
194         cgm_vrotate_quat(&dir, &cam_rot);
195         cgm_vadd(&cam_pos, &dir);
196
197         sball_update_pending = 1;
198 }
199
200 void demo_sball_rotate(int x, int y, int z)
201 {
202         float rx = (float)x;
203         float ry = (float)y;
204         float rz = (float)z;
205         float axis_len = sqrt(rx * rx + ry * ry + rz * rz);
206         if(axis_len > 0.0) {
207                 cgm_quat q;
208                 cgm_qrotation(&q, -axis_len * 0.001, rx / axis_len, ry / axis_len, -rz / axis_len);
209                 cgm_qmul(&obj_rot, &q);
210
211                 cgm_qrotation(&q, axis_len * 0.001, rx / axis_len, ry / axis_len, -rz / axis_len);
212                 cgm_qmul(&cam_rot, &q);
213         }
214         sball_update_pending = 1;
215 }
216
217 void demo_sball_button(int bn, int pressed)
218 {
219         if(!pressed) return;
220
221         switch(bn) {
222         case 0:
223                 cgm_vcons(&obj_pos, 0, 0, 0);
224                 cgm_vcons(&cam_pos, 0, 0, 0);
225                 cgm_qcons(&obj_rot, 0, 0, 0, 1);
226                 cgm_qcons(&cam_rot, 0, 0, 0, 1);
227                 sball_update_pending = 1;
228                 break;
229
230         default:
231                 break;
232         }
233 }
234
235
236 static void recalc_sball_matrix(float *objmat, float *cammat)
237 {
238         float rmat[16], tmat[16];
239
240         cgm_mrotation_quat(rmat, &cam_rot);
241         cgm_mtranspose(rmat);
242
243         cgm_mtranslation(tmat, -cam_pos.x, -cam_pos.y, -cam_pos.z);
244         cgm_mcopy(cammat, tmat);
245         cgm_mmul(cammat, rmat);
246
247         cgm_mrotation_quat(rmat, &obj_rot);
248         cgm_mtranspose(rmat);
249
250         cgm_mtranslation(tmat, obj_pos.x, obj_pos.y, obj_pos.z);
251         cgm_mcopy(objmat, rmat);
252         cgm_mmul(objmat, tmat);
253 }