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_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 */
36 * The keys are defined by coordinates that are described by the following
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).
54 static struct key_font {
58 { '0', "bdjtxvpfb qi" },
61 { '3', "fbdjntxvp ln" },
64 { '6', "jdbfpvxtnk" },
66 { '8', "lfbdjntxvpln" },
67 { '9', "jnlfbdjtxvp" },
74 { 'G', "jdbfpvxt yom" },
84 { 'Q', "bdjtxvpfb ys" },
86 { 'S', "jdbflntxvp" },
103 { 's', "" }, /* space */
104 { 'b', "beyvkb gs qi" },
105 { 'e', "dsp pl pv" },
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).
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 ",
122 NULL, /* end of keyboard */
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,
138 /* definition of keys with coordinates for rendering */
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];
156 /* definition for each keyboard */
157 static struct keyboard_def {
158 struct key_def key[MAX_KEYS];
163 * add key to keyboard_def[].key structure
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
178 static int add_key(char key, int fkey, double width, struct key_def *key_def)
181 double font_scale = 1.0, font_offset = 0.0;
183 memset(key_def, 0, sizeof(*key_def));
186 key_def->fkey = fkey;
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;
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;
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;
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;
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;
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;
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;
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;
221 /* lines to be drawn ontop of the key (see layout in the description above) */
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 */
236 if (key_def->key == 'h')
238 else if (key_def->key == 'r')
240 else if (key_def->key == 'e')
247 if (key_def->key == 'h')
249 else if (key_def->key == 'r')
251 else if (key_def->key == 'e')
253 else if (key_def->key != '0')
260 if (key_def->key == 'h')
262 else if (key_def->key == 'r')
264 else if (key_def->key == 'e')
266 else if (key_def->key != '0')
273 if (key_def->key == 'h')
275 else if (key_def->key == 'r')
282 if (key_def->key == 'r')
289 if (key_def->key == 'r')
295 /* search for key font */
296 for (f = 0; key_font[f].key; f++) {
297 if (key_font[f].key == key)
300 if (!key_font[f].key) {
301 print_error("Failed to find keyboard character '%c' in key_font, please fix\n", key);
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] == ' ') {
312 /* the second character is space, so we start over with a new line sequence */
313 if (key_font[f].font[i + 1] == ' ') {
318 if (l == MAX_KEY_LINES) {
319 print_error("Failed to add key definition, maximum number of lines exeeded, please fix\n");
322 key_def->x1[l] = (double)(((key_font[f].font[i] - 'a') % 5) - 2) * font_scale + font_offset;
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;
327 key_def->z2[l] = (double)((key_font[f].font[i + 1] - 'a') / 5) - 2;
337 static void scale_key(double px, double py, double pz, double scale, struct key_def *key_def)
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;
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;
378 static void rotate_yz(double *y, double *z, double angle)
382 out_y = (*y) * cos(angle) - (*z) * sin(angle);
383 out_z = (*y) * sin(angle) + (*z) * cos(angle);
389 static void rotate_key(double angle, struct key_def *key_def)
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);
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);
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;
414 int init_vr_keyboard(double _keyboard_height, double _keyboard_distance)
421 keyboard_height = _keyboard_height;
422 keyboard_distance = _keyboard_distance;
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] == ' ')
433 key = keyboard_layout[l][x];
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 */
440 if (keyboard_layout[l][x + 1] == 'r')
441 width = 2.375; /* return key */
443 if (keyboard_layout[l][x + 1] == 'e')
444 width = 1.5; /* escape key */
446 if (keyboard_layout[l][x + 1] == '0')
447 width = 1.5; /* F10-key */
449 width = 1.25; /* F-key */
450 key = keyboard_layout[l][x + 1];
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');
457 print_error("Failed to add key, maximum number keys exeeded, please fix\n");
460 rc = add_key(key, fkey, width, &keyboard_def.key[k]);
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]);
475 /* skip size information, if any */
476 if (keyboard_layout[l][x + 1] > ' ')
480 keyboard_def.keys = k;
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;
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)
494 struct key_def *key_def;
499 /* generate poiting vector */
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;
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;
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);
517 /* check if pointer points towards keypad plane */
518 if (from_y - 1.0 < 0.0 || to_y > from_y - 1.0)
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;
526 /* check for margin */
527 if (to_x > 22 || to_x < -22 || to_z > 13 || to_z < -2)
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)
535 if (to_x > key_def->margin_right)
537 if (to_z < key_def->margin_back)
539 if (to_z > key_def->margin_front)
542 *key = keyboard_codes[k];
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);
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;
561 /* render keyboard per eye */
562 void render_vr_keyboard(double camera_x, double __attribute__((unused)) camera_y)
565 int rendered[MAX_KEYS];
566 double dists[MAX_KEYS], dist_x, dist_y, dist;
567 struct key_def *key_def;
569 glEnable(GL_CULL_FACE);
571 glCullFace(GL_FRONT);
573 memset(rendered, 0, sizeof(rendered));
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);
586 /* search for most distant key */
587 for (k = 0; k < keyboard_def.keys; k++) {
588 /* skip keys that have been already rendered */
591 if (!key_def || dists[k] > dist) {
593 key_def = &keyboard_def.key[k];
597 /* no unrendered key, we are done */
600 rendered[distant_k] = 1;
602 /* render case of key */
605 if (distant_k == highlight_k)
606 glColor4f(0.3, 0.7, 0.7, 1.0);
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);
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);
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);
632 if (distant_k == highlight_k)
633 glColor4f(0.3, 0.4, 0.4, 1.0);
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);
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 */
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]) {
654 glVertex3f(key_def->x1[l], key_def->y1[l], key_def->z1[l]);
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]);
665 glDisable(GL_CULL_FACE);
670 /* render pointer as a line from pose to keyboard */
671 glColor4f(1.0, 0.0, 0.0, 1.0);
673 glVertex3f(from_x, from_y, from_z);
674 glVertex3f(to_x, to_y, to_z);
679 /* render dot where pose points to */
682 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
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);
698 /* render a 'shot' */
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);
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);
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);