Capture visual info into a structure before rendering
authorAndreas Eversberg <jolly@eversberg.eu>
Fri, 30 Mar 2018 10:04:40 +0000 (12:04 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Thu, 5 Apr 2018 16:00:14 +0000 (18:00 +0200)
This is required to interpolate between two frames of the game, later...

src/libsdl/opengl.c
src/libsdl/opengl.h
src/mercenary/main.c
src/mercenary/render.c
src/mercenary/render.h

index 6d72ed2..e10ef5f 100644 (file)
@@ -266,29 +266,17 @@ void opengl_blit_benson(uint8_t *rgb, int filter, int benson_at_line, double fov
        glDisable(GL_TEXTURE_2D);
 }
 
-static double transparency;
-
-/* start rendering scene */
-void opengl_transparency_set(double _transparency)
+/* set color and opacity */
+void opengl_render_color(double r, double g, double b, double a)
 {
-       if (transparency)
-               glDisable(GL_BLEND);
-
-       transparency = _transparency;
-
-       /* for debugging use transparent rendering */
-       if (transparency) {
+       if (a < 1.0) {
                glEnable(GL_BLEND);
                glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-       }
-}
-
-void opengl_render_color(double r, double g, double b)
-{
-       if (transparency)
-               glColor4d(r, g, b, 1.0 - transparency);
-       else
+               glColor4d(r, g, b, a);
+       } else {
+               glDisable(GL_BLEND);
                glColor3d(r, g, b);
+       }
 }
 
 /* render polygon */
index cc186d6..883c803 100644 (file)
@@ -7,8 +7,7 @@ void opengl_viewport_legacy(int top);
 void opengl_blit_legacy(uint8_t *rgb, int filter);
 void opengl_viewport_improved(int bottom, int benson_at_line, double fov, double benson_size);
 void opengl_blit_benson(uint8_t *rgb, int filter, int benson_at_line, double fov, double benson_size, int pixel_size);
-void opengl_transparency_set(double _transparency);
-void opengl_render_color(double r, double g, double b);
+void opengl_render_color(double r, double g, double b, double a);
 void opengl_render_polygon(double *x, double *y, double *z, int count, int cull_face);
 void opengl_render_polygon_and_line(double *x, double *y, double *z, int count);
 void opengl_render_line(double x1, double y1, double z1, double x2, double y2, double z2, double size);
index adc53aa..11eceb1 100644 (file)
@@ -238,7 +238,7 @@ illegal_parameter:
 static void special_event(int event)
 {
        if (render_improved)
-               render_improved_event(event);
+               render_capture_event(event);
 }
 
 static void main_loop(void)
@@ -277,9 +277,9 @@ printf("frame rate: %.6f\n", 1.0 / vbl_duration);
                /* STEP 1: let the CPU render/process the game, also improve rendering via OpenGL, if enabled */
                /* don't render if we still delay */
                if (!render_delay) {
-                       /* start rendering for improved graphics */
+                       /* start capturing for improved graphics */
                        if (render_improved)
-                               render_start(config_fov, config_improve_extend_roads, config_debug_transparent);
+                               render_capture_start(config_fov, config_improve_extend_roads, config_debug_transparent);
 
                        /* execute until the rendered image is ready (wait for VBL) */
                        cycle_count = 0;
@@ -289,6 +289,9 @@ printf("frame rate: %.6f\n", 1.0 / vbl_duration);
                                if (event != STOP_AT_WAIT_VBL)
                                        special_event(event);
                        } while (event != STOP_AT_WAIT_VBL);
+                       /* stop capturing for improved graphics */
+                       if (render_improved)
+                               render_capture_stop();
                        /* copy palette */
                        palette_address = mercenary_palette_view();
                        for (i = 0; i < 16; i++)
@@ -297,6 +300,9 @@ printf("frame rate: %.6f\n", 1.0 / vbl_duration);
                        if (config_amiga_speed)
                                render_delay = (double)cycle_count / CPU_SPEED;
                }
+               /* render improved graphics */
+               if (render_improved)
+                       render_all_items();
 
                /* STEP 2: transfer legacy image (or just benson) in memory to OpenGL texture */
                if (had_first_irq) {
@@ -307,10 +313,8 @@ printf("frame rate: %.6f\n", 1.0 / vbl_duration);
                                emul_video(image, memory, palette, IMAGE_WIDTH, IMAGE_HEIGHT, IMAGE_DIWSTART, chipreg, 0, BENSON_AT_LINE, double_pixel_size);
                }
                /* render benson on improved rendering, if enabled */
-               if (render_improved) {
-                       render_finish();
+               if (render_improved)
                        opengl_blit_benson(image, config_video_filter, (double_pixel_size) ? BENSON_AT_LINE * 2 : BENSON_AT_LINE, config_fov, benson_size, (double_pixel_size) ? 2 : 1);
-               }
                /* setup viewport for legacy image and render image, if enabled */
                if (render_legacy) {
                        opengl_viewport_legacy(debug_opengl);
index 030213e..7c0bc1f 100644 (file)
@@ -20,6 +20,7 @@
 #include <stdio.h>
 #include <stdint.h>
 #include <stdlib.h>
+#include <string.h>
 #include <math.h>
 #include <GL/glew.h>
 #include "../libsdl/print.h"
 
 //#define DEBUG_COLOR
 //#define DEBUG_VERTEX
+#define DEBUG_ITEMS
 
-#define MAX_VERTEX 0x300
-static int coord_x[MAX_VERTEX >> 2];
-static int coord_y[MAX_VERTEX >> 2];
-static int coord_z[MAX_VERTEX >> 2];
+#define MAX_POLYGON            16      /* number of polygon complexity (vertices) */
+#define MAX_VERTEX             0x100   /* this is the value range, these are 64 vertices */
+#define MAX_INTERIOR_VERTEX    0x400   /* do we need that much? */
+#define MAX_INTERSTARS         80      /* always 80 stars */
+#define PLANET_VERTICES                128
+#define PLANET_ELIPSE          1.17
 
-#define MAX_INTERIOR_VERTEX 0x400 /* do we need that much? */
-static int interior_coord_x[MAX_INTERIOR_VERTEX >> 2];
-static int interior_coord_y[MAX_INTERIOR_VERTEX >> 2][4]; /* 4 levels (floor; ceiling; window or door top; window bottom) */
-static int interior_coord_z[MAX_INTERIOR_VERTEX >> 2];
 
 static int extend_roads; /* extend roads in its original width, rather than just using a single point */
 static double fov;
-static double transparency;
+static double debug_opacity;
 static double frustum_slope_64, frustum_slope_fov;
+static double orientation_roll, orientation_pitch, orientation_yaw;
+static uint16_t orientation_raw_yaw;
+static int16_t orientation_raw_pitch;
+static double planet_inclination, planet_azimuth;
+
+enum render_item_type {
+       RENDER_ITEM_VERTICES_0,
+       RENDER_ITEM_VERTICES_1,
+       RENDER_ITEM_VERTICES_2,
+       RENDER_ITEM_VERTICES_INTERIOR,
+       RENDER_ITEM_SKY,
+       RENDER_ITEM_GROUND,
+       RENDER_ITEM_OBJECT_POLYGON,
+       RENDER_ITEM_OBJECT_LINE,
+       RENDER_ITEM_BEACON_POINT,
+       RENDER_ITEM_BUILDING_EXTERIOR_POLYGON,
+       RENDER_ITEM_BUILDING_EXTERIOR_LINE,
+       RENDER_ITEM_BUILDING_INTERIOR_1TO4,
+       RENDER_ITEM_BUILDING_INTERIOR_5TO6,
+       RENDER_ITEM_BUILDING_INTERIOR_WALL,
+       RENDER_ITEM_COMET_POLYGON,
+       RENDER_ITEM_ROAD_LINE,
+       RENDER_ITEM_ROAD_POLYGON,
+       RENDER_ITEM_TAG_LINE,
+       RENDER_ITEM_TAG_POLYGON,
+       RENDER_ITEM_PLANET,
+       RENDER_ITEM_STARS,
+       RENDER_ITEM_INTERSTELLAR_STARS,
+       RENDER_ITEM_INTERSTELLAR_SUN,
+       RENDER_ITEM_ISLAND_POLYGON,
+       RENDER_ITEM_SIGHTS,
+};
+
+struct render_item_vertices {
+       int32_t x[MAX_VERTEX >> 2], y[MAX_VERTEX >> 2], z[MAX_VERTEX >> 2];
+};
+
+struct render_item_vertices_interior {
+       int32_t x[MAX_INTERIOR_VERTEX >> 2], y[4], z[MAX_INTERIOR_VERTEX >> 2];
+};
+
+struct render_item_sky {
+       double red, green, blue;
+};
+
+struct render_item_ground {
+       double red, green, blue;
+};
+
+struct render_item_polygon {
+       double red, green, blue;
+       int vertices;
+       int vertex[MAX_POLYGON];
+};
+
+struct render_item_interior14 {
+       double red, green, blue;
+       int level;
+       int vertex[4];
+};
+
+struct render_item_interior56 {
+       double red, green, blue;
+       int level12;
+       int level34;
+       int vertex14;
+       int vertex23;
+};
+
+struct render_item_line {
+       double red, green, blue;
+       int vertex[2];
+};
+
+struct render_item_point {
+       double red, green, blue;
+       int vertex;
+};
+
+struct render_item_planet {
+       double front_red, front_green, front_blue;
+       double back_red, back_green, back_blue;
+       int vertex;
+       double size;
+};
+
+struct render_item_stars {
+       int16_t v_offset;
+       int tilt;
+       int32_t tilt_value;
+       int above_zenith;
+};
+
+struct render_item_interstars {
+       uint8_t color[MAX_INTERSTARS];
+       int16_t x[MAX_INTERSTARS], y[MAX_INTERSTARS];
+       int     count;
+};
+
+typedef struct render_item {
+       struct render_item *next;
+       enum render_item_type type;
+       union {
+               struct render_item_vertices             vertices;
+               struct render_item_vertices_interior    vertices_interior;
+               struct render_item_sky                  sky;
+               struct render_item_ground               ground;
+               struct render_item_polygon              polygon;
+               struct render_item_line                 line;
+               struct render_item_point                point;
+               struct render_item_interior14           interior14;
+               struct render_item_interior56           interior56;
+               struct render_item_planet               planet;
+               struct render_item_stars                stars;
+               struct render_item_interstars           interstars;
+       } u;
+} render_item_t;
+
+static render_item_t *render_list_start = NULL, **render_list_end = &render_list_start;
+static render_item_t *render_item;
+static render_item_t *render_item_vertices_0, *render_item_vertices_1, *render_item_vertices_2;
+static render_item_t *render_item_vertices_interior;
+
+void render_item_add(enum render_item_type type)
+{
+       render_item = calloc(1, sizeof(render_item_t));
+       if (!render_item) {
+               print_error("No memory, must abort!\n");
+               abort();
+       }
+       render_item->type = type;
+       *render_list_end = render_item;
+       render_list_end = &render_item->next;
+}
 
 /* rendering starts, initialize variables */
-void render_start(double _fov, int _extend_roads, int debug)
+void render_capture_start(double _fov, int _extend_roads, int debug)
 {
 #if defined(DEBUG_COLOR) || defined(DEBUG_VERTEX)
        printf("start rendering a new frame...\n");
 #endif
 
+       /* flush render list */
+       while (render_list_start) {
+               render_item = render_list_start;
+               render_list_start = render_list_start->next;
+               free(render_item);
+       }
+       render_list_end = &render_list_start;
+       render_item = NULL;
+
+       /* set rendering options */
        fov = _fov;
        extend_roads = _extend_roads;
-
-       transparency = (debug) ? 0.5 : 0.0;
-       opengl_transparency_set(transparency);
+       /* set some transpareny, if debugging is enabled */
+       debug_opacity = (debug) ? 0.5 : 1.0;
 
        /* calculate slope of 64 degree frustum and current FOV's frustum */    
        frustum_slope_64 = tan(64.0 / 2.0 / 180.0 * M_PI);
        frustum_slope_fov = tan(fov / 2.0 / 180.0 * M_PI);
+
+       /* get orientation */
+       mercenary_get_orientation(&orientation_roll, &orientation_pitch, &orientation_yaw);
+       mercenary_get_orientation_raw(&orientation_raw_pitch, &orientation_raw_yaw);
+       mercenary_get_orientation_planet(&planet_inclination, &planet_azimuth);
+
+       render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
+       render_item_vertices_interior = NULL;
 }
 
-void render_finish(void)
+void render_capture_stop(void)
 {
-       opengl_transparency_set(0.0);
 }
 
-static void gamecolor2gl_index(uint16_t index)
+static void gamecolor2gl_index(double *red, double *green, double *blue, uint16_t index)
 {
        uint32_t palette;
        uint16_t color;
@@ -87,14 +237,12 @@ static void gamecolor2gl_index(uint16_t index)
                print_error("Use of color index from current palette, but index is not defined as being set!\n");
 #endif
        }
-       opengl_render_color(
-               (double)((color >> 8) & 0xf) / 15.0,
-               (double)((color >> 4) & 0xf) / 15.0,
-               (double)(color & 0xf) / 15.0
-       );
+       *red = (double)((color >> 8) & 0xf) / 15.0;
+       *green = (double)((color >> 4) & 0xf) / 15.0;
+       *blue = (double)(color & 0xf) / 15.0;
 }
 
