OVR: Improved keyboard, so it can be used with touch and xbox controller
[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_KEYBOARDS   2       /* maximum number of keyboards to we have */
32 #define MAX_KEYS        64      /* maximum number of keys per keyboard */
33 #define MAX_KEY_LINES   32      /* maximum number of lines on each key */
34 #define TILT_KEYBOARD           /* keyboard is tilted up from horzontal x-z-plane to vertical x-y-plane */
35
36 /*
37  * The keys are defined by coordinates that are described by the following
38  * digits:
39  *
40  * a  b  c  d  e
41  *
42  * f  g  h  i  j
43  *
44  * k  l  m  n  o
45  *
46  * p  q  r  s  t
47  *
48  * u  v  w  x  y
49  *
50  * The lines are defined from digit to digit to digit.... To start with a
51  * new line (not connected to the previous one, add ' ' (space).
52  *
53  */
54
55 static struct key_font {
56         char key;
57         const char *font;
58 } key_font[] = {
59         { '0', "bdjtxvpfb qi" },
60         { '1', "gcw vx" },
61         { '2', "fbdjnlpuy" },
62         { '3', "fbdjntxvp ln" },
63         { '4', "ako hw" },
64         { '5', "eakntxu" },
65         { '6', "jdbfpvxtnk" },
66         { '7', "aemw" },
67         { '8', "lfbdjntxvpln" },
68         { '9', "jnlfbdjtxvp" },
69         { 'A', "ukoy kco" },
70         { 'B', "knjdauxtn" },
71         { 'C', "jdbfpvxt" },
72         { 'D', "adjtxua" },
73         { 'E', "eauy km" },
74         { 'F', "eau km" },
75         { 'G', "jdbfpvxt yom" },
76         { 'H', "au ey ko" },
77         { 'I', "bd vx cw" },
78         { 'J', "aetxvpk" },
79         { 'K', "au emy km" },
80         { 'L', "auy" },
81         { 'M', "uamey" },
82         { 'N', "uaye" },
83         { 'O', "bdjtxvpfb" },
84         { 'P', "uadjnk" },
85         { 'Q', "bdjtxvpfb ys" },
86         { 'R', "uadjnk my" },
87         { 'S', "jdbflntxvp" },
88         { 'T', "ae cw" },
89         { 'U', "apvxte" },
90         { 'V', "akwoe" },
91         { 'W', "aumye" },
92         { 'X', "ay ue" },
93         { 'Y', "ame mw" },
94         { 'Z', "aeuy" },
95         { 'u', "cw kco" },
96         { 'd', "cw kwo" },
97         { 'l', "ko ckw" },
98         { 'r', "ko cow" },
99         { '.', "rr" },
100         { ',', "rv" },
101         { '+', "cw ko" },
102         { '-', "ko" },
103         { '*', "ko ay ue" },
104         { 's', "" }, /* space */
105         { 'b', "beyvkb gs qi" },
106         { 'e', "dsp pl pv" },
107         { ' ', "" },
108         { 0, NULL }
109 };
110
111 /*
112  * f-keys are 25 percent larger, so 4 f-keys are as wide as 5 regular keys.
113  * This is why f-keys use 5 steps instead of four (regular keys).
114  */
115
116 static const char *keyboard_layout[] = {
117         "1   2   3   4   5   6   7   8   9   0   G",
118         "    fh      fr                           ",
119         "    f1    f2    f0     7   8   9   *     ",
120         "                       4   5   6   -     ",
121         "           u           1   2   3   +     ",
122         "       l   d   r       02      e2        ",
123         NULL, /* end of keyboard */
124         "1   2   3   4   5   6   7   8   9   0   b",
125         "  Q   W   E   R   T   Y   U   I   O   P  ",
126         "   A   S   D   F   G   H   J   K   L   e ",
127         "     Z   X   C   V   B   N   M   ,   .   ",
128         "          s6                             ",
129         NULL, /* end of keyboard */
130         NULL, /* end of all keyboards */
131 };
132
133 static enum keycode keyboard_codes_1[] = {
134         KEYCODE_1, KEYCODE_2, KEYCODE_3, KEYCODE_4, KEYCODE_5, KEYCODE_6, KEYCODE_7, KEYCODE_8, KEYCODE_9, KEYCODE_0, KEYCODE_g,
135         KEYCODE_HELP, KEYCODE_RETURN,
136         KEYCODE_F1, KEYCODE_F2, KEYCODE_F10, KEYCODE_KP_7, KEYCODE_KP_8, KEYCODE_KP_9, KEYCODE_KP_MULTIPLY,
137         KEYCODE_KP_4, KEYCODE_KP_5, KEYCODE_KP_6, KEYCODE_KP_MINUS,
138         KEYCODE_UP, KEYCODE_KP_1, KEYCODE_KP_2, KEYCODE_KP_3, KEYCODE_KP_PLUS,
139         KEYCODE_LEFT, KEYCODE_DOWN, KEYCODE_RIGHT, KEYCODE_KP_0, KEYCODE_KP_ENTER,
140 };
141
142 static enum keycode keyboard_codes_2[] = {
143         KEYCODE_1, KEYCODE_2, KEYCODE_3, KEYCODE_4, KEYCODE_5, KEYCODE_6, KEYCODE_7, KEYCODE_8, KEYCODE_9, KEYCODE_0, KEYCODE_BACKSPACE,
144         KEYCODE_q, KEYCODE_w, KEYCODE_e, KEYCODE_r, KEYCODE_t, KEYCODE_y, KEYCODE_u, KEYCODE_i, KEYCODE_o, KEYCODE_p,
145         KEYCODE_a, KEYCODE_s, KEYCODE_d, KEYCODE_f, KEYCODE_g, KEYCODE_h, KEYCODE_j, KEYCODE_k, KEYCODE_l, KEYCODE_RETURN,
146         KEYCODE_z, KEYCODE_x, KEYCODE_c, KEYCODE_v, KEYCODE_b, KEYCODE_n, KEYCODE_m, KEYCODE_COMMA, KEYCODE_PERIOD,
147         KEYCODE_SPACE,
148 };
149
150 static enum keycode *keyboard_codes[] = {
151         keyboard_codes_1, keyboard_codes_2,
152 };
153
154 /* definition of keys with coordinates for rendering */
155
156 struct key_def {
157         char key;
158         int fkey;
159         double left_top_x, right_top_x;
160         double top_y;
161         double front_top_z, back_top_z;
162         double left_bottom_x, right_bottom_x;
163         double bottom_y;
164         double front_bottom_z, back_bottom_z;
165         double x1[MAX_KEY_LINES], y1[MAX_KEY_LINES], z1[MAX_KEY_LINES];
166         double x2[MAX_KEY_LINES], y2[MAX_KEY_LINES], z2[MAX_KEY_LINES];
167         int lines;
168 };
169
170 /* definition for each keyboard */
171 static struct keyboard_def {
172         struct key_def key[MAX_KEYS];
173         int keys;
174 } keyboard_def[MAX_KEYBOARDS];
175
176 static int keyboards = 0;
177
178 /*
179  * add key to keyboard_def[].key structure
180  *
181  *-4  -2     0     2 3 4
182  * +-------------------+ 4
183  * | +---------------+ | 3
184  * | | a  b  c  d  e | | 2
185  * | | f  g  h  i  j | | 1
186  * | | k  l  m  n  o | | 0
187  * | | p  q  r  s  t | | -1
188  * | | u  v  w  x  y | | -2
189  * | +---------------+ | -3
190  * +-------------------+ -4
191  *        (front)
192  */
193
194 static int add_key(char key, int fkey, double width, struct key_def *key_def)
195 {
196         int d, l, f, i;
197         double font_scale = 1.0, font_offset = 0.0;
198
199         memset(key_def, 0, sizeof(*key_def));
200
201         key_def->key = key;
202         key_def->fkey = fkey;
203
204         /* key case (see layout in the description above) */
205         key_def->left_top_x = -3.0;
206         key_def->right_top_x = 3.0 + (width - 1.0) * 9.0;
207         key_def->top_y = 0;
208         key_def->front_top_z = 3.0;
209         key_def->back_top_z = -3.0;
210         key_def->left_bottom_x = -4.0;
211         key_def->right_bottom_x = 4.0 + (width - 1.0) * 9.0;
212         key_def->bottom_y = -4.0;
213         key_def->front_bottom_z = 4.0;
214         key_def->back_bottom_z = -4.0;
215
216         /* lines to be drawn ontop of the key (see layout in the description above) */
217         l = 0;
218         /* up to 4 letters/digits are displayed on key */
219         for (d = 0; d < 6; d++) {
220                 if (!key_def->fkey) {
221                         /* render regular key */
222                         if (d == 0)
223                                 key = key_def->key;
224                         else
225                                 break;
226                 } else {
227                         /* render F-key */
228                         if (d == 0) {
229                                 font_scale = 0.5;
230                                 font_offset = -0.25;
231                                 if (key_def->key == 'h')
232                                         key = 'H';
233                                 else if (key_def->key == 'r')
234                                         key = 'R';
235                                 else
236                                         key = 'F';
237                         }
238                         else if (d == 1) {
239                                 font_offset += 2.5;
240                                 if (key_def->key == 'h')
241                                         key = 'E';
242                                 else if (key_def->key == 'r')
243                                         key = 'E';
244                                 else if (key_def->key != '0')
245                                         key = key_def->key;
246                                 else
247                                         key = '1';
248                         }
249                         else if (d == 2) {
250                                 font_offset += 2.5;
251                                 if (key_def->key == 'h')
252                                         key = 'L';
253                                 else if (key_def->key == 'r')
254                                         key = 'T';
255                                 else if (key_def->key != '0')
256                                         break;
257                                 else
258                                         key = '0';
259                         }
260                         else if (d == 3) {
261                                 font_offset += 2.5;
262                                 if (key_def->key == 'h')
263                                         key = 'P';
264                                 else if (key_def->key == 'r')
265                                         key = 'U';
266                                 else
267                                         break;
268                         }
269                         else if (d == 4) {
270                                 font_offset += 2.5;
271                                 if (key_def->key == 'r')
272                                         key = 'R';
273                                 else
274                                         break;
275                         }
276                         else if (d == 5) {
277                                 font_offset += 2.5;
278                                 if (key_def->key == 'r')
279                                         key = 'N';
280                                 else
281                                         break;
282                         }
283                 }
284                 /* search for key font */
285                 for (f = 0; key_font[f].key; f++) {
286                         if (key_font[f].key == key)
287                                 break;
288                 }
289                 if (!key_font[f].key) {
290                         print_error("Failed to find keyboard character '%c' in key_font, please fix\n", key);
291                         return -EINVAL;
292                 }
293                 /* generate lines */
294                 i = 0;
295                 while (key_font[f].font[i] && key_font[f].font[i + 1]) {
296                         /* skip spaces, but this should not happen */
297                         if (key_font[f].font[i] == ' ') {
298                                 i++;
299                                 continue;
300                         }
301                         /* the second character is space, so we start over with a new line sequence */
302                         if (key_font[f].font[i + 1] == ' ') {
303                                 i += 2;
304                                 continue;
305                         }
306                         /* add line */
307                         if (l == MAX_KEY_LINES) {
308                                 print_error("Failed to add key definition, maximum number of lines exeeded, please fix\n");
309                                 return -EINVAL;
310                         }
311                         key_def->x1[l] = (double)(((key_font[f].font[i] - 'a') % 5) - 2) * font_scale + font_offset;
312                         key_def->y1[l] = 0;
313                         key_def->z1[l] = (double)((key_font[f].font[i] - 'a') / 5) - 2;
314                         key_def->x2[l] = (double)(((key_font[f].font[i + 1] - 'a') % 5) - 2) * font_scale + font_offset;
315                         key_def->y2[l] = 0;
316                         key_def->z2[l] = (double)((key_font[f].font[i + 1] - 'a') / 5) - 2;
317                         l++;
318                         i++;
319                 }
320         }
321         key_def->lines = l;
322
323         return 0;
324 }
325
326 static void scale_key(double px, double py, double pz, double scale, struct key_def *key_def)
327 {
328         int l;
329
330         /* scale and translate key case */
331         key_def->left_top_x = key_def->left_top_x * scale + px;
332         key_def->right_top_x = key_def->right_top_x * scale + px;
333         key_def->top_y = key_def->top_y * scale + py;
334         key_def->front_top_z = key_def->front_top_z * scale + pz;
335         key_def->back_top_z = key_def->back_top_z * scale + pz;
336         key_def->left_bottom_x = key_def->left_bottom_x * scale + px;
337         key_def->right_bottom_x = key_def->right_bottom_x * scale + px;
338         key_def->bottom_y = key_def->bottom_y * scale + py;
339         key_def->front_bottom_z = key_def->front_bottom_z * scale + pz;
340         key_def->back_bottom_z = key_def->back_bottom_z * scale + pz;
341
342         /* scale and translate line ontop of keys */
343         for (l = 0; l < key_def->lines; l++) {
344                 key_def->x1[l] = key_def->x1[l] * scale + px;
345                 key_def->y1[l] = key_def->y1[l] * scale + py;
346                 key_def->z1[l] = key_def->z1[l] * scale + pz;
347                 key_def->x2[l] = key_def->x2[l] * scale + px;
348                 key_def->y2[l] = key_def->y2[l] * scale + py;
349                 key_def->z2[l] = key_def->z2[l] * scale + pz;
350         }
351 }
352
353 #define KEY_SIZE_INCH   3.0
354
355 int init_vr_keyboard(double keyboard_height, double keyboard_distance)
356 {
357         double width;
358         int l, k, y, x;
359         int rc;
360         int key, fkey;
361
362         l = 0;
363         /* count all keyboards */
364         while (keyboard_layout[l]) {
365                 k = 0;
366                 /* for each row in keyboard */
367                 for (y = 0; keyboard_layout[l]; y++, l++) {
368                         /* for each key in row */
369                         for (x = 0; keyboard_layout[l][x]; x++) {
370                                 /* skip spaces, because this is no key */
371                                 if (keyboard_layout[l][x] == ' ')
372                                         continue;
373                                 width = 1;
374                                 key = keyboard_layout[l][x];
375                                 fkey = 0;
376                                 /* if we have an F-key, this means size * 1.5 */
377                                 if (keyboard_layout[l][x] == 'f') {
378                                         if (keyboard_layout[l][x + 1] == 'h')
379                                                 width = 2.0; /* help key */
380                                         else
381                                         if (keyboard_layout[l][x + 1] == 'r')
382                                                 width = 2.5; /* return key */
383                                         else
384                                                 width = 1.5; /* f-key */
385                                         key = keyboard_layout[l][x + 1];
386                                         fkey = 1;
387                                 } else
388                                 /* if we have a digit after the key, this means different size */
389                                 if (keyboard_layout[l][x + 1] > '0')
390                                         width = (double)(keyboard_layout[l][x + 1] - '0');
391                                 rc = add_key(key, fkey, width, &keyboard_def[keyboards].key[k]);
392                                 if (rc < 0)
393                                         return -EINVAL;
394 #ifdef TILT_KEYBOARD
395                                 scale_key(((double)x / 4.0 - 5.0) * KEY_SIZE_INCH, -keyboard_distance, (double)y * KEY_SIZE_INCH - keyboard_height, KEY_SIZE_INCH / 9, &keyboard_def[keyboards].key[k]);
396 #else
397                                 scale_key(((double)x / 4.0 - 5.0) * KEY_SIZE_INCH, keyboard_height, (double)y * KEY_SIZE_INCH - keyboard_distance, KEY_SIZE_INCH / 9, &keyboard_def[keyboards].key[k]);
398 #endif
399                                 k++;
400                                 /* skip size information, if any */
401                                 if (keyboard_layout[l][x + 1] > ' ')
402                                         x++;
403                         }
404                 }
405                 keyboard_def[keyboards].keys = k;
406                 keyboards++;
407                 l++;
408         }
409
410         return 0;
411 }
412
413 static int highlight_k;
414 static double from_x, from_y, from_z;
415 static double to_x, to_y, to_z;
416 static int pointer_valid;
417
418 /* calculate pointer and to what key it points to */
419 void handle_vr_keyboard(int keyboard, double pointer_x, double pointer_y, double pointer_z, double pointer_yaw, double pointer_pitch, enum keycode *key)
420 {
421         int k;
422         struct key_def *key_def;
423 #ifdef TILT_KEYBOARD
424         double keyboard_dist = keyboard_def[keyboard].key[0].y1[0]; /* just get the dist from first line of first key */
425 #else
426         double keyboard_height = keyboard_def[keyboard].key[0].y1[0]; /* just get the height from first line of first key */
427 #endif
428
429         /* generate poiting vector */
430         from_x = pointer_x;
431         from_y = pointer_y;
432         from_z = pointer_z;
433         to_x = from_x - sin(pointer_yaw) * cos(pointer_pitch) * 20;
434         to_y = from_y + sin(pointer_pitch) * 20;
435         to_z = from_z - cos(pointer_yaw) * cos(pointer_pitch) * 20;
436         pointer_valid = 0;
437
438         /* if pointer points down, intersect with keyboard */
439         highlight_k = -1;
440 #ifdef TILT_KEYBOARD
441         if (from_z - 1.0 > keyboard_dist && to_z < from_z - 1.0) {
442                 pointer_valid = 1;
443                 to_x = (to_x - from_x) / (from_z - to_z) * (from_z - keyboard_dist) + from_x;
444                 to_y = (to_y - from_y) / (from_z - to_z) * (from_z - keyboard_dist) + from_y;
445                 to_z = keyboard_dist;
446
447                 /* find key that we intersect with */
448                 for (k = 0; k < keyboard_def[keyboard].keys; k++) {
449                         key_def = &keyboard_def[keyboard].key[k];
450                         if (to_x < key_def->left_top_x)
451                                 continue;
452                         if (to_x > key_def->right_top_x)
453                                 continue;
454                         if (-to_y < key_def->back_top_z)
455                                 continue;
456                         if (-to_y > key_def->front_top_z)
457                                 continue;
458                         highlight_k = k;
459                         *key = keyboard_codes[keyboard][k];
460                         break;
461                 }
462         }
463 #else
464         if (from_y - 1.0 > keyboard_height && to_y < from_y - 1.0) {
465                 pointer_valid = 1;
466                 to_x = (to_x - from_x) / (from_y - to_y) * (from_y - keyboard_height) + from_x;
467                 to_z = (to_z - from_z) / (from_y - to_y) * (from_y - keyboard_height) + from_z;
468                 to_y = keyboard_height;
469
470                 /* find key that we intersect with */
471                 for (k = 0; k < keyboard_def[keyboard].keys; k++) {
472                         key_def = &keyboard_def[keyboard].key[k];
473                         if (to_x < key_def->left_top_x)
474                                 continue;
475                         if (to_x > key_def->right_top_x)
476                                 continue;
477                         if (to_z < key_def->back_top_z)
478                                 continue;
479                         if (to_z > key_def->front_top_z)
480                                 continue;
481                         highlight_k = k;
482                         *key = keyboard_codes[keyboard][k];
483                         break;
484                 }
485         }
486 #endif
487 }
488
489 #ifdef TILT_KEYBOARD
490 #define FLIP_YZ(y, z) -z, y
491 #else
492 #define FLIP_YZ(y, z) y, z
493 #endif
494
495 /* render keyboard per eye */
496 void render_vr_keyboard(int keyboard, double camera_x, double camera_y)
497 {
498         int k, l, distant_k;
499         int rendered[MAX_KEYS];
500         double dists[MAX_KEYS], dist_x, dist_y, dist;
501         struct key_def *key_def;
502
503         glEnable(GL_CULL_FACE);
504         glFrontFace(GL_CW);
505         glCullFace(GL_FRONT);
506
507         memset(rendered, 0, sizeof(rendered));
508
509         /* calculate distances to keys */
510         for (k = 0; k < keyboard_def[keyboard].keys; k++) {
511                 key_def = &keyboard_def[keyboard].key[k];
512 #ifdef TILT_KEYBOARD
513                 dist_x = (key_def->left_top_x + key_def->right_top_x) / 2.0 - camera_x;
514                 dist_y = (key_def->front_top_z + key_def->back_top_z) / 2.0 + camera_y;
515 #else
516                 dist_x = (key_def->left_top_x + key_def->right_top_x) / 2.0 - camera_x;
517                 dist_y = (key_def->front_top_z + key_def->back_top_z) / 2.0;
518 #endif
519                 dists[k] = sqrt(dist_x * dist_x + dist_y * dist_y);
520         }
521
522         while (1) {
523                 key_def = NULL;
524                 /* search for most distant key */
525                 for (k = 0; k < keyboard_def[keyboard].keys; k++) {
526                         /* skip keys that have been already rendered */
527                         if (rendered[k])
528                                 continue;
529                         if (!key_def || dists[k] > dist) {
530                                 dist = dists[k];
531                                 key_def = &keyboard_def[keyboard].key[k];
532                                 distant_k = k;
533                         }
534                 }
535                 /* no unrendered key, we are done */
536                 if (!key_def)
537                         break;
538                 rendered[distant_k] = 1;
539
540                 /* render case of key */
541                 glBegin(GL_QUADS);
542                 /* top plane */
543                 if (distant_k == highlight_k)
544                         glColor4f(0.0, 0.7, 0.7, 1.0);
545                 else
546                         glColor4f(0.5, 0.5, 0.5, 1.0);
547                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
548                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
549                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
550                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
551                 /* front plane (in front of player) */
552                 glColor4f(0.1, 0.1, 0.1, 1.0);
553                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
554                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
555                 glVertex3f(key_def->right_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->front_bottom_z));
556                 glVertex3f(key_def->left_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->front_bottom_z));
557                 /* back plane (away from player) */
558                 glColor4f(0.3, 0.3, 0.3, 1.0);
559                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
560                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
561                 glVertex3f(key_def->left_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->back_bottom_z));
562                 glVertex3f(key_def->right_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->back_bottom_z));
563                 /* left plane */
564                 glColor4f(0.2, 0.2, 0.2, 1.0);
565                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
566                 glVertex3f(key_def->left_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
567                 glVertex3f(key_def->left_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->front_bottom_z));
568                 glVertex3f(key_def->left_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->back_bottom_z));
569                 /* right plane */
570                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->front_top_z));
571                 glVertex3f(key_def->right_top_x, FLIP_YZ(key_def->top_y, key_def->back_top_z));
572                 glVertex3f(key_def->right_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->back_bottom_z));
573                 glVertex3f(key_def->right_bottom_x, FLIP_YZ(key_def->bottom_y, key_def->front_bottom_z));
574                 /* no bottom plane, because it is unlikely visible */
575                 glEnd();
576
577                 /* render lines of key */
578                 glColor4f(1.0, 1.0, 1.0, 1.0);
579                 for (l = 0; l < key_def->lines; l++) {
580                         if (key_def->x1[l] == key_def->x2[l] && key_def->z1[l] == key_def->z2[l]) {
581                                 /* just a point */
582                                 glBegin(GL_POINTS);
583                                 glVertex3f(key_def->x1[l], FLIP_YZ(key_def->y1[l], key_def->z1[l]));
584                                 glEnd();
585                         } else {
586                                 glBegin(GL_LINES);
587                                 glVertex3f(key_def->x1[l], FLIP_YZ(key_def->y1[l], key_def->z1[l]));
588                                 glVertex3f(key_def->x2[l], FLIP_YZ(key_def->y2[l], key_def->z2[l]));
589                                 glEnd();
590                         }
591                 }
592         }
593
594         glDisable(GL_CULL_FACE);
595
596         if (!pointer_valid)
597                 return;
598         if (to_x > 25 || to_x < -25 || to_y > 20 || to_y < -20)
599                 return;
600 #if 0
601         /* render pointer as a line from pose to keyboard */
602         glColor4f(1.0, 0.0, 0.0, 1.0);
603         glBegin(GL_LINES);
604         glVertex3f(from_x, from_y, from_z);
605         glVertex3f(to_x, to_y, to_z);
606         glEnd();
607 #endif
608
609 #if 0
610         /* render dot where pose points to */
611         double delta = 0.20;
612         glEnable(GL_BLEND);
613         glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
614         glBegin(GL_POLYGON);
615         glColor4f(1.0, 0.0, 0.0, 0.7);
616         glVertex3f(to_x - delta / 2, to_y + delta, to_z);
617         glVertex3f(to_x + delta / 2, to_y + delta, to_z);
618         glVertex3f(to_x + delta, to_y + delta / 2, to_z);
619         glVertex3f(to_x + delta, to_y - delta / 2, to_z);
620         glVertex3f(to_x + delta / 2, to_y - delta, to_z);
621         glVertex3f(to_x - delta / 2, to_y - delta, to_z);
622         glVertex3f(to_x - delta, to_y - delta / 2, to_z);
623         glVertex3f(to_x - delta, to_y + delta / 2, to_z);
624         glEnd();
625         glDisable(GL_BLEND);
626 #endif
627
628 #if 1
629         /* render a 'shot' */
630         double delta = 0.50;
631         glBegin(GL_LINES);
632         glColor4f(1.0, 1.0, 1.0, 1.0);
633         glVertex3f(to_x - delta / 2, to_y + delta, to_z - delta / 2 + delta);
634         glVertex3f(to_x + delta / 2, to_y - delta, to_z + delta / 2 + delta);
635         glVertex3f(to_x + delta / 2, to_y + delta, to_z - delta / 2 + delta);
636         glVertex3f(to_x - delta / 2, to_y - delta, to_z + delta / 2 + delta);
637         glVertex3f(to_x - delta / 2, to_y + delta, to_z + delta / 2 + delta);
638         glVertex3f(to_x + delta / 2, to_y - delta, to_z - delta / 2 + delta);
639         glVertex3f(to_x + delta / 2, to_y + delta, to_z + delta / 2 + delta);
640         glVertex3f(to_x - delta / 2, to_y - delta, to_z - delta / 2 + delta);
641
642         glVertex3f(to_x - delta, to_y + delta / 2, to_z - delta / 2 + delta);
643         glVertex3f(to_x + delta, to_y - delta / 2, to_z + delta / 2 + delta);
644         glVertex3f(to_x - delta, to_y - delta / 2, to_z - delta / 2 + delta);
645         glVertex3f(to_x + delta, to_y + delta / 2, to_z + delta / 2 + delta);
646         glVertex3f(to_x - delta, to_y + delta / 2, to_z + delta / 2 + delta);
647         glVertex3f(to_x + delta, to_y - delta / 2, to_z - delta / 2 + delta);
648         glVertex3f(to_x - delta, to_y - delta / 2, to_z + delta / 2 + delta);
649         glVertex3f(to_x + delta, to_y + delta / 2, to_z - delta / 2 + delta);
650
651         glVertex3f(to_x - delta / 2, to_y + delta / 2, to_z + delta + delta);
652         glVertex3f(to_x + delta / 2, to_y - delta / 2, to_z - delta + delta);
653         glVertex3f(to_x + delta / 2, to_y + delta / 2, to_z + delta + delta);
654         glVertex3f(to_x - delta / 2, to_y - delta / 2, to_z - delta + delta);
655         glVertex3f(to_x - delta / 2, to_y - delta / 2, to_z + delta + delta);
656         glVertex3f(to_x + delta / 2, to_y + delta / 2, to_z - delta + delta);
657         glVertex3f(to_x + delta / 2, to_y - delta / 2, to_z + delta + delta);
658         glVertex3f(to_x - delta / 2, to_y + delta / 2, to_z - delta + delta);
659         glEnd();
660 #endif
661 }
662