OVR: Add patch to make game render planets behind observer
[mercenary-reloaded.git] / src / mercenary / render.c
index 85498fc..8f0b140 100644 (file)
@@ -38,7 +38,6 @@
 #include <stdlib.h>
 #include <string.h>
 #include <math.h>
-#include <GL/glew.h>
 #include "../libsdl/print.h"
 #include "../libcpu/m68k.h"
 #include "../libcpu/m68kcpu.h"
@@ -46,6 +45,9 @@
 #include "../libsdl/opengl.h"
 #include "mercenary.h"
 
+#define GL3_PROTOTYPES 1
+#include <GL/glew.h>
+
 //#define DEBUG_COLOR
 //#define DEBUG_VERTEX
 //#define DEBUG_ITEMS
@@ -105,7 +107,7 @@ struct render_item_info {
 };
 
 struct render_item_vertices {
-       int32_t x[MAX_VERTEX >> 2], y[MAX_VERTEX >> 2], z[MAX_VERTEX >> 2];
+       double x[MAX_VERTEX >> 2], y[MAX_VERTEX >> 2], z[MAX_VERTEX >> 2];
 };
 
 struct render_item_vertices_interior {
@@ -213,10 +215,12 @@ typedef struct interpolation {
        double offset_east, offset_height, offset_north;
        double orientation_roll, orientation_pitch, orientation_yaw;
        double orientation_raw_yaw, orientation_raw_pitch;
+       double planet_inclination, planet_azimuth;
        int object_id[MAX_MOVING_OBJECTS];
        double object_offset_east[MAX_MOVING_OBJECTS], object_offset_height[MAX_MOVING_OBJECTS], object_offset_north[MAX_MOVING_OBJECTS];
        int object_count;
        render_item_t *interior;
+       render_item_t *planets;
 } interpolation_t;
 
 #define GET_ORIENTATION \
@@ -253,7 +257,7 @@ static render_item_t *render_item;
 static render_item_t *render_item_object_info;
 /* current vertices */
 static render_item_t *render_item_vertices_0, *render_item_vertices_1, *render_item_vertices_2;
-static render_item_t *render_item_vertices_interior;
+static render_item_t *render_item_vertices_planets, *render_item_vertices_interior;
 
 /*
  * capturing
@@ -314,11 +318,12 @@ void render_capture_start(double _fov, int _extend_roads, int debug)
        /* in case of player on the ground, there is no roll, so it will be reset to 0 when screen is cleared */
        mercenary_get_orientation(&motion_new.orientation_roll, &motion_new.orientation_pitch, &motion_new.orientation_yaw);
        mercenary_get_orientation_raw(&motion_new.orientation_raw_pitch, &motion_new.orientation_raw_yaw);
-       motion_new.planet_rotation = 0;
+       motion_new.planet_rotation = motion_old.planet_rotation;
        mercenary_get_orientation_planet(&motion_new.planet_inclination, &motion_new.planet_azimuth);
 
        render_item_object_info = NULL;
        render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
+       render_item_vertices_planets = NULL;
        render_item_vertices_interior = NULL;
 
        /* detect elevator movement */
@@ -358,7 +363,7 @@ static void gamecolor2gl_index(double *red, double *green, double *blue, uint16_
 #endif
        if (color >= 0x8000) {
 #ifdef DEBUG_COLOR
-               print_error("Use of color index from current palette, but index is not defined as being set!\n");
+               fprintf(stderr, "Use of color index from current palette, but index is not defined as being set!\n");
 #endif
        }
        *red = (double)((color >> 8) & 0xf) / 15.0;
@@ -396,7 +401,7 @@ again:
 #endif
                /* now use that color info parse again (hopefully it does not contain a "pre-defined palette" again and again! */
                if (nesting++ == 8) {
-                       print_error("Color lookup from pre-defined palette is nesting too much, please fix!\n");
+                       print_info("Color lookup from pre-defined palette is nesting too much, please fix!\n");
                        return;
                }
                goto again;
@@ -416,7 +421,7 @@ static int32_t wrap_int28(int32_t value)
 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);
+               print_info("Vertex %d is not a multiple of four!\n", vertex);
                return;
        }
        /* create new vertices item, if there was no vertex before, or if the vertex has different offet */
