3 * (C) 2018 by Andreas Eversberg <jolly@eversberg.eu>
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.
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.
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/>.
25 #include "../../include/keycodes.h"
26 #include "../libsdl/print.h"
28 #define GL3_PROTOTYPES 1
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 */
37 * The keys are defined by coordinates that are described by the following
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).
55 static struct key_font {
59 { '0', "bdjtxvpfb qi" },
62 { '3', "fbdjntxvp ln" },
65 { '6', "jdbfpvxtnk" },
67 { '8', "lfbdjntxvpln" },
68 { '9', "jnlfbdjtxvp" },
75 { 'G', "jdbfpvxt yom" },
85 { 'Q', "bdjtxvpfb ys" },
87 { 'S', "jdbflntxvp" },
104 { 's', "" }, /* space */
105 { 'b', "beyvkb gs qi" },
106 { 'e', "dsp pl pv" },
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).
116 static const char *keyboard_layout[] = {
117 "1 2 3 4 5 6 7 8 9 0 G",
119 " f1 f2 f0 7 8 9 * ",
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 , . ",
129 NULL, /* end of keyboard */
130 NULL, /* end of all keyboards */
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,
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,
150 static enum keycode *keyboard_codes[] = {
151 keyboard_codes_1, keyboard_codes_2,
154 /* definition of keys with coordinates for rendering */
159 double left_top_x, right_top_x;
161 double front_top_z, back_top_z;
162 double left_bottom_x, right_bottom_x;
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];
170 /* definition for each keyboard */
171 static struct keyboard_def {
172 struct key_def key[MAX_KEYS];
174 } keyboard_def[MAX_KEYBOARDS];
176 static int keyboards = 0;
179 * add key to keyboard_def[].key structure
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
194 static int add_key(char key, int fkey, double width, struct key_def *key_def)
197 double font_scale = 1.0, font_offset = 0.0;
199 memset(key_def, 0, sizeof(*key_def));
202 key_def->fkey = fkey;
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;
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;
216 /* lines to be drawn ontop of the key (see layout in the description above) */
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 */
231 if (key_def->key == 'h')
233 else if (key_def->key == 'r')
240 if (key_def->key == 'h')
242 else if (key_def->key == 'r')
244 else if (key_def->key != '0')
251 if (key_def->key == 'h')
253 else if (key_def->key == 'r')
255 else if (key_def->key != '0')
262 if (key_def->key == 'h')
264 else if (key_def->key == 'r')
271 if (key_def->key == 'r')
278 if (key_def->key == 'r')
284 /* search for key font */
285 for (f = 0; key_font[f].key; f++) {
286 if (key_font[f].key == key)
289 if (!key_font[f].key) {
290 print_error("Failed to find keyboard character '%c' in key_font, please fix\n", key);
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] == ' ') {
301 /* the second character is space, so we start over with a new line sequence */
302 if (key_font[f].font[i + 1] == ' ') {
307 if (l == MAX_KEY_LINES) {
308 print_error("Failed to add key definition, maximum number of lines exeeded, please fix\n");
311 key_def->x1[l] = (double)(((key_font[f].font[i] - 'a') % 5) - 2) * font_scale + font_offset;
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;
316 key_def->z2[l] = (double)((key_font[f].font[i + 1] - 'a') / 5) - 2;
326 static void scale_key(double px, double py, double pz, double scale, struct key_def *key_def)
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;
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;
353 #define KEY_SIZE_INCH 3.0
355 int init_vr_keyboard(double keyboard_height, double keyboard_distance)
363 /* count all keyboards */
364 while (keyboard_layout[l]) {
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] == ' ')
374 key = keyboard_layout[l][x];
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 */
381 if (keyboard_layout[l][x + 1] == 'r')
382 width = 2.5; /* return key */
384 width = 1.5; /* f-key */
385 key = keyboard_layout[l][x + 1];
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]);
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]);
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]);
400 /* skip size information, if any */
401 if (keyboard_layout[l][x + 1] > ' ')
405 keyboard_def[keyboards].keys = k;
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;
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)
422 struct key_def *key_def;
424 double keyboard_dist = keyboard_def[keyboard].key[0].y1[0]; /* just get the dist from first line of first key */
426 double keyboard_height = keyboard_def[keyboard].key[0].y1[0]; /* just get the height from first line of first key */
429 /* generate poiting vector */
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;
438 /* if pointer points down, intersect with keyboard */
441 if (from_z - 1.0 > keyboard_dist && to_z < from_z - 1.0) {
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;
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)
452 if (to_x > key_def->right_top_x)
454 if (-to_y < key_def->back_top_z)
456 if (-to_y > key_def->front_top_z)
459 *key = keyboard_codes[keyboard][k];
464 if (from_y - 1.0 > keyboard_height && to_y < from_y - 1.0) {
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;
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)
475 if (to_x > key_def->right_top_x)
477 if (to_z < key_def->back_top_z)
479 if (to_z > key_def->front_top_z)
482 *key = keyboard_codes[keyboard][k];
490 #define FLIP_YZ(y, z) -z, y
492 #define FLIP_YZ(y, z) y, z
495 /* render keyboard per eye */
496 void render_vr_keyboard(int keyboard, double camera_x, double camera_y)
499 int rendered[MAX_KEYS];
500 double dists[MAX_KEYS], dist_x, dist_y, dist;
501 struct key_def *key_def;
503 glEnable(GL_CULL_FACE);
505 glCullFace(GL_FRONT);
507 memset(rendered, 0, sizeof(rendered));
509 /* calculate distances to keys */
510 for (k = 0; k < keyboard_def[keyboard].keys; k++) {
511 key_def = &keyboard_def[keyboard].key[k];
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;
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;
519 dists[k] = sqrt(dist_x * dist_x + dist_y * dist_y);
524 /* search for most distant key */
525 for (k = 0; k < keyboard_def[keyboard].keys; k++) {
526 /* skip keys that have been already rendered */
529 if (!key_def || dists[k] > dist) {
531 key_def = &keyboard_def[keyboard].key[k];
535 /* no unrendered key, we are done */
538 rendered[distant_k] = 1;
540 /* render case of key */
543 if (distant_k == highlight_k)
544 glColor4f(0.0, 0.7, 0.7, 1.0);
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));
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));
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 */
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]) {
583 glVertex3f(key_def->x1[l], FLIP_YZ(key_def->y1[l], key_def->z1[l]));
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]));
594 glDisable(GL_CULL_FACE);
598 if (to_x > 25 || to_x < -25 || to_y > 20 || to_y < -20)
601 /* render pointer as a line from pose to keyboard */
602 glColor4f(1.0, 0.0, 0.0, 1.0);
604 glVertex3f(from_x, from_y, from_z);
605 glVertex3f(to_x, to_y, to_z);
610 /* render dot where pose points to */
613 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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);
629 /* render a 'shot' */
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);
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);
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);