-static void gamecolor2gl(uint16_t color)
+static void gamecolor2gl(double *red, double *green, double *blue, uint16_t color)
 {
        uint16_t index;
        uint32_t palette;
@@ -112,7 +260,7 @@ again:
                printf("using given color, color is now 0x%04x\n", color);
 #endif
        } else if ((color & 0xff) < 0x80) {
-               gamecolor2gl_index(color & 0xf);
+               gamecolor2gl_index(red, green, blue, color & 0xf);
                return;
        } else {
                /* use given index from pre-defined palette */
@@ -129,54 +277,60 @@ again:
                }
                goto again;
        }
-       opengl_render_color(
-               (double)((color >> 8) & 0xf) / 15.0,
-               (double)((color >> 4) & 0xf) / 15.0,
-               (double)(color & 0xf) / 15.0
-       );
+       *red = (double)((color >> 8) & 0xf) / 15.0;
+       *green = (double)((color >> 4) & 0xf) / 15.0;
+       *blue = (double)(color & 0xf) / 15.0;
 }
 
-static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, double x, double y, double z)
+static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z)
 {
        if ((vertex & 3)) {
                print_error("Vertex %d is not a multiple of four!\n", vertex);
                return;
        }
-       if (vertex >= MAX_VERTEX) {
-               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+       /* create new vertices item, if there was no vertex before, or if the vertex has different offet */
+       if (vertex < 0x100) {
+               if (!render_item || render_item->type != RENDER_ITEM_VERTICES_0) {
+                       render_item_add(RENDER_ITEM_VERTICES_0);
+                       /* copy vertices that have been captured already */
+                       if (render_item_vertices_0)
+                               memcpy(&render_item->u.vertices, &render_item_vertices_0->u.vertices, sizeof(render_item->u.vertices));
+                       render_item_vertices_0 = render_item;
+               }
+       } else
+       if (vertex < 0x200) {
+               if (!render_item || render_item->type != RENDER_ITEM_VERTICES_1) {
+                       render_item_add(RENDER_ITEM_VERTICES_1);
+                       /* copy vertices that have been captured already */
+                       if (render_item_vertices_1)
+                               memcpy(&render_item->u.vertices, &render_item_vertices_1->u.vertices, sizeof(render_item->u.vertices));
+                       render_item_vertices_1 = render_item;
+               }
+               vertex -= 0x100;
+       } else
+       if (vertex < 0x300) {
+               if (!render_item || render_item->type != RENDER_ITEM_VERTICES_2) {
+                       render_item_add(RENDER_ITEM_VERTICES_2);
+                       /* copy vertices that have been captured already */
+                       if (render_item_vertices_2)
+                               memcpy(&render_item->u.vertices, &render_item_vertices_2->u.vertices, sizeof(render_item->u.vertices));
+                       render_item_vertices_2 = render_item;
+               }
+               vertex -= 0x200;
+       } else {
+               print_error("Vertex %d exceeds maximum vertex number, please fix!\n", vertex);
                return;
        }
        vertex >>= 2;
 #ifdef DEBUG_VERTEX
        printf("storing %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, x, y, z);
 #endif
-       coord_x[vertex] = x;
-       coord_y[vertex] = y;
-       coord_z[vertex] = z;
+       render_item->u.vertices.x[vertex] = x;
+       render_item->u.vertices.y[vertex] = y;
+       render_item->u.vertices.z[vertex] = z;
 }
 
-static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z)
-{
-       if ((vertex & 3)) {
-               print_error("Vertex %d is not a multiple of four!\n", vertex);
-               return -1;
-       }
-       if (vertex >= MAX_VERTEX) {
-               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
-               return -1;
-       }
-       vertex >>= 2;
-       *x = coord_x[vertex];
-       *y = coord_y[vertex];
-       *z = coord_z[vertex];
-#ifdef DEBUG_VERTEX
-       printf("using %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, *x, *y, *z);
-#endif
-
-       return 0;
-}
-
-static void store_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, double x, double y1, double y2, double y3, double y4, double z)
+static void store_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y1, int32_t y2, int32_t y3, int32_t y4, int32_t z)
 {
        if ((vertex & 3)) {
                print_error("Vertex is not a multiple of four!\n");
@@ -186,41 +340,18 @@ static void store_interior_coord(const char __attribute__((unused)) *what, uint3
                print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_INTERIOR_VERTEX);
                return;
        }
+       if (!render_item || render_item->type != RENDER_ITEM_VERTICES_INTERIOR)
+               render_item_add(RENDER_ITEM_VERTICES_INTERIOR);
        vertex >>= 2;
 #ifdef DEBUG_VERTEX
        printf("storing %s coordinates: vertex=%d, x=%.0f, y=%.0f;%.0f;%.0f;%.0F, Z=%.0F\n", what, vertex, x, y1, y2, y3, y4, z);
 #endif
-       interior_coord_x[vertex] = x;
-       interior_coord_y[vertex][0] = y1;
-       interior_coord_y[vertex][1] = y2;
-       interior_coord_y[vertex][2] = y3;
-       interior_coord_y[vertex][3] = y4;
-       interior_coord_z[vertex] = z;
-}
-
-static int use_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, int level, double *x, double *y, double *z)
-{
-       if ((vertex & 3)) {
-               print_error("Vertex is not a multiple of four!\n");
-               return -1;
-       }
-       if (vertex >= MAX_VERTEX) {
-               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
-               return -1;
-       }
-       if (level < 1 || level > 4) {
-               print_error("Level %d is out of range (1..4)!\n", level);
-               return -1;
-       }
-       vertex >>= 2;
-       *x = interior_coord_x[vertex];
-       *y = interior_coord_y[vertex][level - 1];
-       *z = interior_coord_z[vertex];
-#ifdef DEBUG_VERTEX
-       printf("using %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, *x, *y, *z);
-#endif
-
-       return 0;
+       render_item->u.vertices_interior.x[vertex] = x;
+       render_item->u.vertices_interior.y[0] = y1;
+       render_item->u.vertices_interior.y[1] = y2;
+       render_item->u.vertices_interior.y[2] = y3;
+       render_item->u.vertices_interior.y[3] = y4;
+       render_item->u.vertices_interior.z[vertex] = z;
 }
 
 static int planet_rotation = 0;
@@ -248,153 +379,112 @@ static void rotate_coordinate(double roll, double pitch, double yaw, double *x,
        *y = out_y;
 }
 
-/* coordinates ready for an object */
-static void coord_object(void)
-{
-       int32_t x, y, z;
-
-       x = (int16_t)REG_D[3];
-       x += (int32_t)REG_A[1];
-       y = (int16_t)REG_D[4];
-       y += (int32_t)REG_A[2];
-       z = (int16_t)REG_D[5];
-       z += (int32_t)REG_A[3];
-       store_coord("object", REG_A[0], (double)x, (double)y, (double)z);
-}
-
 static int ground_index;
 
-/* clear screen (sky / universe) */
+/* clear screen color (sky / universe) */
 static void clear_screen(int index)
 {
-       double x[4], y[4], z[4];
-
 #ifdef DEBUG_VERTEX
        printf("clear screen:\n");
 #endif
 
-       opengl_transparency_set(0.0);
-
-       /* create plane to fill view */
-       x[0] = x[1] = y[1] = y[2] = -1000000;
-       x[2] = x[3] = y[0] = y[3] = 1000000;
-       z[0] = z[1] = z[2] = z[3] = 10;
-       gamecolor2gl_index(8);
-       opengl_render_polygon(x, y, z, 4, 0); /* no culling, because background is always visible! */
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_SKY);
 
-       opengl_transparency_set(transparency);
+       /* set color */
+       gamecolor2gl_index(&render_item->u.ground.red, &render_item->u.ground.green, &render_item->u.ground.blue, 8);
 
        /* store for later use after planets have been rendered */
        ground_index = index;
 }
 