@@ -449,12 +454,12 @@ static void store_coord(const char __attribute__((unused)) *what, uint32_t verte
                }
                vertex -= 0x200;
        } else {
-               print_error("Vertex %d exceeds maximum vertex number, please fix!\n", vertex);
+               print_info("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);
+       printf("storing %s coordinates: vertex=%d, x=%d, y=%d, z=%d\n", what, vertex, x, y, z);
 #endif
        /* use absolute position */
        x += motion_new.position_east;
@@ -465,21 +470,48 @@ static void store_coord(const char __attribute__((unused)) *what, uint32_t verte
        render_item->u.vertices.z[vertex] = z;
 }
 
+static void store_planets_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z)
+{
+       if ((vertex & 3)) {
+               print_info("Vertex %d is not a multiple of four!\n", vertex);
+               return;
+       }
+       /* create new vertices item, if there was no vertex before, or if the vertex has different offet */
+       if (vertex >= MAX_VERTEX) {
+               print_info("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_INTERIOR_VERTEX);
+               return;
+       }
+       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;
+       }
+       vertex >>= 2;
+#ifdef DEBUG_VERTEX
+       printf("storing %s coordinates: vertex=%d, x=%d, y=%d, z=%d\n", what, vertex, x, y, z);
+#endif
+       render_item->u.vertices.x[vertex] = x;
+       render_item->u.vertices.y[vertex] = y;
+       render_item->u.vertices.z[vertex] = 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");
+               print_info("Vertex is not a multiple of four!\n");
                return;
        }
        if (vertex >= MAX_INTERIOR_VERTEX) {
-               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_INTERIOR_VERTEX);
+               print_info("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);
+       printf("storing %s coordinates: vertex=%d, x=%d, y=%d;%d;%d;%d, z=%d\n", what, vertex, x, y1, y2, y3, y4, z);
 #endif
        /* use absolute position */
        x += motion_new.position_east;
@@ -502,22 +534,26 @@ static void rotate_coordinate(double roll, double pitch, double yaw, double *x,
        double out_x, out_y, out_z;
 
        /* rotate yaw (German: Gier, turn view to the right) */
-       out_z = (*z) * cos(yaw) - (*x) * sin(yaw);
-       out_x = (*z) * sin(yaw) + (*x) * cos(yaw);
-       *z = out_z;
-       *x = out_x;
+       if (yaw) {
+               out_z = (*z) * cos(yaw) - (*x) * sin(yaw);
+               out_x = (*z) * sin(yaw) + (*x) * cos(yaw);
+               *z = out_z;
+               *x = out_x;
+       }
        /* rotate pitch (German: Nick, turn head down) */
-       out_y = (*y) * cos(pitch) - (*z) * sin(pitch);
-       out_z = (*y) * sin(pitch) + (*z) * cos(pitch);
-       *y = out_y;
-       *z = out_z;
-       if (roll == 0.0)
-               return;
+       if (pitch) {
+               out_y = (*y) * cos(pitch) - (*z) * sin(pitch);
+               out_z = (*y) * sin(pitch) + (*z) * cos(pitch);
+               *y = out_y;
+               *z = out_z;
+       }
        /* rotate roll (tilt head to the right) */
-       out_x = (*x) * cos(roll) - (*y) * sin(roll);
-       out_y = (*x) * sin(roll) + (*y) * cos(roll);
-       *x = out_x;
-       *y = out_y;
+       if (roll) {
+               out_x = (*x) * cos(roll) - (*y) * sin(roll);
+               out_y = (*x) * sin(roll) + (*y) * cos(roll);
+               *x = out_x;
+               *y = out_y;
+       }
 }
 
 /* clear screen color (sky / universe) */
@@ -825,7 +861,7 @@ 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], x, y, z);
+       store_planets_coord("comet tail", REG_A[0], x, y, z);
 }
 
 /* polygon of comet tail */
@@ -1026,7 +1062,7 @@ 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], x, y, z);
+       store_planets_coord("planet", REG_A[0], x, y, z);
 }
 
 /* planet */
@@ -1113,7 +1149,7 @@ static void draw_stars_interstellar(void)
        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);
