a844257576d044e9a99b96db16da3d1e9720310b
[mercenary-reloaded.git] / src / libovr / keyboard.c
1 /* VR Keyboard
2  *
3  * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
4  * All Rights Reserved
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdint.h>
23 #include <errno.h>
24 #include <math.h>
25 #include "../../include/keycodes.h"
26 #include "../libsdl/print.h"
27 #include "keyboard.h"
28 #define GL3_PROTOTYPES 1
29 #include <GL/glew.h>
30
31 #define MAX_KEYS        128     /* maximum number of keys per keyboard */
32 #define MAX_KEY_LINES   32      /* maximum number of lines on each key */
33 #define TILT_KEYS       45      /* rotate keyboard by given degrees */
34
35 /*
36  * The keys are defined by coordinates that are described by the following
37  * digits:
38  *
39  * a  b  c  d  e
40  *
41  * f  g  h  i  j
42  *
43  * k  l  m  n  o
44  *
45  * p  q  r  s  t
46  *
47  * u  v  w  x  y
48  *
49  * The lines are defined from digit to digit to digit.... To start with a
50  * new line (not connected to the previous one, add ' ' (space).
51  *
52  */
53
54 static struct key_font {
55         char key;
56         const char *font;
57 } key_font[] = {
58         { '0', "bdjtxvpfb qi" },
59         { '1', "gcw vx" },
60         { '2', "fbdjnlpuy" },
61         { '3', "fbdjntxvp ln" },
62         { '4', "ako hw" },
63         { '5', "eakntxu" },
64         { '6', "jdbfpvxtnk" },
65         { '7', "aemw" },
66         { '8', "lfbdjntxvpln" },
67         { '9', "jnlfbdjtxvp" },
68         { 'A', "ukoy kco" },
69         { 'B', "knjdauxtn" },
70         { 'C', "jdbfpvxt" },
71         { 'D', "adjtxua" },
72         { 'E', "eauy km" },
73         { 'F', "eau km" },
74         { 'G', "jdbfpvxt yom" },
75         { 'H', "au ey ko" },
76         { 'I', "bd vx cw" },
77         { 'J', "aetxvpk" },
78         { 'K', "au emy km" },
79         { 'L', "auy" },
80         { 'M', "uamey" },
81         { 'N', "uaye" },
82         { 'O', "bdjtxvpfb" },
83         { 'P', "uadjnk" },
84         { 'Q', "bdjtxvpfb ys" },
85         { 'R', "uadjnk my" },
86         { 'S', "jdbflntxvp" },
87         { 'T', "ae cw" },
88         { 'U', "apvxte" },
89         { 'V', "akwoe" },
90         { 'W', "aumye" },
91         { 'X', "ay ue" },
92         { 'Y', "ame mw" },
93         { 'Z', "aeuy" },
94         { 'u', "cw kco" },
95         { 'd', "cw kwo" },
96         { 'l', "ko ckw" },
97         { 'r', "ko cow" },
98         { '.', "rr" },
99         { ',', "rv" },
100         { '+', "cw ko" },
101         { '-', "ko" },
102         { '*', "ko ay ue" },
103         { 's', "" }, /* space */
104         { 'b', "beyvkb gs qi" },
105         { 'e', "dsp pl pv" },
106         { ' ', "" },
107         { 0, NULL }
108 };
109
110 /*
111  * f-keys are 25 percent larger, so 4 f-keys are as wide as 5 regular keys.
112  * This is why f-keys use 5 steps instead of four (regular keys).
113  */
114
115 static const char *keyboard_layout[] = {
116         "fe     f1   f2   f3   f4   f5    f6   f7   f8   f9   f0",
117         "1   2   3   4   5   6   7   8   9   0   b2         fh          7   8   9   *",
118         "  Q   W   E   R   T   Y   U   I   O   P                        4   5   6   -",
119         "   A   S   D   F   G   H   J   K   L   fr            u         1   2   3   +",
120         "     Z   X   C   V   B   N   M   ,   .           l   d   r     02      e2   ",
121         "          s6                             ",
122         NULL, /* end of keyboard */
123 };
124
125 static enum keycode keyboard_codes[] = {
126         KEYCODE_ESCAPE, KEYCODE_F1, KEYCODE_F2, KEYCODE_F3, KEYCODE_F4, KEYCODE_F5, KEYCODE_F6, KEYCODE_F7, KEYCODE_F8, KEYCODE_F9, KEYCODE_F10,
127         KEYCODE_1, KEYCODE_2, KEYCODE_3, KEYCODE_4, KEYCODE_5, KEYCODE_6, KEYCODE_7, KEYCODE_8, KEYCODE_9, KEYCODE_0, KEYCODE_BACKSPACE,
128         KEYCODE_HELP, KEYCODE_KP_7, KEYCODE_KP_8, KEYCODE_KP_9, KEYCODE_KP_MULTIPLY,
129         KEYCODE_q, KEYCODE_w, KEYCODE_e, KEYCODE_r, KEYCODE_t, KEYCODE_y, KEYCODE_u, KEYCODE_i, KEYCODE_o, KEYCODE_p,
130         KEYCODE_KP_4, KEYCODE_KP_5, KEYCODE_KP_6, KEYCODE_KP_MINUS,
131         KEYCODE_a, KEYCODE_s, KEYCODE_d, KEYCODE_f, KEYCODE_g, KEYCODE_h, KEYCODE_j, KEYCODE_k, KEYCODE_l, KEYCODE_RETURN,
132         KEYCODE_UP, KEYCODE_KP_1, KEYCODE_KP_2, KEYCODE_KP_3, KEYCODE_KP_PLUS,
133         KEYCODE_z, KEYCODE_x, KEYCODE_c, KEYCODE_v, KEYCODE_b, KEYCODE_n, KEYCODE_m, KEYCODE_COMMA, KEYCODE_PERIOD,
134         KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_RIGHT, KEYCODE_KP_0, KEYCODE_KP_ENTER,
135         KEYCODE_SPACE,
136 };
137
138 /* definition of keys with coordinates for rendering */
139 struct key_def {
140         char key;
141         int fkey;
142         double margin_left, margin_right, margin_front, margin_back;
143         double left_top_front_x, left_top_front_y, left_top_front_z;
144         double right_top_front_x, right_top_front_y, right_top_front_z;
145         double left_top_back_x, left_top_back_y, left_top_back_z;
146         double right_top_back_x, right_top_back_y, right_top_back_z;
147         double left_bottom_front_x, left_bottom_front_y, left_bottom_front_z;
148         double right_bottom_front_x, right_bottom_front_y, right_bottom_front_z;
149         double left_bottom_back_x, left_bottom_back_y, left_bottom_back_z;
150         double right_bottom_back_x, right_bottom_back_y, right_bottom_back_z;
151         double x1[MAX_KEY_LINES], y1[MAX_KEY_LINES], z1[MAX_KEY_LINES];
152         double x2[MAX_KEY_LINES], y2[MAX_KEY_LINES], z2[MAX_KEY_LINES];
153         int lines;
154 };
155
156 /* definition for each keyboard */
157 static struct keyboard_def {
158         struct key_def key[MAX_KEYS];
159         int keys;
160 } keyboard_def;
161
162 /*
163  * add key to keyboard_def[].key structure
164  *
165  *-4  -2     0     2 3 4
166  * +-------------------+ 4
167  * | +---------------+ | 3
168  * | | a  b  c  d  e | | 2
169  * | | f  g  h  i  j | | 1
170  * | | k  l  m  n  o | | 0
171  * | | p  q  r  s  t | | -1
172  * | | u  v  w  x  y | | -2
173  * | +---------------+ | -3
174  * +-------------------+ -4
175  *        (front)
176  */
177
178 static int add_key(char key, int fkey, double width, struct key_def *key_def)
179 {
180         int d, l, f, i;
181         double font_scale = 1.0, font_offset = 0.0;
182
183         memset(key_def, 0, sizeof(*key_def));
184
185         key_def->key = key;
186         key_def->fkey = fkey;
187
188         /* key case (see layout in the description above) */
189         key_def->left_top_front_x = -3.0;
190         key_def->left_top_front_y = 0;
191         key_def->left_top_front_z = 3.0;
192
193         key_def->right_top_front_x = 3.0 + (width - 1.0) * 9.0;
194         key_def->right_top_front_y = 0;
195         key_def->right_top_front_z = 3.0;
196
197         key_def->left_top_back_x = -3.0;
198         key_def->left_top_back_y = 0;
199         key_def->left_top_back_z = -3.0;
200
201         key_def->right_top_back_x = 3.0 + (width - 1.0) * 9.0;
202         key_def->right_top_back_y = 0;
203         key_def->right_top_back_z = -3.0;
204
205         key_def->left_bottom_front_x = -4.0;
206         key_def->left_bottom_front_y = -2.0;
207         key_def->left_bottom_front_z = 4.0;
208
209         key_def->right_bottom_front_x = 4.0 + (width - 1.0) * 9.0;
210         key_def->right_bottom_front_y = -2.0;
211         key_def->right_bottom_front_z = 4.0;
212
213         key_def->left_bottom_back_x = -4.0;
214         key_def->left_bottom_back_y = -2.0;
215         key_def->left_bottom_back_z = -4.0;
216
217         key_def->right_bottom_back_x = 4.0 + (width - 1.0) * 9.0;
218         key_def->right_bottom_back_y = -2.0;
219         key_def->right_bottom_back_z = -4.0;
220
221         /* lines to be drawn ontop of the key (see layout in the description above) */
222         l = 0;
223         /* up to 4 letters/digits are displayed on key */
224         for (d = 0; d < 6; d++) {
225                 if (!key_def->fkey) {
226                         /* render regular key */
227                         if (d == 0)
228                                 key = key_def->key;
229                         else
230                                 break;
231                 } else {
232                         /* render F-key */
233                         if (d == 0) {
234                                 font_scale = 0.5;
235                                 font_offset = -0.25;
236                                 if (key_def->key == 'h')
237                                         key = 'H';
238                                 else if (key_def->key == 'r')
239                                         key = 'R';
240                                 else if (key_def->key == 'e')
241                                         key = 'E';
242                                 else
243                                         key = 'F';
244                         }
245                         else if (d == 1) {
246                                 font_offset += 2.5;
247                                 if (key_def->key == 'h')
248                                         key = 'E';
249                                 else if (key_def->key == 'r')
250                                         key = 'E';
251                                 else if (key_def->key == 'e')
252                                         key = 'S';
253                                 else if (key_def->key != '0')
254                                         key = key_def->key;
255                                 else
256                                         key = '1';
257                         }
258                         else if (d == 2) {
259                                 font_offset += 2.5;
260                                 if (key_def->key == 'h')
261                                         key = 'L';
262                                 else if (key_def->key == 'r')
263                                         key = 'T';
264                                 else if (key_def->key == 'e')
265                                         key = 'C';
266                                 else if (key_def->key != '0')
267                                         break;
268                                 else
269                                         key = '0';
270                         }
271                         else if (d == 3) {
272                                 font_offset += 2.5;
273                                 if (key_def->key == 'h')
274                                         key = 'P';
275                                 else if (key_def->key == 'r')
276                                         key = 'U';
277                                 else
278                                         break;
279                         }
280                         else if (d == 4) {
281                                 font_offset += 2.5;
282                                 if (key_def->key == 'r')
283                                         key = 'R';
284                                 else
285                                         break;
286                         }
287                         else if (d == 5) {
288                                 font_offset += 2.5;
289                                 if (key_def->key == 'r')
290                                         key = 'N';
291                                 else
292                                         break;
293                         }
294                 }
295                 /* search for key font */
296                 for (f = 0; key_font[f].key; f++) {
297                         if (key_font[f].key == key)
298                                 break;
299                 }
300                 if (!key_font[f].key) {
301                         print_error("Failed to find keyboard character '%c' in key_font, please fix\n", key);
302                         return -EINVAL;
303                 }
304                 /* generate lines */
305                 i = 0;
306                 while (key_font[f].font[i] && key_font[f].font[i + 1]) {
307                         /* skip spaces, but this should not happen */
308                         if (key_font[f].font[i] == ' ') {
309                                 i++;
310                                 continue;
311                         }
312                         /* the second character is space, so we start over with a new line sequence */
313                         if (key_font[f].font[i + 1] == ' ') {
314                                 i += 2;
315                                 continue;
316                         }
317                         /* add line */
318                         if (l == MAX_KEY_LINES) {
319                                 print_error("Failed to add key definition, maximum number of lines exeeded, please fix\n");
320                                 return -EINVAL;
321                         }
322                         key_def->x1[l] = (double)(((key_font[f].font[i] - 'a') % 5) - 2) * font_scale + font_offset;
323                         key_def->y1[l] = 0;
324                         key_def->z1[l] = (double)((key_font[f].font[i] - 'a') / 5) - 2;
325                         key_def->x2[l] = (double)(((key_font[f].font[i + 1] - 'a') % 5) - 2) * font_scale + font_offset;
326                         key_def->y2[l] = 0;
327                         key_def->z2[l] = (double)((key_font[f].font[i + 1] - 'a') / 5) - 2;
328                         l++;
329                         i++;
330                 }
331         }
332         key_def->lines = l;
333
334         return 0;
335 }
336
337 static void scale_key(double px, double py, double pz, double scale, struct key_def *key_def)
338 {
339         int l;
340
341         /* scale and translate key case */
342         key_def->left_top_front_x = key_def->left_top_front_x * scale + px;
343         key_def->right_top_front_x = key_def->right_top_front_x * scale + px;
344         key_def->left_top_back_x = key_def->left_top_back_x * scale + px;
345         key_def->right_top_back_x = key_def->right_top_back_x * scale + px;
346         key_def->left_bottom_front_x = key_def->left_bottom_front_x * scale + px;
347         key_def->right_bottom_front_x = key_def->right_bottom_front_x * scale + px;
348         key_def->left_bottom_back_x = key_def->left_bottom_back_x * scale + px;
349         key_def->right_bottom_back_x = key_def->right_bottom_back_x * scale + px;
350         key_def->left_top_front_y = key_def->left_top_front_y * scale + py;
351         key_def->right_top_front_y = key_def->right_top_front_y * scale + py;
352         key_def->left_top_back_y = key_def->left_top_back_y * scale + py;
353         key_def->right_top_back_y = key_def->right_top_back_y * scale + py;
354         key_def->left_bottom_front_y = key_def->left_bottom_front_y * scale + py;
355         key_def->right_bottom_front_y = key_def->right_bottom_front_y * scale + py;
356         key_def->left_bottom_back_y = key_def->left_bottom_back_y * scale + py;
357         key_def->right_bottom_back_y = key_def->right_bottom_back_y * scale + py;
358         key_def->left_top_front_z = key_def->left_top_front_z * scale + pz;
359         key_def->right_top_front_z = key_def->right_top_front_z * scale + pz;
360         key_def->left_top_back_z = key_def->left_top_back_z * scale + pz;
361         key_def->right_top_back_z = key_def->right_top_back_z * scale + pz;
362         key_def->left_bottom_front_z = key_def->left_bottom_front_z * scale + pz;
363         key_def->right_bottom_front_z = key_def->right_bottom_front_z * scale + pz;
364         key_def->left_bottom_back_z = key_def->left_bottom_back_z * scale + pz;
365         key_def->right_bottom_back_z = key_def->right_bottom_back_z * scale + pz;
366
367         /* scale and translate line ontop of keys */
368         for (l = 0; l < key_def->lines; l++) {
369                 key_def->x1[l] = key_def->x1[l] * scale + px;
370                 key_def->y1[l] = key_def->y1[l] * scale + py;
371                 key_def->z1[l] = key_def->z1[l] * scale + pz;
372                 key_def->x2[l] = key_def->x2[l] * scale + px;
373                 key_def->y2[l] = key_def->y2[l] * scale + py;
374                 key_def->z2[l] = key_def->z2[l] * scale + pz;
375         }
376 }
377
378 static void rotate_yz(double *y, double *z, double angle)
379 {
380         double out_y, out_z;
381
382         out_y = (*y) * cos(angle) - (*z) * sin(angle);
383         out_z = (*y) * sin(angle) + (*z) * cos(angle);
384
385         *y = out_y;
386         *z = out_z;
387 }
388
389 static void rotate_key(double angle, struct key_def *key_def)
390 {
391         int l;
392
393         /* rotate key case */
394         rotate_yz(&key_def->left_top_front_y, &key_def->left_top_front_z, angle);
395         rotate_yz(&key_def->right_top_front_y, &key_def->right_top_front_z, angle);
396         rotate_yz(&key_def->left_top_back_y, &key_def->left_top_back_z, angle);
397         rotate_yz(&key_def->right_top_back_y, &key_def->right_top_back_z, angle);
398         rotate_yz(&key_def->left_bottom_front_y, &key_def->left_bottom_front_z, angle);
399         rotate_yz(&key_def->right_bottom_front_y, &key_def->right_bottom_front_z, angle);
400         rotate_yz(&key_def->left_bottom_back_y, &key_def->left_bottom_back_z, angle);
401         rotate_yz(&key_def->right_bottom_back_y, &key_def->right_bottom_back_z, angle);
402
403         /* rotate line ontop of keys */
404         for (l = 0; l < key_def->lines; l++) {
405                 rotate_yz(&key_def->y1[l], &key_def->z1[l], angle);
406                 rotate_yz(&key_def->y2[l], &key_def->z2[l], angle);
407         }
408 }
409
410 #define KEY_OFFSET      9.5     /* adjust x-posion of keyboard */
411 #define KEY_SIZE_INCH   2.0     /* size of keys */
412 static double keyboard_height, keyboard_distance;
413
414 int init_vr_keyboard(double _keyboard_height, double _keyboard_distance)
415 {
416         double width;
417         int l, k, y, x;
418         int rc;
419         int key, fkey;
420
421         keyboard_height = _keyboard_height;
422         keyboard_distance = _keyboard_distance;
423
424         k = 0;
425         /* for each row in keyboard */
426         for (l = 0, y = 0; keyboard_layout[l]; y++, l++) {
427                 /* for each key in row */
428                 for (x = 0; keyboard_layout[l][x]; x++) {
429                         /* skip spaces, because this is no key */
430                         if (keyboard_layout[l][x] == ' ')
431                                 continue;
432                         width = 1;
433                         key = keyboard_layout[l][x];
434                         fkey = 0;
435                         /* if we have an F-key, this means size * 1.5 */
436                         if (keyboard_layout[l][x] == 'f') {
437                                 if (keyboard_layout[l][x + 1] == 'h')
438                                         width = 2.0; /* help key */
439                                 else
440                                 if (keyboard_layout[l][x + 1] == 'r')
441                                         width = 2.375; /* return key */
442                                 else
443                                 if (keyboard_layout[l][x + 1] == 'e')
444                                         width = 1.5; /* escape key */
445                                 else
446                                 if (keyboard_layout[l][x + 1] == '0')
447                                         width = 1.5; /* F10-key */
448                                 else
449                                         width = 1.25; /* F-key */
450                                 key = keyboard_layout[l][x + 1];
451                                 fkey = 1;
452                         } else
453                         /* if we have a digit after the key, this means different size */
454                         if (keyboard_layout[l][x + 1] > '0')
455                                 width = (double)(keyboard_layout[l][x + 1] - '0');
456                         if (k == MAX_KEYS) {
457                                 print_error("Failed to add key, maximum number keys exeeded, please fix\n");
458                                 return -EINVAL;
459                         }
460                         rc = add_key(key, fkey, width, &keyboard_def.key[k]);
461                         if (rc < 0)
462                                 return -EINVAL;
463                         /* order keys and scale, but keep it at origin */
464                         scale_key(((double)x / 4.0 - KEY_OFFSET) * KEY_SIZE_INCH, 0.0, (double)y * KEY_SIZE_INCH, KEY_SIZE_INCH / 9, &keyboard_def.key[k]);
465                         /* margin for locating keys */
466                         keyboard_def.key[k].margin_left = keyboard_def.key[k].left_bottom_front_x;
467                         keyboard_def.key[k].margin_right = keyboard_def.key[k].right_bottom_front_x;
468                         keyboard_def.key[k].margin_front = keyboard_def.key[k].left_bottom_front_z;
469                         keyboard_def.key[k].margin_back = keyboard_def.key[k].left_bottom_back_z;
470                         /* rotate whole keyboard */
471                         rotate_key(TILT_KEYS / 180.0 * M_PI, &keyboard_def.key[k]);
472                         /* shift keyboard from origin to it's location */
473                         scale_key(0.0, keyboard_height, -keyboard_distance, 1.0, &keyboard_def.key[k]);
474                         k++;
475                         /* skip size information, if any */
476                         if (keyboard_layout[l][x + 1] > ' ')
477                                 x++;
478                 }
479         }
480         keyboard_def.keys = k;
481
482         return 0;
483 }
484
485 static int highlight_k;
486 static double from_x, from_y, from_z;
487 static double to_x, to_y, to_z;
488 static int pointer_valid;
489
490 /* calculate pointer and to what key it points to */
491 int handle_vr_keyboard(double pointer_x, double pointer_y, double pointer_z, double pointer_yaw, double pointer_pitch, enum keycode *key)
492 {
493         int k;
494         struct key_def *key_def;
495
496         pointer_valid = 0;
497         highlight_k = -1;
498
499         /* generate poiting vector */
500         from_x = pointer_x;
501         from_y = pointer_y;
502         from_z = pointer_z;
503         to_x = from_x - sin(pointer_yaw) * cos(pointer_pitch) * 20;
504         to_y = from_y + sin(pointer_pitch) * 20;
505         to_z = from_z - cos(pointer_yaw) * cos(pointer_pitch) * 20;
506
507         /* translate pointer back to keyboard's origin */
508         from_y -= keyboard_height;
509         from_z -= -keyboard_distance;
510         to_y -= keyboard_height;
511         to_z -= -keyboard_distance;
512
513         /* rotate pointer back to horizontal */
514         rotate_yz(&from_y, &from_z, -TILT_KEYS / 180.0 * M_PI);
515         rotate_yz(&to_y, &to_z, -TILT_KEYS / 180.0 * M_PI);
516
517         /* check if pointer points towards keypad plane */
518         if (from_y - 1.0 < 0.0 || to_y > from_y - 1.0)
519                 return 0;
520
521         /* intesct */
522         to_x = (to_x - from_x) / (from_y - to_y) * from_y + from_x;
523         to_z = (to_z - from_z) / (from_y - to_y) * from_y + from_z;
524         to_y = 0.0;
525
526         /* check for margin */
527         if (to_x > 22 || to_x < -22 || to_z > 13 || to_z < -2)
528                 return 0;
529
530         /* find key that we intersect with */
531         for (k = 0; k < keyboard_def.keys; k++) {
532                 key_def = &keyboard_def.key[k];
533                 if (to_x < key_def->margin_left)
534                         continue;
535                 if (to_x > key_def->margin_right)
536                         continue;
537                 if (to_z < key_def->margin_back)
538                         continue;
539                 if (to_z > key_def->margin_front)
540                         continue;
541                 highlight_k = k;
542                 *key = keyboard_codes[k];
543                 break;
544         }
545
546         /* rotate pointer to keyboard's tilt */
547         rotate_yz(&from_y, &from_z, TILT_KEYS / 180.0 * M_PI);
548         rotate_yz(&to_y, &to_z, TILT_KEYS / 180.0 * M_PI);
549
550         /* translate pointer to keyboard's position */
551         from_y += keyboard_height;
552         from_z += -keyboard_distance;
553         to_y += keyboard_height;
554         to_z += -keyboard_distance;
555
556         pointer_valid = 1;
557
558         return 1;
559 }
560
561 /* render keyboard per eye */
562 void render_vr_keyboard(double camera_x, double camera_y)
563 {
564         int k, l, distant_k;
565         int rendered[MAX_KEYS];
566         double dists[MAX_KEYS], dist_x, dist_y, dist;
567         struct key_def *key_def;
568
569         glEnable(GL_CULL_FACE);
570         glFrontFace(GL_CW);
571         glCullFace(GL_FRONT);
572
573         memset(rendered, 0, sizeof(rendered));
574
575         /* calculate distances to keys */
576         for (k = 0; k < keyboard_def.keys; k++) {
577                 key_def = &keyboard_def.key[k];
578                 // FIXME: this works, but we sould only use margin with camera_x
579                 dist_x = (key_def->left_top_front_x + key_def->right_top_front_x) / 2.0 - camera_x;
580                 dist_y = (key_def->left_top_front_z + key_def->left_top_back_z) / 2.0;
581                 dists[k] = sqrt(dist_x * dist_x + dist_y * dist_y);
582         }
583
584         while (1) {
585                 key_def = NULL;
586                 /* search for most distant key */
587                 for (k = 0; k < keyboard_def.keys; k++) {
588                         /* skip keys that have been already rendered */
589                         if (rendered[k])
590                                 continue;
591                         if (!key_def || dists[k] > dist) {
592                                 dist = dists[k];
593                                 key_def = &keyboard_def.key[k];
594                                 distant_k = k;
595                         }
596                 }
597                 /* no unrendered key, we are done */
598                 if (!key_def)
599                         break;
600                 rendered[distant_k] = 1;
601
602                 /* render case of key */
603                 glBegin(GL_QUADS);
604                 /* top plane */
605                 if (distant_k == highlight_k)
606                         glColor4f(0.3, 0.7, 0.7, 1.0);
607                 else
608                         glColor4f(0.5, 0.5, 0.5, 1.0);
609                 glVertex3f(key_def->left_top_back_x, key_def->left_top_back_y, key_def->left_top_back_z);
610                 glVertex3f(key_def->right_top_back_x, key_def->right_top_back_y, key_def->right_top_back_z);
611                 glVertex3f(key_def->right_top_front_x, key_def->right_top_front_y, key_def->right_top_front_z);
612                 glVertex3f(key_def->left_top_front_x, key_def->left_top_front_y, key_def->left_top_front_z);
613                 /* front plane (in front of player) */
614                 if (distant_k == highlight_k)
615                         glColor4f(0.15, 0.2, 0.2, 1.0);
616                 else
617                         glColor4f(0.1, 0.1, 0.1, 1.0);
618                 glVertex3f(key_def->left_top_front_x, key_def->left_top_front_y, key_def->left_top_front_z);
619                 glVertex3f(key_def->right_top_front_x, key_def->right_top_front_y, key_def->right_top_front_z);
620                 glVertex3f(key_def->right_bottom_front_x, key_def->right_bottom_front_y, key_def->right_bottom_front_z);
621                 glVertex3f(key_def->left_bottom_front_x, key_def->left_bottom_front_y, key_def->left_bottom_front_z);
622                 /* back plane (away from player) */
623                 if (distant_k == highlight_k)
624                         glColor4f(0.45, 0.6, 0.6, 1.0);
625                 else
626                         glColor4f(0.3, 0.3, 0.3, 1.0);
627                 glVertex3f(key_def->right_top_back_x, key_def->right_top_back_y, key_def->right_top_back_z);
628                 glVertex3f(key_def->left_top_back_x, key_def->left_top_back_y, key_def->left_top_back_z);
629                 glVertex3f(key_def->left_bottom_back_x, key_def->left_bottom_back_y, key_def->left_bottom_back_z);
630                 glVertex3f(key_def->right_bottom_back_x, key_def->right_bottom_back_y, key_def->right_bottom_back_z);
631                 /* left plane */
632                 if (distant_k == highlight_k)
633                         glColor4f(0.3, 0.4, 0.4, 1.0);
634                 else
635                         glColor4f(0.2, 0.2, 0.2, 1.0);
636                 glVertex3f(key_def->left_top_back_x, key_def->left_top_back_y, key_def->left_top_back_z);
637                 glVertex3f(key_def->left_top_front_x, key_def->left_top_front_y, key_def->left_top_front_z);
638                 glVertex3f(key_def->left_bottom_front_x, key_def->left_bottom_front_y, key_def->left_bottom_front_z);
639                 glVertex3f(key_def->left_bottom_back_x, key_def->left_bottom_back_y, key_def->left_bottom_back_z);
640                 /* right plane */
641                 glVertex3f(key_def->right_top_front_x, key_def->right_top_front_y, key_def->right_top_front_z);
642                 glVertex3f(key_def->right_top_back_x, key_def->right_top_back_y, key_def->right_top_back_z);
643                 glVertex3f(key_def->right_bottom_back_x, key_def->right_bottom_back_y, key_def->right_bottom_back_z);
644                 glVertex3f(key_def->right_bottom_front_x, key_def->right_bottom_front_y, key_def->right_bottom_front_z);
645                 /* no bottom plane, because it is unlikely visible */
646                 glEnd();
647
648                 /* render lines of key */
649                 glColor4f(1.0, 1.0, 1.0, 1.0);
650                 for (l = 0; l < key_def->lines; l++) {
651                         if (key_def->x1[l] == key_def->x2[l] && key_def->z1[l] == key_def->z2[l]) {
652                                 /* just a point */
653                                 glBegin(GL_POINTS);
654                                 glVertex3f(key_def->x1[l], key_def->y1[l], key_def->z1[l]);
655                                 glEnd();
656                         } else {
657                                 glBegin(GL_LINES);
658                                 glVertex3f(key_def->x1[l], key_def->y1[l], key_def->z1[l]);
659                                 glVertex3f(key_def->x2[l], key_def->y2[l], key_def->z2[l]);
660                                 glEnd();
661                         }
662                 }
663         }
664
665         glDisable(GL_CULL_FACE);
666
667         if (!pointer_valid)
668                 return;
669 #if 0
670         /* render pointer as a line from pose to keyboard */
671         glColor4f(1.0, 0.0, 0.0, 1.0);
672         glBegin(GL_LINES);
673         glVertex3f(from_x, from_y, from_z);
674         glVertex3f(to_x, to_y, to_z);
675         glEnd();
676 #endif
677
678 #if 0
679         /* render dot where pose points to */
680         double delta = 0.20;
681         glEnable(GL_BLEND);
682         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
683         glBegin(GL_POLYGON);
684         glColor4f(1.0, 0.0, 0.0, 0.7);
685         glVertex3f(to_x - delta / 2, to_y + delta, to_z);
686         glVertex3f(to_x + delta / 2, to_y + delta, to_z);
687         glVertex3f(to_x + delta, to_y + delta / 2, to_z);
688         glVertex3f(to_x + delta, to_y - delta / 2, to_z);
689         glVertex3f(to_x + delta / 2, to_y - delta, to_z);
690         glVertex3f(to_x - delta / 2, to_y - delta, to_z);
691         glVertex3f(to_x - delta, to_y - delta / 2, to_z);
692         glVertex3f(to_x - delta, to_y + delta / 2, to_z);
693         glEnd();
694         glDisable(GL_BLEND);
695 #endif
696
697 #if 1
698         /* render a 'shot' */
699         double delta = 0.50;
700         glBegin(GL_LINES);
701         glColor4f(1.0, 1.0, 1.0, 1.0);
702         glVertex3f(to_x - delta / 2, to_y + delta + delta, to_z - delta / 2 + delta);
703         glVertex3f(to_x + delta / 2, to_y - delta + delta, to_z + delta / 2 + delta);
704         glVertex3f(to_x + delta / 2, to_y + delta + delta, to_z - delta / 2 + delta);
705         glVertex3f(to_x - delta / 2, to_y - delta + delta, to_z + delta / 2 + delta);
706         glVertex3f(to_x - delta / 2, to_y + delta + delta, to_z + delta / 2 + delta);
707         glVertex3f(to_x + delta / 2, to_y - delta + delta, to_z - delta / 2 + delta);
708         glVertex3f(to_x + delta / 2, to_y + delta + delta, to_z + delta / 2 + delta);
709         glVertex3f(to_x - delta / 2, to_y - delta + delta, to_z - delta / 2 + delta);
710
711         glVertex3f(to_x - delta, to_y + delta / 2 + delta, to_z - delta / 2 + delta);
712         glVertex3f(to_x + delta, to_y - delta / 2 + delta, to_z + delta / 2 + delta);
713         glVertex3f(to_x - delta, to_y - delta / 2 + delta, to_z - delta / 2 + delta);
714         glVertex3f(to_x + delta, to_y + delta / 2 + delta, to_z + delta / 2 + delta);
715         glVertex3f(to_x - delta, to_y + delta / 2 + delta, to_z + delta / 2 + delta);
716         glVertex3f(to_x + delta, to_y - delta / 2 + delta, to_z - delta / 2 + delta);
717         glVertex3f(to_x - delta, to_y - delta / 2 + delta, to_z + delta / 2 + delta);
718         glVertex3f(to_x + delta, to_y + delta / 2 + delta, to_z - delta / 2 + delta);
719
720         glVertex3f(to_x - delta / 2, to_y + delta / 2 + delta, to_z + delta + delta);
721         glVertex3f(to_x + delta / 2, to_y - delta / 2 + delta, to_z - delta + delta);
722         glVertex3f(to_x + delta / 2, to_y + delta / 2 + delta, to_z + delta + delta);
723         glVertex3f(to_x - delta / 2, to_y - delta / 2 + delta, to_z - delta + delta);
724         glVertex3f(to_x - delta / 2, to_y - delta / 2 + delta, to_z + delta + delta);
725         glVertex3f(to_x + delta / 2, to_y + delta / 2 + delta, to_z - delta + delta);
726         glVertex3f(to_x + delta / 2, to_y - delta / 2 + delta, to_z + delta + delta);
727         glVertex3f(to_x - delta / 2, to_y + delta / 2 + delta, to_z - delta + delta);
728         glEnd();
729 #endif
730 }
731