-/* draw ground */
+/* ground color */
 static void draw_ground(void)
 {
-       double roll, pitch, yaw, x[4], y[4], z[4];
-
        /* no ground in space :) */
        if (ground_index < 0)
                return;
 
 #ifdef DEBUG_VERTEX
-       printf("draw ground plane:\n");
+       printf("add ground plane:\n");
 #endif
 
-       opengl_transparency_set(0.0);
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
-       yaw = 0.0; /* no need to rotate x-z plane, we don't want look at a corner of the 'ground-square' */
-
-       /* create huge square */
-       x[0] = x[1] = z[1] = z[2] = -1000000;
-       x[2] = x[3] = z[0] = z[3] = 1000000;
-       y[0] = y[1] = y[2] = y[3] = -10;
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_GROUND);
 
-       /* rotate vertex */
-       rotate_coordinate(roll, pitch, yaw, &x[0], &y[0], &z[0]);
-       rotate_coordinate(roll, pitch, yaw, &x[1], &y[1], &z[1]);
-       rotate_coordinate(roll, pitch, yaw, &x[2], &y[2], &z[2]);
-       rotate_coordinate(roll, pitch, yaw, &x[3], &y[3], &z[3]);
+       /* set color */
+       gamecolor2gl_index(&render_item->u.ground.red, &render_item->u.ground.green, &render_item->u.ground.blue, ground_index);
+}
 
-       gamecolor2gl_index(ground_index);
-       opengl_render_polygon(x, y, z, 4, 0); /* no culling, because ground is always visible! */
+/* coordinates ready for an object */
+static void coord_object(void)
+{
+       int32_t x, y, z;
 
-       opengl_transparency_set(transparency);
+       x = (int16_t)REG_D[3];
+       x += (int32_t)REG_A[1];
+       y = (int16_t)REG_D[4];
+       y += (int32_t)REG_A[2];
+       z = (int16_t)REG_D[5];
+       z += (int32_t)REG_A[3];
+       store_coord("object", REG_A[0], x, y, z);
 }
 
-/* render polygon of object */
+/* polygon of object */
 static void poly_object(int mercenary)
 {
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw object's polygon:\n");
+       printf("add object's polygon:\n");
 #endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_OBJECT_POLYGON);
+
+       /* set color */
        if (mercenary == 3)
-               gamecolor2gl(REG_D[0]);
+               gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, REG_D[0]);
        else {
                uint16_t color;
                color = m68k_read_memory_8(vertex_address++) << 8;
                color |= m68k_read_memory_8(vertex_address++);
-               gamecolor2gl(color);
+               gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
        }
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
-
        /* the vertex list is zero-terminated */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < MAX_POLYGON; i++) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
-               /* get vertex */
-               rc = use_coord("object", vertex, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               render_item->u.polygon.vertex[i] = vertex;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+       render_item->u.polygon.vertices = i;
 }
 
-/* render line of object */
+/* line of object */
 static void line_object(void)
 {
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
-       double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw object's line:\n");
+       printf("add object's line:\n");
 #endif
-       gamecolor2gl(REG_D[0]);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_OBJECT_LINE);
+
+       /* set color */
+       gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
 
+       /* two vertices */
        vertex = m68k_read_memory_8(vertex_address++);
-       /* get vertex */
-       rc = use_coord("object", vertex, &x1, &y1, &z1);
-       if (rc < 0)
-               return;
+       render_item->u.line.vertex[0] = vertex;
        vertex = m68k_read_memory_8(vertex_address++);
-       /* get vertex */
-       rc = use_coord("object", vertex, &x2, &y2, &z2);
-       if (rc < 0)
-               return;
-       /* rotate vertices */
-       rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
-       rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
-       /* transfer line to OpenGL */
-       opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+       render_item->u.line.vertex[1] = vertex;
 }
 
 /* coordinates ready for a beacon */
@@ -403,117 +493,91 @@ static void coord_beacon(void)
        int32_t x, y, z;
 
        /* only 28 bits seem to be a correct signed int value */
-       x = (double)((int32_t)REG_D[3] << 4) / 16.0;
-       y = (double)((int32_t)REG_D[4] << 4) / 16.0;
-       z = (double)((int32_t)REG_D[5] << 4) / 16.0;
-       store_coord("beacon", 0, (double)x, (double)y, (double)z);
+       x = ((int32_t)REG_D[3] << 4) / 16;
+       y = ((int32_t)REG_D[4] << 4) / 16;
+       z = ((int32_t)REG_D[5] << 4) / 16;
+       store_coord("beacon", 0, x, y, z);
 }
 
-/* render point of beacon */
+/* point of beacon */
 static void point_beacon(void)
 {
-       double roll, pitch, yaw, x, y, z;
-       int rc;
-
 #ifdef DEBUG_VERTEX
-       printf("draw beacon's point:\n");
+       printf("add beacon's point:\n");
 #endif
-       gamecolor2gl(REG_D[2]);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BEACON_POINT);
 
-       /* get vertex */
-       rc = use_coord("beacon", 0, &x, &y, &z);
-       if (rc < 0)
-               return;
-       /* rotate vertex */
-       rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
-       /* transfer point to OpenGL */
-       opengl_render_point(x, y, z, 0.0);
+       /* set color */
+       gamecolor2gl(&render_item->u.point.red, &render_item->u.point.green, &render_item->u.point.blue, REG_D[2]);
+
+       /* one vertex */
+       render_item->u.point.vertex = 0;
 }
 
 /* coordinates ready for a building (exterior) */
 static void coord_building_exterior(void)
 {
-       int x, y, z;
+       int32_t x, y, z;
 
        x = (int32_t)REG_D[3];
        y = (int32_t)REG_D[4];
        z = (int32_t)REG_D[5];
-       store_coord("building exterior", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("building exterior", REG_A[0], x, y, z);
 }
 
-/* render polygon of building (exterior) */
+/* polygon of building (exterior) */
 static void poly_building_exterior(void)
 {
+       uint16_t color;
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw building's polygon:\n");
+       printf("add building's polygon:\n");
 #endif
-       uint16_t color;
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BUILDING_EXTERIOR_POLYGON);
+
+       /* set color */
        color = m68k_read_memory_8(vertex_address++) << 8;
        color |= m68k_read_memory_8(vertex_address++);
-       gamecolor2gl(color);
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
 
        /* the vertex list is zero-terminated */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < MAX_POLYGON; i++) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
-               vertex |= 0x100;
-               /* get vertex */
-               rc = use_coord("building exterior", vertex, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               render_item->u.polygon.vertex[i] = vertex | 0x100;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+       render_item->u.polygon.vertices = i;
 }
 
-/* render line of building (exterior) */
+/* line of building (exterior) */
 static void line_building_exterior(void)
 {
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
-       double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw building's line:\n");
+       printf("add building's line:\n");
 #endif
-       gamecolor2gl(REG_D[0]);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BUILDING_EXTERIOR_LINE);
 
+       /* set color */
+       gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
+
+       /* two vertices */
        vertex = m68k_read_memory_8(vertex_address++);
-       vertex |= 0x100;
-       /* get vertex */
-       rc = use_coord("building line", vertex, &x1, &y1, &z1);
-       if (rc < 0)
-               return;
+       render_item->u.line.vertex[0] = vertex | 0x100;
        vertex = m68k_read_memory_8(vertex_address++);
-       vertex |= 0x100;
-       /* get vertex */
-       rc = use_coord("building line", vertex, &x2, &y2, &z2);
-       if (rc < 0)
-               return;
-       /* rotate vertices */
-       rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
-       rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
-       /* transfer line to OpenGL */
-       opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+       render_item->u.line.vertex[1] = vertex | 0x100;
 }
 
 static int interior_level12 = 0;
@@ -526,129 +590,79 @@ static void coord_building_interior(void)
        int32_t height1, height2, height3, height4;
 
        mercenary_coord_building_interior(&east, &height1, &height2, &height3, &height4, &north);
-       store_interior_coord("interior", REG_A[0], (double)east, (double)height1, (double)height2, (double)height3, (double)height4, (double)north);
+       store_interior_coord("interior", REG_A[0], east, height1, height2, height3, height4, north);
 }
 