+               print_info("Expecting maximum of %d stars here, plese fix!\n", MAX_INTERSTARS);
                return;
        }
        for (i = 0; i < count; i++) {
@@ -1317,7 +1353,7 @@ void render_capture_event(int event)
        case STOP_AT_POLY_BUILDING_INTERIOR1to4:
                /* before we come here, we must already passed the break points above, so we know the level to be rendered */
                if (interior_level12 == 0) {
-                       print_error("Interior level is not set, please fix!\n");
+                       print_info("Interior level is not set, please fix!\n");
                        break;
                }
                poly_building_interior1to4(interior_level12);
@@ -1326,7 +1362,7 @@ void render_capture_event(int event)
        case STOP_AT_POLY_BUILDING_INTERIOR5to6:
                /* before we come here, we must already passed the break points above, so we know the level to be rendered */
                if (interior_level12 == 0) {
-                       print_error("Interior level is not set, please fix!\n");
+                       print_info("Interior level is not set, please fix!\n");
                        break;
                }
                poly_building_interior5to6(interior_level12, interior_level34);
@@ -1436,6 +1472,9 @@ void render_capture_event(int event)
        case STOP_AT_EXPLOSION:
                draw_explosion();
                break;
+       case STOP_AT_PATCH_RENDER:
+               mercenary_patch_render();
+               break;
        }
 }
 