-/* render polygon of building (interior) */
+/* polygon of building (interior) */
 static void poly_building_interior1to4(int level)
 {
        uint16_t color;
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw roof/floor's polygon at level %d:\n", level);
+       printf("add roof/floor's polygon at level %d:\n", level);
 #endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BUILDING_INTERIOR_1TO4);
+
+       /* set color */
        color = m68k_read_memory_8(REG_A[0]) << 8;
        color |= m68k_read_memory_8(REG_A[0] + 1);
-       gamecolor2gl(color);
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       gamecolor2gl(&render_item->u.interior14.red, &render_item->u.interior14.green, &render_item->u.interior14.blue, color);
 
-       /* the vertex list is zero-terminated */
+       /* four vertices, one level */
        for (i = 0; i < 4; i++) {
                vertex = REG_A[(2 + i)];
-               /* get vertex */
-               rc = use_interior_coord("interior", vertex, level, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               render_item->u.interior14.vertex[i] = vertex;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+       render_item->u.interior14.level = level;
 }
 
-/* render polygon of building (interior) */
+/* polygon of building (interior) */
 static void poly_building_interior5to6(int level12, int level34)
 {
        uint16_t color;
-       uint32_t vertex;
-       int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw polygon above/below window/door at level %d/%d:\n", level12, level34);
+       printf("add polygon above/below window/door at level %d/%d:\n", level12, level34);
 #endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BUILDING_INTERIOR_5TO6);
+
+       /* set color */
        color = m68k_read_memory_8(REG_A[0]) << 8;
        color |= m68k_read_memory_8(REG_A[0] + 1);
-       gamecolor2gl(color);
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       gamecolor2gl(&render_item->u.interior56.red, &render_item->u.interior56.green, &render_item->u.interior56.blue, color);
 
-       /* the vertex list is zero-terminated */
-       for (i = 0; i < 4; i++) {
-               vertex = (i == 0 || i == 3) ? REG_A[2] : REG_A[3];
-               /* get vertex */
-               rc = use_interior_coord("interior", vertex, (i == 0 || i == 1) ? level12 : level34, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
-       }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+       /* two vertices, two levels */
+       render_item->u.interior56.vertex14 = REG_A[2];
+       render_item->u.interior56.vertex23 = REG_A[3];
+       render_item->u.interior56.level12 = level12;
+       render_item->u.interior56.level34 = level34;
 }
 
+/* wall part of a building */
 static void wall_building(void)
 {
-       double roll, pitch, yaw, x[4], y[4], z[4];
-       double bottom1_x, bottom1_y, bottom1_z;
-       double bottom2_x, bottom2_y, bottom2_z;
-       double top1_x, top1_y, top1_z;
-       double top2_x, top2_y, top2_z;
-       int rc;
-
 #ifdef DEBUG_VERTEX
-       printf("draw wall:\n");
+       printf("add wall:\n");
 #endif
-       gamecolor2gl(REG_D[3]);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_BUILDING_INTERIOR_WALL);
 
-       /* get bottom coordinate */
-       rc = use_interior_coord("interior", REG_A[1], 1, &bottom1_x, &bottom1_y, &bottom1_z);
-       if (rc < 0)
-               return;
-       /* rotate vertex */
-       rotate_coordinate(roll, pitch, yaw, &bottom1_x, &bottom1_y, &bottom1_z);
-       /* get top coordinate according to bit 12 in D3 */
-       rc = use_interior_coord("interior", REG_A[1], (REG_D[3] & (1 << 12)) ? 3 : 2, &top1_x, &top1_y, &top1_z);
-       if (rc < 0)
-               return;
-       /* rotate vertex */
-       rotate_coordinate(roll, pitch, yaw, &top1_x, &top1_y, &top1_z);
-       /* if wall is not just a strait line */
-       if (REG_A[1] != REG_A[2]) {
-               /* get bottom coordinate */
-               rc = use_interior_coord("interior", REG_A[2], 1, &bottom2_x, &bottom2_y, &bottom2_z);
-               if (rc < 0)
-                       return;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &bottom2_x, &bottom2_y, &bottom2_z);
-               /* get top coordinate according to bit 12 in D3 */
-               rc = use_interior_coord("interior", REG_A[2], (REG_D[3] & (1 << 12)) ? 3 : 2, &top2_x, &top2_y, &top2_z);
-               if (rc < 0)
-                       return;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &top2_x, &top2_y, &top2_z);
-               /* transfer vertex to OpenGL */
-               x[0] = bottom1_x;       y[0] = bottom1_y;       z[0] = bottom1_z;
-               x[1] = top1_x;          y[1] = top1_y;          z[1] = top1_z;
-               x[2] = top2_x;          y[2] = top2_y;          z[2] = top2_z;
-               x[3] = bottom2_x;       y[3] = bottom2_y;       z[3] = bottom2_z;
-               /* render polygon to OpenGL */
-               opengl_render_polygon_and_line(x, y, z, 4); /* no culling, because walls are always visible! */
-       } else {
-               /* transfer vertex to OpenGL */
-               opengl_render_line(bottom1_x, bottom1_y, bottom1_z, top1_x, top1_y, top1_z, 0.0);
-       }
+       /* set color */
+       gamecolor2gl(&render_item->u.interior56.red, &render_item->u.interior56.green, &render_item->u.interior56.blue, REG_D[3]);
+
+       /* two vertices, two levels */
+       render_item->u.interior56.vertex14 = REG_A[1];
+       render_item->u.interior56.vertex23 = REG_A[2];
+       /* get top level according to bit 12 in D3 */
+       render_item->u.interior56.level12 = (REG_D[3] & (1 << 12)) ? 3 : 2;
+       render_item->u.interior56.level34 = 1;
 }
 
 /* coordinates ready for comet tail */
@@ -659,49 +673,37 @@ static void coord_comet(void)
        x = (int32_t)REG_D[3];
        y = (int32_t)REG_D[4];
        z = (int32_t)REG_D[5];
-       store_coord("comet tail", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("comet tail", REG_A[0], x, y, z);
 }
 
-/* render polygon of comet tail */
+/* polygon of comet tail */
 static void poly_comet(void)
 {
        uint16_t color;
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw;
-       double inclination, rotation;
-       double x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw comet's polygon:\n");
+       printf("add comet's polygon:\n");
 #endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_COMET_POLYGON);
+
+       /* set color */
        color = m68k_read_memory_8(vertex_address++) << 8;
        color |= m68k_read_memory_8(vertex_address++);
-       gamecolor2gl(color);
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
-       if (planet_rotation)
-               mercenary_get_orientation_planet(&inclination, &rotation);
+       gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
 
        /* the vertex list is zero-terminated */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < MAX_POLYGON; i++) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
-               /* get vertex */
-               rc = use_coord("comet tail", vertex, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               if (planet_rotation)
-                       rotate_coordinate(0.0, inclination, rotation, &x[i], &y[i], &z[i]);
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               render_item->u.polygon.vertex[i] = vertex;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon_and_line(x, y, z, i); /* no culling, because we render only two (out of four) planes! */
+       render_item->u.polygon.vertices = i;
 }
 
 /* coordinates ready for lines of a road / ground surface */
@@ -713,40 +715,29 @@ static void coord_line_road(void)
        mercenary_get_height(&y);
        y = -y;
        z = REG_D[5];
-       store_coord("road", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("road", REG_A[0], x, y, z);
 }
 
-/* render line of road */
+/* line of road */
 static void line_road(void)
 {
        uint32_t vertex;
-       double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw road's line:\n");
+       printf("add road's line:\n");
 #endif
 
-       gamecolor2gl_index(mercenary_street_color_index());
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_ROAD_LINE);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* set color */
+       gamecolor2gl_index(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, mercenary_street_color_index());
 
+       /* two vertices */
        vertex = REG_A[1];
-       /* get vertex */
-       rc = use_coord("road", vertex, &x1, &y1, &z1);
-       if (rc < 0)
-               return;
+       render_item->u.line.vertex[0] = vertex;
        vertex = REG_A[2];
-       /* get vertex */
-       rc = use_coord("road", vertex, &x2, &y2, &z2);
-       if (rc < 0)
-               return;
-       /* rotate vertices */
-       rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
-       rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
-       /* transfer line to OpenGL */
-       opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+       render_item->u.line.vertex[1] = vertex;
 }
 
 /* coordinates ready for polygons of a road / ground surface */
@@ -762,100 +753,37 @@ static void coord_poly_road(void)
        y = -y;
        z = m68k_read_memory_32(576 + REG_A[0]);
        z -= REG_A[3];
-       store_coord("road/place", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("road/place", REG_A[0], x, y, z);
 }
 
-/* render polygon of road */
+/* polygon of road */
 static void poly_road()
 {
        uint16_t color;
        uint32_t vertex_address = REG_A[0];
-       uint32_t vertex, vertex_prev, vertex_next;
-       int i, v;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       double x_current, y_current, z_current;
-       double x_prev, y_prev, z_prev;
-       double x_next, y_next, z_next;
-       uint32_t vertices[16];
-       int vertices_num;
-       int rc;
+       uint32_t vertex;
+       int i;
 
 #ifdef DEBUG_VERTEX
-       printf("draw road/place's polygon:\n");
+       printf("add road/place's polygon:\n");
 #endif
-       color = m68k_read_memory_8(vertex_address++) << 8;
-       color |= m68k_read_memory_8(vertex_address++);
-       gamecolor2gl(color);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_ROAD_POLYGON);
 
+       /* set color */
+       color = m68k_read_memory_8(vertex_address++) << 8;
+       color |= m68k_read_memory_8(vertex_address++);
+       gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
 
-       /* count the vertex list, it is zero-terminated */
-       vertices_num = 0;
-       for (i = 0; i < 16; i++) {
+       /* the vertex list is zero-terminated */
+       for (i = 0; i < MAX_POLYGON; i++) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
-               vertices[i] = vertex;
-               vertices_num++;
+               render_item->u.polygon.vertex[i] = vertex;
        }
-
-       /* the vertex list is zero-terminated */
-       i = 0;
-       for (v = 0; v < vertices_num; v++) {
-               vertex = vertices[v];
-               rc = use_coord("road/place", vertex, &x_current, &y_current, &z_current);
-               if (rc < 0)
-                       break;
-               /* check for road extension, so we extend the road to the given end point */
-               if (extend_roads && vertex >= 0xf0) {
-                       /* previous vertex */
-                       vertex_prev = vertices[(v + vertices_num - 1) % vertices_num];
-                       rc = use_coord("road/place", vertex_prev, &x_prev, &y_prev, &z_prev);
-                       if (rc < 0)
-                               break;
-                       /* next vertex */
-                       vertex_next = vertices[(v + 1) % vertices_num];
-                       rc = use_coord("road/place", vertex_next, &x_next, &y_next, &z_next);
-                       if (rc < 0)
-                               break;
-                       /* extend vertices to end point position
-                        * change x or z coordinate, whatever is greater
-                       */
-                       if (fabs(x_prev - x_current) > fabs(z_prev - z_current))
-                               x_prev = x_next = x_current;
-                       else
-                               z_prev = z_next = z_current;
-                       /* store vertices */
-                       x[i] = x_prev;
-                       y[i] = y_prev;
-                       z[i] = z_prev;
-                       /* rotate vertex */
-                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
-                       if (i++ == 16)
-                               break;
-                       x[i] = x_next;
-                       y[i] = y_next;
-                       z[i] = z_next;
-                       /* rotate vertex */
-                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
-                       if (i++ == 16)
-                               break;
-                       continue;
-               } else {
-                       /* no extension, just keep the current point as is */
-                       x[i] = x_current;
-                       y[i] = y_current;
-                       z[i] = z_current;
-                       /* rotate vertex */
-                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
-                       if (i++ == 16)
-                               break;
-               }
-       }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 0); /* no culling, because polygons lay on the gound and are always visible! */
+       render_item->u.polygon.vertices = i;
 }
 
 /* coordinates ready for tags */