@@ -1448,19 +1487,19 @@ static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex,
        render_item_t *ri = NULL;
 
        if ((vertex & 3)) {
-               print_error("Vertex %d is not a multiple of four!\n", vertex);
+               print_info("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);
+                       print_info("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);
+                       print_info("Vertices item for vertex %d not yet set!\n", vertex);
                        return -1;
                }
                ri = render_item_vertices_1;
@@ -1468,13 +1507,13 @@ static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex,
        } else
        if (vertex < 0x300) {
                if (!render_item_vertices_2) {
-                       print_error("Vertices item for vertex %d not yet set!\n", vertex);
+                       print_info("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);
+               print_info("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
                return -1;
        }
        vertex >>= 2;
@@ -1495,22 +1534,53 @@ static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex,
        return 0;
 }
 
+static int use_planet_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z)
+{
+       render_item_t *ri = NULL;
+
+       if ((vertex & 3)) {
+               print_info("Vertex %d is not a multiple of four!\n", vertex);
+               return -1;
+       }
+       if (vertex >= MAX_VERTEX) {
+               print_info("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+               return -1;
+       }
+       if (interpolation.planets)
+               ri = interpolation.planets;
+       else
+               ri = render_item_vertices_0;
+       if (!ri) {
+               print_info("Vertices item for planets verticies not yet set!\n");
+               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");
+               print_info("Vertex is not a multiple of four!\n");
                return -1;
        }
        if (vertex >= MAX_INTERIOR_VERTEX) {
-               print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+               print_info("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);
+               print_info("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");
+               print_info("Vertices item for interior verticies not yet set!\n");
                return -1;
        }
        vertex >>= 2;
@@ -1534,7 +1604,7 @@ static int use_interior_coord(const char __attribute__((unused)) *what, uint32_t
 }
 
 /* renders one item from render list */
-void render_one_item(render_item_t *render_item)
+void render_one_item(render_item_t *render_item, int vr)
 {
        switch (render_item->type) {
        case RENDER_ITEM_OBJECT_INFO:
@@ -1643,7 +1713,7 @@ void render_one_item(render_item_t *render_item)
 #endif
 
                /* special case where we don't want to interpolate motion (taxi/busses/intercity) */
-               if (render_item->type == RENDER_ITEM_OBJECT_POLYGON && render_item_object_info && !render_item_object_info->u.info.moving) {
+               if ((render_item->type == RENDER_ITEM_OBJECT_POLYGON || render_item->type == RENDER_ITEM_TAG_POLYGON_OBJECT) && render_item_object_info && !render_item_object_info->u.info.moving) {
 //                     GET_ORIENTATION_FIX;
                        fix = 1;
                }
@@ -1682,7 +1752,7 @@ void render_one_item(render_item_t *render_item)
                GET_ORIENTATION;
                int fix = 0;
                double x[2], y[2], z[2];
-               int i;
+               int i, o;
                int rc;
 
 #ifdef DEBUG_ITEMS
@@ -1708,6 +1778,18 @@ void render_one_item(render_item_t *render_item)
                        rc = use_coord("object", render_item->u.line.vertex[i], &x[i], &y[i], &z[i], fix);
                        if (rc < 0)
                                break;
+                       /* interpolate motion, if object is moving */
+                       if ((render_item->type == RENDER_ITEM_OBJECT_LINE || render_item->type == RENDER_ITEM_TAG_LINE_OBJECT)  && render_item_object_info && render_item_object_info->u.info.moving) {
+                               for (o = 0; o < interpolation.object_count; o++) {
+                                       if (interpolation.object_id[o] == render_item_object_info->u.info.id)
+                                               break;
+                               }
+                               if (o < interpolation.object_count) {
+                                       x[i] += interpolation.object_offset_east[o];
+                                       y[i] += interpolation.object_offset_height[o];
+                                       z[i] += interpolation.object_offset_north[o];
+                               }
+                       }
                        /* rotate vertex */
                        rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
                }
@@ -1887,7 +1969,7 @@ void render_one_item(render_item_t *render_item)
        case RENDER_ITEM_COMET_POLYGON:
        {
                GET_ORIENTATION;
-               double inclination = motion_new.planet_inclination, azimuth = motion_new.planet_azimuth;
+               double inclination = interpolation.planet_inclination, azimuth = interpolation.planet_azimuth;
                double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
                int i;
                int rc;
@@ -1900,7 +1982,7 @@ void render_one_item(render_item_t *render_item)
                /* 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], motion_new.planet_rotation);
+                       rc = use_planet_coord("comet tail", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
                        if (rc < 0)
                                break;
                        /* rotate vertex */
@@ -2016,11 +2098,14 @@ void render_one_item(render_item_t *render_item)
        case RENDER_ITEM_PLANET:
        {
                GET_ORIENTATION;
-               double inclination = motion_new.planet_inclination, azimuth = motion_new.planet_azimuth;
-               double sun_x, sun_y, sun_z, angle_sun;
-               double loc_x, loc_y, loc_z, angle_loc;
+               double inclination = interpolation.planet_inclination, azimuth = interpolation.planet_azimuth;
+               double sun_x, sun_y, sun_z, angle_sun_h;
+               double loc_x, loc_y, loc_z, angle_loc_h, angle_loc_v;
+               double circle_x[PLANET_VERTICES], circle_y[PLANET_VERTICES], circle_z[PLANET_VERTICES];
+               double crescent_x[PLANET_VERTICES], crescent_y[PLANET_VERTICES], crescent_z[PLANET_VERTICES];
                double x[PLANET_VERTICES], y[PLANET_VERTICES], z[PLANET_VERTICES];
-               double size, angle;
+               double size, angle, fabs_angle, crescent;
+               double _sin, _cos;
                int i;
                int rc;
 
@@ -2028,10 +2113,10 @@ void render_one_item(render_item_t *render_item)
                printf("RENDER_ITEM_PLANET\n");
 #endif
                /* get location */
-               rc = use_coord("planet(sun)", 0, &sun_x, &sun_y, &sun_z, motion_new.planet_rotation);
+               rc = use_planet_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, motion_new.planet_rotation);
+               rc = use_planet_coord("planet", render_item->u.planet.vertex, &loc_x, &loc_y, &loc_z);
                if (rc < 0)
                        break;
                /* get size */
@@ -2045,13 +2130,19 @@ void render_one_item(render_item_t *render_item)
                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;
+               angle_sun_h = atan2(sun_x, sun_z);
+               angle_loc_h = atan2(loc_x, loc_z);
+               angle_loc_v = atan2(loc_y, sqrt(loc_x * loc_x + loc_z * loc_z));
+               /* angle between planets */
+               angle = angle_sun_h - angle_loc_h;
                if (angle > M_PI)
                        angle -= 2.0 * M_PI;
                if (angle < -M_PI)
                        angle += 2.0 * M_PI;
+               /* absolute angle to be used as crescent */
+               fabs_angle = fabs(angle);
+               if (fabs_angle > M_PI / 2.0)
+                       fabs_angle = M_PI - fabs_angle;
 
                /* 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) {
@@ -2063,10 +2154,39 @@ void render_one_item(render_item_t *render_item)
                }
 
                /* create and render cicle */
+               crescent = sin((1.0 - fabs_angle / (M_PI / 2)) * (M_PI / 2.0));
+               if (vr) {
+                       for (i = 0; i < PLANET_VERTICES; i++) {
+                               _sin = size * sin(2.0 * M_PI * (double)i / PLANET_VERTICES);
+                               _cos = size * cos(2.0 * M_PI * (double)i / PLANET_VERTICES);
+                               circle_x[i] = _sin * PLANET_ELIPSE;
+                               circle_y[i] = _cos;
+                               circle_z[i] = 0.0;
+                               crescent_x[i] = circle_x[i] * crescent;
+                               crescent_y[i] = circle_y[i];
+                               crescent_z[i] = circle_z[i];
+                               /* rotate circle and cresent towards observer (billboarding) */
+                               rotate_coordinate(0.0, -angle_loc_v, 0.0, &circle_x[i], &circle_y[i], &circle_z[i]);
+                               rotate_coordinate(0.0, 0.0, angle_loc_h, &circle_x[i], &circle_y[i], &circle_z[i]);
+                               rotate_coordinate(0.0, -angle_loc_v, 0.0, &crescent_x[i], &crescent_y[i], &crescent_z[i]);
+                               rotate_coordinate(0.0, 0.0, angle_loc_h, &crescent_x[i], &crescent_y[i], &crescent_z[i]);
+                       }
+               } else {
+                       for (i = 0; i < PLANET_VERTICES; i++) {
+                               _sin = size * sin(2.0 * M_PI * (double)i / PLANET_VERTICES);
+                               _cos = size * cos(2.0 * M_PI * (double)i / PLANET_VERTICES);
+                               circle_x[i] = _sin * PLANET_ELIPSE;
+                               circle_y[i] = _cos;
+                               circle_z[i] = 0.0;
+                               crescent_x[i] = circle_x[i] * crescent;
+                               crescent_y[i] = circle_y[i];
+                               crescent_z[i] = circle_z[i];
+                       }
+               }
                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;
+                       x[i] = loc_x + circle_x[i];
+                       y[i] = loc_y + circle_y[i];
+                       z[i] = loc_z + circle_z[i];
                }
                opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
 
@@ -2086,34 +2206,29 @@ void render_one_item(render_item_t *render_item)
 
                /* 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;
+                               x[i] = loc_x + circle_x[i];
+                               y[i] = loc_y + circle_y[i];
+                               z[i] = loc_z + circle_z[i];
                        }
+                       _sin = sin((1.0 - angle / (M_PI / 2)) * (M_PI / 2.0));
                        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;
+                               x[i] = loc_x + crescent_x[i];
+                               y[i] = loc_y + crescent_y[i];
+                               z[i] = loc_z + crescent_z[i];
                        }
                } 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;
+                               x[i] = loc_x + crescent_x[i];
+                               y[i] = loc_y + crescent_y[i];
+                               z[i] = loc_z + crescent_z[i];
                        }
                        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;
+                               x[i] = loc_x + circle_x[i];
+                               y[i] = loc_y + circle_y[i];
+                               z[i] = loc_z + circle_z[i];
                        }
                }
                opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
@@ -2292,7 +2407,7 @@ void render_one_item(render_item_t *render_item)
                break;
        }
        default:
-               print_error("Unknown type, please fix!\n");
+               print_info("Unknown render item type, please fix!\n");
        }
 }
 
@@ -2475,15 +2590,55 @@ static void interpolate_objects(double inter)
        interpolation.object_count = count;
 }
 
+/* make a vertex list of interpolated planets */
+static render_item_t *interpolate_planets(double inter)
+{
+       static render_item_t interpolated;
+       render_item_t *old_info, *new_info;
+       render_item_t *old_vertices = NULL, *new_vertices = NULL;
+       int i;
+
+       /* get vertices for planets/comet */
+       for (old_info = render_list_old; old_info; old_info = old_info -> next) {
+               if (old_info->type == RENDER_ITEM_VERTICES_0)
+                       old_vertices = old_info;
+               /* check until comet's polygons are renderd. at this time the coordinates are all ready, so we can interpolate */
+               if (old_info->type == RENDER_ITEM_COMET_POLYGON)
+                       break;
+       }
+       for (new_info = render_list_new; new_info; new_info = new_info -> next) {
+               if (new_info->type == RENDER_ITEM_VERTICES_0)
+                       new_vertices = new_info;
+               /* check until comet's polygons are renderd. at this time the coordinates are all ready, so we can interpolate */
+               if (new_info->type == RENDER_ITEM_COMET_POLYGON)
+                       break;
+       }
+
+       /* check for existing planet's vertices and if planets are rendered in both lists (old and new) */
+       if (old_info == NULL || new_info == NULL || old_vertices == NULL || new_vertices == NULL)
+               return NULL;
+
+       /* interpolate vertices */
+       for (i = 0; i < (MAX_VERTEX >> 2); i++) {
+               interpolated.u.vertices.x[i] = old_vertices->u.vertices.x[i] * (1.0 - inter) + new_vertices->u.vertices.x[i] * inter;
+               interpolated.u.vertices.y[i] = old_vertices->u.vertices.y[i] * (1.0 - inter) + new_vertices->u.vertices.y[i] * inter;
+               interpolated.u.vertices.z[i] = old_vertices->u.vertices.z[i] * (1.0 - inter) + new_vertices->u.vertices.z[i] * inter;
+       }
+
+       return &interpolated;
+}
+
 /* always renders NEW! items
  * use inter == 1.0 to render motion to vertices of NEW items
  * use inter 0.0 .. 1.0 to interpolate motion between OLD and NEW items
+ * return 0, if the scene was rendered, returns < 0, if there is no scene
  */
-void render_all_items(double inter)
+int render_all_items(double inter, int vr)
 {
        render_item_object_info = NULL;
        render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
        render_item_vertices_interior = NULL;
+       render_item_vertices_planets = NULL;
 
        /* no interpolation when leaving or entering planet to/from space */
        if ((last_ground_index < 0 && ground_index >= 0)
@@ -2498,6 +2653,8 @@ void render_all_items(double inter)
        interpolation.orientation_yaw = motion_new.orientation_yaw;
        interpolation.orientation_raw_pitch = motion_new.orientation_raw_pitch;
        interpolation.orientation_raw_yaw = motion_new.orientation_raw_yaw;
+       interpolation.planet_inclination = motion_new.planet_inclination;
+       interpolation.planet_azimuth = motion_new.planet_azimuth;
 //printf("we are at %08x %08x %08x\n", motion_new.position_east, motion_new.position_height, motion_new.position_north);
 
        /* do interpolation */
@@ -2508,6 +2665,8 @@ void render_all_items(double inter)
                interpolation.orientation_yaw = interpolate_orientation(motion_old.orientation_yaw, motion_new.orientation_yaw, inter);
                interpolation.orientation_raw_pitch = interpolate_raw_orientation(motion_old.orientation_raw_pitch, motion_new.orientation_raw_pitch, inter);
                interpolation.orientation_raw_yaw = interpolate_raw_orientation(motion_old.orientation_raw_yaw, motion_new.orientation_raw_yaw, inter);
+               interpolation.planet_inclination = interpolate_orientation(motion_old.planet_inclination, motion_new.planet_inclination, inter);
+               interpolation.planet_azimuth = interpolate_orientation(motion_old.planet_azimuth, motion_new.planet_azimuth, inter);
 
                /* interpolate position */
                interpolation.offset_east = interpolate_offset(motion_old.position_east, motion_new.position_east, inter, 0);
@@ -2527,23 +2686,20 @@ void render_all_items(double inter)
 
                /* interpolate objects */
                interpolate_objects(inter);
-       }
 
-       /* add a blank background, if render list is empty */
-       if (!render_list_new) {
-               render_item_t blank;
-               memset(&blank, 0, sizeof(blank));
-               blank.type = RENDER_ITEM_SKY;
-               blank.u.sky.red = 0.5;
-               blank.u.sky.green = 0.5;
-               blank.u.sky.blue = 0.5;
-               render_one_item(&blank);
-               return;
+               /* interpolate planets */
+               interpolation.planets = interpolate_planets(inter);
        }
 
+       /* return failure, if nothing can be rendered */
+       if (!render_list_new)
+               return -1;
+
        for (render_item = render_list_new; render_item; render_item = render_item->next) {
-               render_one_item(render_item);
+               render_one_item(render_item, vr);
        }
+
+       return 0;
 }
 
 void render_capture_reset(void)