@@ -869,7 +797,7 @@ static void coord_tags(void)
        y += (int32_t)REG_A[2];
        z = (int16_t)REG_D[5];
        z += (int32_t)REG_A[3];
-       store_coord("tags", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("tags", REG_A[0], x, y, z);
 }
 
 /* coordinates ready for large tags */
@@ -883,85 +811,62 @@ static void coord_tags2(void)
        y += 2 * (int32_t)REG_A[2];
        z = (int16_t)REG_D[5];
        z += 2 * (int32_t)REG_A[3];
-       store_coord("large tags", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("large tags", REG_A[0], x, y, z);
 }
 
-/* render line of tag */
+/* line of tag */
 static void line_tags(int last_color)
 {
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
-       double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw tag's line:\n");
+       printf("add tag's line:\n");
 #endif
 
-       if (!last_color) {
-               gamecolor2gl(REG_D[0]);
-       } else {
-               gamecolor2gl_index(mercenary_line_tags_index());
-       }
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_TAG_LINE);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* set color */
+       if (!last_color)
+               gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
+       else
+               gamecolor2gl_index(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, mercenary_line_tags_index());
 
+       /* two vertices */
        vertex = m68k_read_memory_8(vertex_address++);
-       vertex |= 0x200;
-       /* get vertex */
-       rc = use_coord("tag", vertex, &x1, &y1, &z1);
-       if (rc < 0)
-               return;
+       render_item->u.line.vertex[0] = vertex | 0x200;
        vertex = m68k_read_memory_8(vertex_address++);
-       vertex |= 0x200;
-       /* get vertex */
-       rc = use_coord("tag", vertex, &x2, &y2, &z2);
-       if (rc < 0)
-               return;
-       /* rotate vertices */
-       rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
-       rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
-       /* transfer line to OpenGL */
-       opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+       render_item->u.line.vertex[1] = vertex | 0x200;
 }
 
-/* render polygon of tags */
+/* polygon of tags */
 static void poly_tags(int last_color)
 {
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw tag's polygon:\n");
+       printf("add tag's polygon:\n");
 #endif
-       if (!last_color) {
-               gamecolor2gl(REG_D[0]);
-       } else {
-               gamecolor2gl(mercenary_poly_tags_color());
-       }
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_TAG_POLYGON);
 
+       /* set color */
+       if (!last_color)
+               gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, REG_D[0]);
+       else
+               gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, mercenary_poly_tags_color());
        /* the vertex list is zero-terminated */
-       for (i = 0; i < 16; i++) {
+       for (i = 0; i < MAX_POLYGON; i++) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
-               vertex |= 0x200;
-               /* get vertex */
-               rc = use_coord("tag", vertex, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               render_item->u.polygon.vertex[i] = vertex | 0x200;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+       render_item->u.polygon.vertices = i;
 }
 
 /* coordinates ready for planet */
@@ -972,41 +877,44 @@ static void coord_planet(void)
        x = (int32_t)REG_D[3];
        y = (int32_t)REG_D[4];
        z = (int32_t)REG_D[5];
-       store_coord("planet", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("planet", REG_A[0], x, y, z);
 }
 
-#define PLANET_VERTICES 128
-#define PLANET_ELIPSE  1.17
-
-/* render planet */
+/* planet */
 static void draw_planet(int comet)
 {
-       uint32_t color = REG_D[0];
-       uint32_t vertex = REG_A[0];
+       uint32_t vertex;
        uint32_t scale_index;
-       int i;
-       double scale1, scale2, size, angle;
-       double roll, pitch, yaw;
-       double inclination, rotation;
-       double sun_x, sun_y, sun_z, angle_sun;
-       double loc_x, loc_y, loc_z, angle_loc;
-       double x[PLANET_VERTICES], y[PLANET_VERTICES], z[PLANET_VERTICES];
-       int rc;
+       double scale1, scale2;
+
+       vertex = REG_A[0];
 
        /* fixing (not noticable) bug in game: don't render comet twice */
        if (!comet && vertex == 116)
                return;
 
-       /* use background color for dark side */
-       color |= (mercenary_background_index() << 16) | 0x80000000; /* shifted by 2 */
-
-       /* make comet black on front side and bright on back */
-       if (comet)
-               color = 0x07770000;
-
 #ifdef DEBUG_VERTEX
-       printf("draw planet/comet/sun: vertex=%d color=%08x\n", vertex, color);
+       printf("add planet/comet/sun: vertex=%d color=%08x\n", vertex, color);
 #endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_PLANET);
+
+       /* set color */
+       if (comet) {
+               /* make comet black on front side and bright on back */
+               gamecolor2gl(&render_item->u.planet.front_red, &render_item->u.planet.front_green, &render_item->u.planet.front_blue, 0x000);
+               gamecolor2gl(&render_item->u.planet.back_red, &render_item->u.planet.back_green, &render_item->u.planet.back_blue, 0x777);
+
+       } else {
+               gamecolor2gl(&render_item->u.planet.front_red, &render_item->u.planet.front_green, &render_item->u.planet.front_blue, REG_D[0]);
+               /* use background color for dark side */
+               gamecolor2gl(&render_item->u.planet.back_red, &render_item->u.planet.back_green, &render_item->u.planet.back_blue, mercenary_background_index() | 0x8000);
+       }
+
+       /* set vertex */
+       render_item->u.planet.vertex = vertex;
+
        /* I REVERSED THE F*CKING PLANET SIZE, took me half a day!
         * the long word 21584(A0) contains two scales
         * the lower word contains the scale between 4096 .. 8191, this is 1.0 .. 2.0
@@ -1015,233 +923,72 @@ static void draw_planet(int comet)
        scale_index = mercenary_planet_scale_index();
        scale1 = (double)(m68k_read_memory_16(scale_index + 2 + vertex) & 0x1fff) / 8192.0;
        scale2 = (double)(1 << (uint16_t)m68k_read_memory_16(scale_index + vertex));
-       size = scale1 * scale2 / 128.0;
-
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
-       if (planet_rotation)
-               mercenary_get_orientation_planet(&inclination, &rotation);
-
-       /* get location */
-       rc = use_coord("planet(sun)", 0, &sun_x, &sun_y, &sun_z);
-       if (rc < 0)
-               return;
-       rc = use_coord("planet", vertex, &loc_x, &loc_y, &loc_z);
-       if (rc < 0)
-               return;
-       /* rotate vertex */
-       if (planet_rotation) {
-               rotate_coordinate(0.0, inclination, rotation, &sun_x, &sun_y, &sun_z);
-               rotate_coordinate(0.0, inclination, rotation, &loc_x, &loc_y, &loc_z);
-       }
-       rotate_coordinate(roll, pitch, yaw, &sun_x, &sun_y, &sun_z);
-       rotate_coordinate(roll, pitch, yaw, &loc_x, &loc_y, &loc_z);
-
-       /* calculate direction of the sun */
-       angle_sun = atan2(sun_x, sun_z);
-       angle_loc = atan2(loc_x, loc_z);
-       angle = angle_sun - angle_loc;
-       if (angle > M_PI)
-               angle -= 2.0 * M_PI;
-       if (angle < -M_PI)
-               angle += 2.0 * M_PI;
-
-       /* on which side are we (sun is always bright, vertex == 0) */
-       if ((angle < M_PI / 2.0 && angle > -M_PI / 2.0) || vertex == 0) {
-               /* set bright side */
-               gamecolor2gl(color);
-       } else {
-               /* set dark side */
-               gamecolor2gl(color >> 16);
-       }
-
-       /* create and render cicle */
-       for (i = 0; i < PLANET_VERTICES; i++) {
-               x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
-               y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
-               z[i] = loc_z;
-       }
-       opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
-
-       if (vertex == 0) {
-               /* sun has no crescent */
-               return;
-       }
-
-       /* on which side are we */
-       if (angle < M_PI / 2.0 && angle > -M_PI / 2.0) {
-               /* set dark side */
-               gamecolor2gl(color >> 16);
-       } else {
-               /* set bright side */
-               gamecolor2gl(color);
-       }
-
-       /* create and render crescent */
-       if (angle > M_PI / 2.0 || (angle < 0.0 && angle > -M_PI / 2.0)) {
-               angle = fabs(angle);
-               if (angle > M_PI / 2.0)
-                       angle = M_PI - angle;
-               /* to the right */
-               for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
-                       x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
-                       y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
-                       z[i] = loc_z;
-               }
-               for (; i < PLANET_VERTICES; i++) {
-                       x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE * sin((1.0 - angle / (M_PI / 2)) * (M_PI / 2.0));
-                       y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
-                       z[i] = loc_z;
-               }
-       } else {
-               angle = fabs(angle);
-               if (angle > M_PI / 2.0)
-                       angle = M_PI - angle;
-               /* to the left */
-               for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
-                       x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE * sin((1.0 - angle / (M_PI / 2)) * (M_PI / 2.0));
-                       y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
-                       z[i] = loc_z;
-               }
-               for (; i < PLANET_VERTICES; i++) {
-                       x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
-                       y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
-                       z[i] = loc_z;
-               }
-       }
-       opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
-       opengl_render_point(loc_x, loc_y, loc_z, 0.0); /* planet is visible at any distance - at least as a point  */
+       render_item->u.planet.size = scale1 * scale2 / 128.0;
 }
 
-/* draw stars */
+/* stars */
 static void draw_stars(int16_t v_offset, int tilt, int above_zenith)
 {
-       int32_t tilt_value;
-       int16_t tilt_offset = 0;
-       int x_offset = 0;
-       uint16_t color[16];
-       uint16_t view_width, yaw;
-       int16_t pitch;
-       uint32_t table, table_start;
-       int16_t x, y;
-       double z;
-       int i;
-
 #ifdef DEBUG_VERTEX
-       printf("draw stars\n");
+       printf("add stars\n");
 #endif
-       /* use default fov of 64 to calculate z distance */
-       z = 160.0 / frustum_slope_64;
 
-       view_width = (int)(320.0 / frustum_slope_64 * frustum_slope_fov);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_STARS);
 
-       /* get palette */
-       for (i = 0; i < 16; i++)
-               color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+       /* vertical offset */
+       render_item->u.stars.v_offset = v_offset;
 
        /* if we fly over the planet, we have tilt, so we get the calculated tilt value from game */
+       render_item->u.stars.tilt = tilt;
        if (tilt)
-               tilt_value = (int32_t)REG_A[4];
+               render_item->u.stars.tilt_value = (int32_t)REG_A[4];
 
-       /* table offset is 91, so we substract it and add it back with different FOV, so table begins at later
-        * full turn is 1024, we have default of 64 degrees: 1024 / 360 * 64 = 182
-        * then we half it, so we get to the center via 91
-        */
-       mercenary_get_orientation_raw(&pitch, &yaw);
-
-       if (above_zenith)
-               yaw = 0x200 + yaw;
-       yaw = (yaw + 91 - (int)(91.0 * (frustum_slope_fov / frustum_slope_64))) & 0x3ff;
-       yaw <<= 1;
-       table = mercenary_star_table();
-       table_start = table + m68k_read_memory_16(table);
-       table += m68k_read_memory_16(table + yaw);
-       yaw = ((uint32_t)yaw * 0xe10e) >> 16;
-
-       if (above_zenith)
-               pitch = 0x200 - pitch;
-       pitch = pitch & 0x3ff;
-       pitch -= v_offset;
-       pitch <<= 2;
-       pitch = (pitch * 0x6ccc) >> 16;
-
-       while (1) {
-               x = m68k_read_memory_16(table);
-               if (x >= 1800) {
-                       x_offset += 1800;
-                       table = table_start;
-               }
-               x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
-               table += 2;
-               if (x < 0)
-                       break;
-               /* special case where we tilt the view when flying on the planet */
-               if (tilt) {
-                       /* use offset as given by game: 160 is half of the screen width
-                        * we extend the width to the actual FOV, so it fits
-                        */
-                       tilt_offset = (int32_t)((x - (int16_t)(160.0 / frustum_slope_64 * frustum_slope_fov)) * tilt_value) >> 16;
-               }
-               y = ((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
-               table += 2;
-               if (above_zenith) {
-                       x = (view_width - 1) - x;
-                       y = ~y + 136;
-               }
-               /* get color */
-               gamecolor2gl(color[(m68k_read_memory_8(table - 2) & 0x3c) >> 2]);
-               /* render point */
-               opengl_render_point(160.0 / frustum_slope_64 * frustum_slope_fov - (double)x, 68.0 - (double)y, z, 0.0);
-       }
+       /* stars above zenith */
+       render_item->u.stars.above_zenith = above_zenith;
 }
 
-/* draw stars of interstellar flight */
+/* stars of interstellar flight */
 static void draw_stars_interstellar(void)
 {
        int i, count;
        uint32_t table;
-       uint16_t color[16];
-       int16_t x, y;
-       double z;
 
 #ifdef DEBUG_VERTEX
-       printf("draw interstellar stars\n");
+       printf("add interstellar stars\n");
 #endif
-       /* use default fov of 64 to calculate z distance */
-       z = 160.0 / frustum_slope_64;
 
-       /* get palette */
-       for (i = 0; i < 16; i++)
-               color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_INTERSTELLAR_STARS);
 
        table = REG_A[0];
        count = REG_D[5] + 1;
+       if (count > MAX_INTERSTARS) {
+               print_error("Expecting maximum of %d stars here, plese fix!\n", MAX_INTERSTARS);
+               return;
+       }
        for (i = 0; i < count; i++) {
                table += 12;
                /* get color */
-               gamecolor2gl(color[(m68k_read_memory_16(table) >> 5) & 0xf]);
+               render_item->u.interstars.color[i] = (m68k_read_memory_16(table) >> 5) & 0xf;
                table += 2;
-               x = m68k_read_memory_16(table);
+               render_item->u.interstars.x[i] = m68k_read_memory_16(table);
                table += 2;
-               y = m68k_read_memory_16(table);
+               render_item->u.interstars.y[i] = m68k_read_memory_16(table);
                table += 2;
-               /* render point */
-               opengl_render_point(160.0 - (double)x, 68.0 - (double)y, z, 0.0);
        }
-
+       render_item->u.interstars.count = count;
 }
 
-/* draw sun of interstellar flight (center dot) */
+/* sun of interstellar flight (center dot) */
 static void draw_sun_interstellar(void)
 {
 #ifdef DEBUG_VERTEX
-       printf("draw interstellar sun\n");
+       printf("add interstellar sun\n");
 #endif
 
-       /* white */
-       gamecolor2gl(0x777);
-       /* render point */
-       opengl_render_point(0.0, 0.0, 100.0, 0.0);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_INTERSTELLAR_SUN);
 }
 
 /* coordinates ready for polygons of islands */
@@ -1256,74 +1003,57 @@ static void coord_islands(void)
        y = -y;
        z = ((int16_t)m68k_read_memory_16(REG_A[4]) * 65536);
        z += (int32_t)REG_A[3];
-       store_coord("island", REG_A[0], (double)x, (double)y, (double)z);
+       store_coord("island", REG_A[0], x, y, z);
 }
 
-/* render polygon of island */
+/* polygon of island */
 static void poly_island()
 {
        uint16_t color;
        uint32_t vertex_address = REG_A[0];
        uint32_t vertex;
        int i;
-       double roll, pitch, yaw, x[16], y[16], z[16];
-       int rc;
 
 #ifdef DEBUG_VERTEX
-       printf("draw island:\n");
+       printf("add island:\n");
 #endif
-       color = m68k_read_memory_8(vertex_address++) << 8;
-       color |= m68k_read_memory_8(vertex_address++);
-       gamecolor2gl(color);
 
-       /* get orientation */
-       mercenary_get_orientation(&roll, &pitch, &yaw);
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_ISLAND_POLYGON);
 
+       /* set color */
+       color = m68k_read_memory_8(vertex_address++) << 8;
+       color |= m68k_read_memory_8(vertex_address++);
+       gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
 
        /* the vertex list is zero-terminated */
        i = 0;
-       while (1) {
+       while (i < MAX_POLYGON) {
                vertex = m68k_read_memory_8(vertex_address++);
                if (vertex == 0 && i)
                        break;
                /* skip mysterious points when rendering island */
                if (vertex >= 0xf0)
                        continue;
-               rc = use_coord("island", vertex, &x[i], &y[i], &z[i]);
-               if (rc < 0)
-                       break;
-               /* rotate vertex */
-               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
-               if (i++ == 16)
-                       break;
+               render_item->u.polygon.vertex[i] = vertex;
+               i++;
        }
-       /* render polygon to OpenGL */
-       opengl_render_polygon_and_line(x, y, z, i); /* no culling, because polygons lay on the gound and are always visible! */
+       render_item->u.polygon.vertices = i;
 }
 
-/* draw sights */
+/* sights */
 static void draw_sights(void)
 {
-       double x[4], y[4], z[4];
-
-       /* use default fov of 64 to calculate z distance */
-       z[0] = z[1] = z[2] = z[3] = 160.0 / frustum_slope_64;
-
-       /* white */
-       gamecolor2gl(0x777);
-
-       y[0] = y[3] = -1.0;
-       y[1] = y[2] = 1.0;
-       x[0] = x[1] = -16.0;
-       x[2] = x[3] = -8.0;
-       opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
-       x[0] = x[1] = 8.0;
-       x[2] = x[3] = 16.0;
-       opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+#ifdef DEBUG_VERTEX
+       printf("add sights:\n");
+#endif
+
+       /* allocate render item */
+       render_item_add(RENDER_ITEM_SIGHTS);
 }
 
 /* stop event from CPU received */
-void render_improved_event(int event)
+void render_capture_event(int event)
 {
        switch (event) {
        case STOP_AT_CLEAR_SCREEN1:
@@ -1526,3 +1256,775 @@ void render_improved_event(int event)
        }
 }
 
+static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z)
+{
+       render_item_t *ri = NULL;
+
+       if ((vertex & 3)) {
+               print_error("Vertex %d is not a multiple of four!\n", vertex);
+               return -1;
+       }
+       if (vertex < 0x100) {
+               if (!render_item_vertices_0) {
+                       print_error("Vertices item for vertex %d not yet set!\n", vertex);
+                       return -1;
+               }
+               ri = render_item_vertices_0;
+       } else
+       if (vertex < 0x200) {
+               if (!render_item_vertices_1) {
+                       print_error("Vertices item for vertex %d not yet set!\n", vertex);
+                       return -1;
+               }
+               ri = render_item_vertices_1;
+               vertex -= 0x100;
+       } else
+       if (vertex < 0x300) {
+               if (!render_item_vertices_2) {
+                       print_error("Vertices item for vertex %d not yet set!\n", vertex);
+                       return -1;
+               }
+               ri = render_item_vertices_2;
+               vertex -= 0x200;
+       } else {
+               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+               return -1;
+       }
+       vertex >>= 2;
+       *x = ri->u.vertices.x[vertex];
+       *y = ri->u.vertices.y[vertex];
+       *z = ri->u.vertices.z[vertex];
+#ifdef DEBUG_VERTEX
+       printf("using %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, *x, *y, *z);
+#endif
+
+       return 0;
+}
+
+static int use_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, int level, double *x, double *y, double *z)
+{
+       if ((vertex & 3)) {
+               print_error("Vertex is not a multiple of four!\n");
+               return -1;
+       }
+       if (vertex >= MAX_VERTEX) {
+               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+               return -1;
+       }
+       if (level < 1 || level > 4) {
+               print_error("Level %d is out of range (1..4)!\n", level);
+               return -1;
+       }
+       if (!render_item_vertices_interior) {
+               print_error("Vertices item for interior verticies not yet set!\n");
+               return -1;
+       }
+       vertex >>= 2;
+       *x = render_item_vertices_interior->u.vertices_interior.x[vertex];
+       *y = render_item_vertices_interior->u.vertices_interior.y[level - 1];
+       *z = render_item_vertices_interior->u.vertices_interior.z[vertex];
+#ifdef DEBUG_VERTEX
+       printf("using %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, *x, *y, *z);
+#endif
+
+       return 0;
+}
+
+/* renders one item from render list */
+void render_one_item(render_item_t *render_item)
+{
+       switch (render_item->type) {
+       case RENDER_ITEM_VERTICES_0:
+       {
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_VERTICES_0\n");
+#endif
+               render_item_vertices_0 = render_item;
+               break;
+       }
+       case RENDER_ITEM_VERTICES_1:
+       {
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_VERTICES_1\n");
+#endif
+               render_item_vertices_1 = render_item;
+               break;
+       }
+       case RENDER_ITEM_VERTICES_2:
+       {
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_VERTICES_2\n");
+#endif
+               render_item_vertices_2 = render_item;
+               break;
+       }
+       case RENDER_ITEM_VERTICES_INTERIOR:
+       {
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_VERTICES_INTERIOR\n");
+#endif
+               render_item_vertices_interior = render_item;
+               break;
+       }
+       case RENDER_ITEM_SKY:
+       {
+               double x[4], y[4], z[4];
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_SKY\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.sky.red, render_item->u.sky.green, render_item->u.sky.blue, 1.0);
+               /* create plane to fill view */
+               x[0] = x[1] = y[1] = y[2] = -1000000;
+               x[2] = x[3] = y[0] = y[3] = 1000000;
+               z[0] = z[1] = z[2] = z[3] = 10;
+               /* render */
+               opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sky (background) is always visible! */
+               break;
+       }
+       case RENDER_ITEM_GROUND:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[4], y[4], z[4];
+               int i;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_GROUND\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.ground.red, render_item->u.ground.green, render_item->u.ground.blue, 1.0);
+               yaw = 0.0; /* no need to rotate x-z plane, we don't want look at a corner of the 'ground-square' */
+               /* create huge square */
+               x[0] = x[1] = z[1] = z[2] = -1000000;
+               x[2] = x[3] = z[0] = z[3] = 1000000;
+               y[0] = y[1] = y[2] = y[3] = -10;
+               /* rotate vertex */
+               for (i = 0; i < 4; i++)
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               /* render */
+               opengl_render_polygon(x, y, z, 4, 0); /* no culling, because gound is always visible! */
+               break;
+       }
+       case RENDER_ITEM_OBJECT_POLYGON:
+       case RENDER_ITEM_TAG_POLYGON:
+       case RENDER_ITEM_ISLAND_POLYGON:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               if (render_item->type == RENDER_ITEM_OBJECT_POLYGON)
+                       printf("RENDER_ITEM_OBJECT_POLYGON\n");
+               if (render_item->type == RENDER_ITEM_TAG_POLYGON)
+                       printf("RENDER_ITEM_TAG_POLYGON\n");
+               if (render_item->type == RENDER_ITEM_ISLAND_POLYGON)
+                       printf("RENDER_ITEM_ISLAND_POLYGON\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < render_item->u.polygon.vertices; i++) {
+                       /* get vertex */
+                       rc = use_coord("object", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_polygon(x, y, z, render_item->u.polygon.vertices, 1); /* back face culling */
+               break;
+       }
+       case RENDER_ITEM_OBJECT_LINE:
+       case RENDER_ITEM_TAG_LINE:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[2], y[2], z[2];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               if (render_item->type == RENDER_ITEM_OBJECT_LINE)
+                       printf("RENDER_ITEM_OBJECT_LINE\n");
+               if (render_item->type == RENDER_ITEM_TAG_LINE)
+                       printf("RENDER_ITEM_TAG_LINE\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < 2; i++) {
+                       /* get vertex */
+                       rc = use_coord("object", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+               break;
+       }
+       case RENDER_ITEM_BEACON_POINT:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x, y, z;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BEACON_POINT\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.point.red, render_item->u.point.green, render_item->u.point.blue, debug_opacity);
+               /* get vertex */
+               rc = use_coord("beacon", render_item->u.point.vertex, &x, &y, &z);
+               if (rc < 0)
+                       break;
+               /* rotate vertex */
+               rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
+               /* render */
+               opengl_render_point(x, y, z, 0.0);
+               break;
+       }
+       case RENDER_ITEM_BUILDING_EXTERIOR_POLYGON:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BUILDING_EXTERIOR_POLYGON\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < render_item->u.polygon.vertices; i++) {
+                       /* get vertex */
+                       rc = use_coord("building exterior", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_polygon(x, y, z, render_item->u.polygon.vertices, 1); /* back face culling */
+               break;
+       }
+       case RENDER_ITEM_BUILDING_EXTERIOR_LINE:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[2], y[2], z[2];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BUILDING_EXTERIOR_LINE\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < 2; i++) {
+                       /* get vertex */
+                       rc = use_coord("building exterior", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+               break;
+       }
+       case RENDER_ITEM_BUILDING_INTERIOR_1TO4:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[4], y[4], z[4];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BUILDING_INTERIOR_1TO4\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.interior14.red, render_item->u.interior14.green, render_item->u.interior14.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < 4; i++) {
+                       /* get vertex */
+                       rc = use_interior_coord("building exterior", render_item->u.interior14.vertex[i], render_item->u.interior14.level, &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_polygon(x, y, z, 4, 1); /* back face culling */
+               break;
+       }
+       case RENDER_ITEM_BUILDING_INTERIOR_5TO6:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[4], y[4], z[4];
+               int i;
+               int vertex, level;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BUILDING_INTERIOR_5TO6\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.interior56.red, render_item->u.interior56.green, render_item->u.interior56.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < 4; i++) {
+                       /* get vertex */
+                       vertex = (i == 0 || i == 3) ? render_item->u.interior56.vertex14 : render_item->u.interior56.vertex23;
+                       level = (i == 0 || i == 1) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+                       rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_polygon(x, y, z, 4, 1); /* back face culling */
+               break;
+       }
+       case RENDER_ITEM_BUILDING_INTERIOR_WALL:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[4], y[4], z[4];
+               int i;
+               int vertex, level;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_BUILDING_INTERIOR_WALL\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.interior56.red, render_item->u.interior56.green, render_item->u.interior56.blue, debug_opacity);
+               /* chedck if wall is a rectangle or a line */
+               if (render_item->u.interior56.vertex14 != render_item->u.interior56.vertex23) {
+                       /* get and rotate vertex */
+                       for (i = 0; i < 4; i++) {
+                               /* get vertex */
+                               vertex = (i == 0 || i == 3) ? render_item->u.interior56.vertex14 : render_item->u.interior56.vertex23;
+                               level = (i == 0 || i == 1) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+                               rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+                               if (rc < 0)
+                                       break;
+                               /* rotate vertex */
+                               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+                       }
+                       /* render */
+                       opengl_render_polygon_and_line(x, y, z, 4); /* no culling, because walls are always visible! */
+               } else {
+                       /* get and rotate vertex */
+                       for (i = 0; i < 2; i++) {
+                               /* get vertex */
+                               vertex = render_item->u.interior56.vertex14;
+                               level = (i == 0) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+                               rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+                               if (rc < 0)
+                                       break;
+                               /* rotate vertex */
+                               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+                       }
+                       /* render */
+                       opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+               }
+               break;
+       }
+       case RENDER_ITEM_COMET_POLYGON:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double inclination = planet_inclination, azimuth = planet_azimuth;
+               double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_COMET_POLYGON\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < render_item->u.polygon.vertices; i++) {
+                       /* get vertex */
+                       rc = use_coord("comet tail", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       if (planet_rotation)
+                               rotate_coordinate(0.0, inclination, azimuth, &x[i], &y[i], &z[i]);
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_polygon_and_line(x, y, z, render_item->u.polygon.vertices); /* no culling, because we render only two (out of four) planes! */
+               break;
+       }
+       case RENDER_ITEM_ROAD_LINE:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[2], y[2], z[2];
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_ROAD_LINE\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+               /* get and rotate vertex */
+               for (i = 0; i < 2; i++) {
+                       /* get vertex */
+                       rc = use_coord("road", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+                       if (rc < 0)
+                               break;
+                       /* rotate vertex */
+                       rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+               }
+               /* render */
+               opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+               break;
+       }
+       case RENDER_ITEM_ROAD_POLYGON:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+               int i, v;
+               uint32_t vertex, vertex_prev, vertex_next;
+               double x_current, y_current, z_current;
+               double x_prev, y_prev, z_prev;
+               double x_next, y_next, z_next;
+               int vertices_num;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_ROAD_POLYGON\n");
+#endif
+               /* get color */
+               opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+               /* get and rotate vertex */
+               i = 0;
+               vertices_num = render_item->u.polygon.vertices;
+               for (v = 0; v < vertices_num; v++) {
+                       /* get vertex */
+                       vertex = render_item->u.polygon.vertex[v];
+                       rc = use_coord("road/place", vertex, &x_current, &y_current, &z_current);
+                       if (rc < 0)
+                               break;
+                       /* check for road extension, so we extend the road to the given end point */
+                       if (extend_roads && vertex >= 0xf0) {
+                               /* previous vertex */
+                               vertex_prev = render_item->u.polygon.vertex[(v + vertices_num - 1) % vertices_num];
+                               rc = use_coord("road/place", vertex_prev, &x_prev, &y_prev, &z_prev);
+                               if (rc < 0)
+                                       break;
+                               /* next vertex */
+                               vertex_next = render_item->u.polygon.vertex[(v + 1) % vertices_num];
+                               rc = use_coord("road/place", vertex_next, &x_next, &y_next, &z_next);
+                               if (rc < 0)
+                                       break;
+                               /* extend vertices to end point position
+                                * change x or z coordinate, whatever is greater
+                               */
+                               if (fabs(x_prev - x_current) > fabs(z_prev - z_current))
+                                       x_prev = x_next = x_current;
+                               else
+                                       z_prev = z_next = z_current;
+                               /* store vertices */
+                               x[i] = x_prev;
+                               y[i] = y_prev;
+                               z[i] = z_prev;
+                               /* rotate vertex */
+                               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+                               if (i++ == MAX_POLYGON)
+                                       break;
+                               x[i] = x_next;
+                               y[i] = y_next;
+                               z[i] = z_next;
+                               /* rotate vertex */
+                               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+                               if (i++ == MAX_POLYGON)
+                                       break;
+                               continue;
+                       } else {
+                               /* no extension, just keep the current point as is */
+                               x[i] = x_current;
+                               y[i] = y_current;
+                               z[i] = z_current;
+                               /* rotate vertex */
+                               rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+                               if (i++ == MAX_POLYGON)
+                                       break;
+                       }
+               }
+               /* render */
+               opengl_render_polygon(x, y, z, i, 0); /* no culling, because polygons lay on the gound and are always visible! */
+               break;
+       }
+       case RENDER_ITEM_PLANET:
+       {
+               double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+               double inclination = planet_inclination, azimuth = planet_azimuth;
+               double sun_x, sun_y, sun_z, angle_sun;
+               double loc_x, loc_y, loc_z, angle_loc;
+               double x[PLANET_VERTICES], y[PLANET_VERTICES], z[PLANET_VERTICES];
+               double size, angle;
+               int i;
+               int rc;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_PLANET\n");
+#endif
+               /* get location */
+               rc = use_coord("planet(sun)", 0, &sun_x, &sun_y, &sun_z);
+               if (rc < 0)
+                       break;
+               rc = use_coord("planet", render_item->u.planet.vertex, &loc_x, &loc_y, &loc_z);
+               if (rc < 0)
+                       break;
+               /* get size */
+               size = render_item->u.planet.size;
+               /* rotate vertex */
+               if (planet_rotation) {
+                       rotate_coordinate(0.0, inclination, azimuth, &sun_x, &sun_y, &sun_z);
+                       rotate_coordinate(0.0, inclination, azimuth, &loc_x, &loc_y, &loc_z);
+               }
+               rotate_coordinate(roll, pitch, yaw, &sun_x, &sun_y, &sun_z);
+               rotate_coordinate(roll, pitch, yaw, &loc_x, &loc_y, &loc_z);
+
+               /* calculate direction of the sun */
+               angle_sun = atan2(sun_x, sun_z);
+               angle_loc = atan2(loc_x, loc_z);
+               angle = angle_sun - angle_loc;
+               if (angle > M_PI)
+                       angle -= 2.0 * M_PI;
+               if (angle < -M_PI)
+                       angle += 2.0 * M_PI;
+
+               /* on which side are we (sun is always bright, vertex == 0) */
+               if ((angle < M_PI / 2.0 && angle > -M_PI / 2.0) || render_item->u.planet.vertex == 0) {
+                       /* get front side color */
+                       opengl_render_color(render_item->u.planet.front_red, render_item->u.planet.front_green, render_item->u.planet.front_blue, debug_opacity);
+               } else {
+                       /* get back side color */
+                       opengl_render_color(render_item->u.planet.back_red, render_item->u.planet.back_green, render_item->u.planet.back_blue, debug_opacity);
+               }
+
+               /* create and render cicle */
+               for (i = 0; i < PLANET_VERTICES; i++) {
+                       x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
+                       y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
+                       z[i] = loc_z;
+               }
+               opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
+
+               if (render_item->u.planet.vertex == 0) {
+                       /* sun has no crescent */
+                       break;
+               }
+
+               /* on which side are we */
+               if (angle < M_PI / 2.0 && angle > -M_PI / 2.0) {
+                       /* get back side color */
+                       opengl_render_color(render_item->u.planet.back_red, render_item->u.planet.back_green, render_item->u.planet.back_blue, debug_opacity);
+               } else {
+                       /* get front side color */
+                       opengl_render_color(render_item->u.planet.front_red, render_item->u.planet.front_green, render_item->u.planet.front_blue, debug_opacity);
+               }
+
+               /* create and render crescent */
+               if (angle > M_PI / 2.0 || (angle < 0.0 && angle > -M_PI / 2.0)) {
+                       angle = fabs(angle);
+                       if (angle > M_PI / 2.0)
+                               angle = M_PI - angle;
+                       /* to the right */
+                       for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
+                               x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
+                               y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
+                               z[i] = loc_z;
+                       }
+                       for (; i < PLANET_VERTICES; i++) {
+                               x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE * sin((1.0 - angle / (M_PI / 2)) * (M_PI / 2.0));
+                               y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
+                               z[i] = loc_z;
+                       }
+               } else {
+                       angle = fabs(angle);
+                       if (angle > M_PI / 2.0)
+                               angle = M_PI - angle;
+                       /* to the left */
+                       for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
+                               x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE * sin((1.0 - angle / (M_PI / 2)) * (M_PI / 2.0));
+                               y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
+                               z[i] = loc_z;
+                       }
+                       for (; i < PLANET_VERTICES; i++) {
+                               x[i] = loc_x + size * sin(2 * M_PI * (double)i / PLANET_VERTICES) * PLANET_ELIPSE;
+                               y[i] = loc_y + size * cos(2 * M_PI * (double)i / PLANET_VERTICES);
+                               z[i] = loc_z;
+                       }
+               }
+               opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
+               opengl_render_point(loc_x, loc_y, loc_z, 0.0); /* planet is visible at any distance - at least as a point  */
+               break;
+       }
+       case RENDER_ITEM_STARS:
+       {
+               int16_t tilt_offset = 0;
+               int x_offset = 0;
+               uint16_t color[16];
+               uint16_t view_width, yaw = orientation_raw_yaw;
+               int16_t pitch = orientation_raw_pitch;
+               uint32_t table, table_start;
+               int16_t x, y;
+               double z;
+               int i;
+               double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_STARS\n");
+#endif
+               /* use default fov of 64 to calculate z distance */
+               z = 160.0 / frustum_slope_64;
+
+               view_width = (int)(320.0 / frustum_slope_64 * frustum_slope_fov);
+
+               /* get palette */
+               for (i = 0; i < 16; i++)
+                       color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+
+               /* table offset is 91, so we substract it and add it back with different FOV, so table begins at later
+                * full turn is 1024, we have default of 64 degrees: 1024 / 360 * 64 = 182
+                * then we half it, so we get to the center via 91
+                */
+
+               if (render_item->u.stars.above_zenith)
+                       yaw = 0x200 + yaw;
+               yaw = (yaw + 91 - (int)(91.0 * (frustum_slope_fov / frustum_slope_64))) & 0x3ff;
+               yaw <<= 1;
+               table = mercenary_star_table();
+               table_start = table + m68k_read_memory_16(table);
+               table += m68k_read_memory_16(table + yaw);
+               yaw = ((uint32_t)yaw * 0xe10e) >> 16;
+
+               if (render_item->u.stars.above_zenith)
+                       pitch = 0x200 - pitch;
+               pitch = pitch & 0x3ff;
+               pitch -= render_item->u.stars.v_offset;
+               pitch <<= 2;
+               pitch = (pitch * 0x6ccc) >> 16;
+
+               while (1) {
+                       x = m68k_read_memory_16(table);
+                       if (x >= 1800) {
+                               x_offset += 1800;
+                               table = table_start;
+                       }
+                       x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
+                       table += 2;
+                       if (x < 0)
+                               break;
+                       /* special case where we tilt the view when flying on the planet */
+                       if (render_item->u.stars.tilt) {
+                               /* use offset as given by game: 160 is half of the screen width
+                                * we extend the width to the actual FOV, so it fits
+                                */
+                               tilt_offset = (int32_t)((x - (int16_t)(160.0 / frustum_slope_64 * frustum_slope_fov)) * render_item->u.stars.tilt_value) >> 16;
+                       }
+                       y = ((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
+                       table += 2;
+                       if (render_item->u.stars.above_zenith) {
+                               x = (view_width - 1) - x;
+                               y = ~y + 136;
+                       }
+                       /* get color */
+                       gamecolor2gl(&red, &green, &blue, color[(m68k_read_memory_8(table - 2) & 0x3c) >> 2]);
+                       opengl_render_color(red, green, blue, debug_opacity);
+                       /* render point */
+                       opengl_render_point(160.0 / frustum_slope_64 * frustum_slope_fov - (double)x, 68.0 - (double)y, z, 0.0);
+               }
+               break;
+       }
+       case RENDER_ITEM_INTERSTELLAR_STARS:
+       {
+               uint16_t color[16];
+               double z;
+               int i;
+               double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_INTERSTELLAR_STARS\n");
+#endif
+               /* use default fov of 64 to calculate z distance */
+               z = 160.0 / frustum_slope_64;
+
+               /* get palette */
+               for (i = 0; i < 16; i++)
+                       color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+
+               for (i = 0; i < render_item->u.interstars.count; i++) {
+                       gamecolor2gl(&red, &green, &blue, color[render_item->u.interstars.color[i]]);
+                       opengl_render_color(red, green, blue, debug_opacity);
+                       /* render point */
+                       opengl_render_point(160.0 - (double)render_item->u.interstars.x[i], 68.0 - (double)render_item->u.interstars.y[i], z, 0.0);
+               }
+               break;
+       }
+       case RENDER_ITEM_INTERSTELLAR_SUN:
+       {
+               double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_INTERSTELLAR_SUN\n");
+#endif
+               /* white */
+               gamecolor2gl(&red, &green, &blue, 0x777);
+               opengl_render_color(red, green, blue, debug_opacity);
+               /* render point */
+               opengl_render_point(0.0, 0.0, 100.0, 0.0);
+               break;
+       }
+       case RENDER_ITEM_SIGHTS:
+       {
+               double x[4], y[4], z[4];
+               double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+               printf("RENDER_ITEM_SIGHTS\n");
+#endif
+               /* use default fov of 64 to calculate z distance */
+               z[0] = z[1] = z[2] = z[3] = 160.0 / frustum_slope_64;
+
+               /* white */
+               gamecolor2gl(&red, &green, &blue, 0x777);
+               opengl_render_color(red, green, blue, debug_opacity);
+
+               y[0] = y[3] = -1.0;
+               y[1] = y[2] = 1.0;
+               x[0] = x[1] = -16.0;
+               x[2] = x[3] = -8.0;
+               opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+               x[0] = x[1] = 8.0;
+               x[2] = x[3] = 16.0;
+               opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+               break;
+       }
+       default:
+               print_error("Unknown type, please fix!\n");
+       }
+}
+
+void render_all_items()
+{
+       render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
+       render_item_vertices_interior = NULL;
+
+       for (render_item = render_list_start; render_item; render_item = render_item->next) {
+               render_one_item(render_item);
+       }
+}
+
index 4549675..67d9bc8 100644 (file)
@@ -1,5 +1,6 @@
 
-void render_start(double _fov, int _extend_roads, int debug);
-void render_finish(void);
-void render_improved_event(int event);
+void render_capture_start(double _fov, int _extend_roads, int debug);
+void render_capture_stop(void);
+void render_capture_event(int event);
+void render_all_items();