OVR: Make interstellar stars appear infinitely away
[mercenary-reloaded.git] / src / mercenary / render.c
index 37380db..4e8b98e 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
@@ -60,6 +62,8 @@
 #define PLANET_ELIPSE          1.17
 #define EXPLOSION_VERTICES     16
 #define EXPLOSION_ELIPSE       1.17
+#define SIGHT_DIST             78.74   /* distanc of sights in inch */
+#define FIX_OBJECT_SCALE       16
 
 /*
  *  render item definition and structures
@@ -105,7 +109,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 +217,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 +259,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
@@ -282,7 +288,7 @@ static void flush_old_items(void)
 }
 
 /* rendering starts, initialize variables */
-void render_capture_start(double _fov, int _extend_roads, int debug)
+void render_capture_start(double _fov, int _extend_roads, int _smooth_planets, int debug)
 {
 #if defined(DEBUG_COLOR) || defined(DEBUG_VERTEX)
        printf("start rendering a new frame...\n");
@@ -314,11 +320,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;
-       mercenary_get_orientation_planet(&motion_new.planet_inclination, &motion_new.planet_azimuth);
+       motion_new.planet_rotation = motion_old.planet_rotation;
+       mercenary_get_orientation_planet(&motion_new.planet_inclination, &motion_new.planet_azimuth, _smooth_planets);
 
        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 */
@@ -413,7 +420,7 @@ static int32_t wrap_int28(int32_t value)
        return value;
 }
 
-static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z)
+static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z, double scale)
 {
        if ((vertex & 3)) {
                print_info("Vertex %d is not a multiple of four!\n", vertex);
@@ -454,12 +461,36 @@ static void store_coord(const char __attribute__((unused)) *what, uint32_t verte
        }
        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;
-       y += motion_new.position_height;
-       z += motion_new.position_north;
+       render_item->u.vertices.x[vertex] = (double)x * scale + motion_new.position_east;
+       render_item->u.vertices.y[vertex] = (double)y * scale + motion_new.position_height;
+       render_item->u.vertices.z[vertex] = (double)z * scale + motion_new.position_north;
+}
+
+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;
@@ -479,7 +510,7 @@ static void store_interior_coord(const char __attribute__((unused)) *what, uint3
                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 +533,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) */
@@ -582,7 +617,7 @@ static void coord_object(void)
        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);
+       store_coord("object", REG_A[0], x, y, z, 1.0);
 }
 
 /* polygon of object */
@@ -651,7 +686,7 @@ static void coord_beacon(void)
        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);
+       store_coord("beacon", 0, x, y, z, 1.0);
 }
 
 /* point of beacon */
@@ -679,7 +714,7 @@ static void coord_building_exterior(void)
        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], x, y, z);
+       store_coord("building exterior", REG_A[0], x, y, z, 1.0);
 }
 
 /* polygon of building (exterior) */
@@ -825,7 +860,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 */
@@ -866,7 +901,7 @@ static void coord_line_road(void)
        x = REG_D[3];
        y = -motion_new.position_height;
        z = REG_D[5];
-       store_coord("road", REG_A[0], x, y, z);
+       store_coord("road", REG_A[0], x, y, z, 1.0);
 }
 
 /* line of road */
@@ -902,7 +937,7 @@ static void coord_poly_road(void)
        y = -motion_new.position_height;
        z = m68k_read_memory_32(576 + REG_A[0]);
        z -= REG_A[3];
-       store_coord("road/place", REG_A[0], x, y, z);
+       store_coord("road/place", REG_A[0], x, y, z, 1.0);
 }
 
 /* polygon of road */
@@ -946,7 +981,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], x, y, z);
+       store_coord("tags", REG_A[0], x, y, z, 1.0);
 }
 
 /* coordinates ready for large tags */
@@ -960,7 +995,10 @@ 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], x, y, z);
+       /* note that large tags have double distance, so the resolution is vitrually doubled.
+        * since we use interpolation and VR, we need to scale the vertex back to normal distance.
+        */
+       store_coord("large tags", REG_A[0], x, y, z, 0.5);
 }
 
 /* line of tag */
@@ -1026,7 +1064,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 */
@@ -1151,7 +1189,7 @@ static void coord_islands(void)
        y = -motion_new.position_height;
        z = ((int16_t)m68k_read_memory_16(REG_A[4]) * 65536);
        z += (int32_t)REG_A[3];
-       store_coord("island", REG_A[0], x, y, z);
+       store_coord("island", REG_A[0], x, y, z, 1.0);
 }
 
 /* polygon of island */
@@ -1271,6 +1309,8 @@ void render_capture_event(int event)
                break;
        case STOP_AT_POINT_BEACON:
                point_beacon();
+               /* note: we may not call the point-renderer, because projected coordinates are invalid */
+               mercenary_patch_render();
                break;
        case STOP_AT_COORD_BUILDING_EXTERIOR:
                coord_building_exterior();
@@ -1436,6 +1476,9 @@ void render_capture_event(int event)
        case STOP_AT_EXPLOSION:
                draw_explosion();
                break;
+       case STOP_AT_PATCH_RENDER:
+               mercenary_patch_render();
+               break;
        }
 }
 
@@ -1495,6 +1538,37 @@ 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)) {
@@ -1534,7 +1608,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:
@@ -1589,12 +1663,25 @@ void render_one_item(render_item_t *render_item)
 #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! */
+               /* create box to fill view */
+               x[0] = x[1] = y[1] = y[2] = -1000;
+               x[2] = x[3] = y[0] = y[3] = 1000;
+               z[0] = z[1] = z[2] = z[3] = 1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
+               z[0] = z[1] = z[2] = z[3] = -1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
+               x[0] = x[1] = z[1] = z[2] = -1000;
+               x[2] = x[3] = z[0] = z[3] = 1000;
+               y[0] = y[1] = y[2] = y[3] = 1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
+               y[0] = y[1] = y[2] = y[3] = -1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
+               y[0] = y[1] = z[1] = z[2] = -1000;
+               y[2] = y[3] = z[0] = z[3] = 1000;
+               x[0] = x[1] = x[2] = x[3] = 1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
+               x[0] = x[1] = x[2] = x[3] = -1000;
+               opengl_render_polygon_and_line(x, y, z, 4);
                break;
        }
        case RENDER_ITEM_GROUND:
@@ -1610,9 +1697,9 @@ void render_one_item(render_item_t *render_item)
                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;
+               x[0] = x[1] = z[1] = z[2] = -1000000000;
+               x[2] = x[3] = z[0] = z[3] = 1000000000;
+               y[0] = y[1] = y[2] = y[3] = -1000;
                /* rotate vertex */
                for (i = 0; i < 4; i++)
                        rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
@@ -1643,7 +1730,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;
                }
@@ -1656,6 +1743,12 @@ void render_one_item(render_item_t *render_item)
                        rc = use_coord("object", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i], fix);
                        if (rc < 0)
                                break;
+                       /* fixed objects are pre-scaled by 16, so we correct this */
+                       if (fix) {
+                               x[i] /= FIX_OBJECT_SCALE;
+                               y[i] /= FIX_OBJECT_SCALE;
+                               z[i] /= FIX_OBJECT_SCALE;
+                       }
                        /* interpolate motion, if object is 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) {
                                for (o = 0; o < interpolation.object_count; o++) {
@@ -1682,7 +1775,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 +1801,24 @@ 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;
+                       /* fixed objects are pre-scaled by 16, so we correct this */
+                       if (fix) {
+                               x[i] /= FIX_OBJECT_SCALE;
+                               y[i] /= FIX_OBJECT_SCALE;
+                               z[i] /= FIX_OBJECT_SCALE;
+                       }
+                       /* 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 +1998,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 +2011,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 +2127,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 dist, size, angle, fabs_angle, crescent;
+               double _sin, _cos;
                int i;
                int rc;
 
@@ -2028,10 +2142,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 */
@@ -2044,14 +2158,23 @@ void render_one_item(render_item_t *render_item)
                rotate_coordinate(roll, pitch, yaw, &sun_x, &sun_y, &sun_z);
                rotate_coordinate(roll, pitch, yaw, &loc_x, &loc_y, &loc_z);
 
+               /* distance to planet */
+               dist = sqrt(loc_x * loc_x + loc_y * loc_y + loc_z * 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 +2186,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]) / dist * 1000000.0;
+                       y[i] = (loc_y + circle_y[i]) / dist * 1000000.0;
+                       z[i] = (loc_z + circle_z[i]) / dist * 1000000.0;
                }
                opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
 
@@ -2086,34 +2238,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]) / dist * 1000000.0;
+                               y[i] = (loc_y + circle_y[i]) / dist * 1000000.0;
+                               z[i] = (loc_z + circle_z[i]) / dist * 1000000.0;
                        }
+                       _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]) / dist * 1000000.0;
+                               y[i] = (loc_y + crescent_y[i]) / dist * 1000000.0;
+                               z[i] = (loc_z + crescent_z[i]) / dist * 1000000.0;
                        }
                } 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]) / dist * 1000000.0;
+                               y[i] = (loc_y + crescent_y[i]) / dist * 1000000.0;
+                               z[i] = (loc_z + crescent_z[i]) / dist * 1000000.0;
                        }
                        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]) / dist * 1000000.0;
+                               y[i] = (loc_y + circle_y[i]) / dist * 1000000.0;
+                               z[i] = (loc_z + circle_z[i]) / dist * 1000000.0;
                        }
                }
                opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
@@ -2128,8 +2275,7 @@ void render_one_item(render_item_t *render_item)
                double view_width, yaw = interpolation.orientation_raw_yaw;
                double pitch = interpolation.orientation_raw_pitch;
                uint32_t table, table_start;
-               double x, y;
-               double z;
+               double x, y, z;
                int i;
                double red, green, blue;
 
@@ -2145,55 +2291,113 @@ void render_one_item(render_item_t *render_item)
                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 = fmod(yaw + 91.0 - (91.0 * (frustum_slope_fov / frustum_slope_64)) + 65536.0, 0x400);
-               yaw *= 2.0;
-               table = mercenary_star_table();
-               table_start = table + m68k_read_memory_16(table);
-               table += m68k_read_memory_16(table + ((uint32_t)yaw & 0x7fe));
-               yaw = yaw / (double)0x800 * 1800.0;
-
-               if (render_item->u.stars.above_zenith)
-                       pitch = 0x200 - pitch;
-               pitch = fmod(pitch + 65536.0, 0x400);
-               pitch -= render_item->u.stars.v_offset;
-               pitch *= 4;
-               pitch = pitch * (double)0x6ccc / 65536.0;
-
-               while (1) {
-                       x = m68k_read_memory_16(table);
-                       if (x >= 1800.0) {
-                               x_offset += 1800.0;
-                               table = table_start;
+               if (!vr) {
+                       /* render legacy stars (as with the original game) */
+
+                       /* 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 = fmod(yaw + 91.0 - (91.0 * (frustum_slope_fov / frustum_slope_64)) + 65536.0, 0x400);
+                       yaw *= 2.0;
+                       table = mercenary_star_table();
+                       table_start = table + m68k_read_memory_16(table);
+                       table += m68k_read_memory_16(table + ((uint32_t)yaw & 0x7fe));
+                       yaw = yaw / (double)0x800 * 1800.0;
+
+                       if (render_item->u.stars.above_zenith)
+                               pitch = 0x200 - pitch;
+                       pitch = fmod(pitch + 65536.0, 0x400);
+                       pitch -= render_item->u.stars.v_offset;
+                       pitch *= 4;
+                       pitch = pitch * (double)0x6ccc / 65536.0;
+
+                       while (1) {
+                               x = m68k_read_memory_16(table);
+                               if (x >= 1800.0) {
+                                       x_offset += 1800.0;
+                                       table = table_start;
+                               }
+                               x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
+                               table += 2;
+                               if (x < 0.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 = ((x - (160.0 / frustum_slope_64 * frustum_slope_fov)) * render_item->u.stars.tilt_value) / 65536.0;
+                               }
+                               y = (double)((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
+                               table += 2;
+                               if (render_item->u.stars.above_zenith) {
+                                       x = (double)(view_width - 1) - x;
+                                       y = -1 - 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 - x, 68.0 - y, z, 0.0);
                        }
-                       x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
-                       table += 2;
-                       if (x < 0.0)
+               } else {
+                       /* render ovr stars, render star table as a sphere */
+
+                       double h, v1, v2;
+                       GET_ORIENTATION;
+                       double inclination = interpolation.planet_inclination, azimuth = interpolation.planet_azimuth;
+
+                       if (render_item->u.stars.above_zenith)
                                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 = ((x - (160.0 / frustum_slope_64 * frustum_slope_fov)) * render_item->u.stars.tilt_value) / 65536.0;
-                       }
-                       y = (double)((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
-                       table += 2;
-                       if (render_item->u.stars.above_zenith) {
-                               x = (double)(view_width - 1) - x;
-                               y = -1 - y + 136;
+
+                       table = mercenary_star_table();
+                       table += m68k_read_memory_16(table);
+
+                       while (1) {
+                               x = m68k_read_memory_16(table);
+                               if (x >= 1800.0)
+                                       break;
+                               table += 2;
+                               y = (double)((m68k_read_memory_16(table)) & 0x1ff) - 108.796875;
+                               table += 2;
+                               /* 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 */
+                               h = (900.0 - x + 160) / 900.0 * M_PI;
+                               v1 = (68.0 - y) / 900.0 * M_PI;
+                               /* wrap star field (is actually 86.2 degrees high) */
+                               if (v1 <= 0.0)
+                                       v2 = v1 + (86.2 / 180.0 * M_PI);
+                               else
+                                       v2 = v1 - (86.2 / 180.0 * M_PI);
+                               if (v1 < 0.934 && v1 > -0.934) {
+                                       /* be sure that v1 will not exceed PI/2 */
+                                       v1 = v1 / cos(v1); /* FIXME: there should be a better way to distribute stars equally */
+                                       x = -sin(h) * cos(v1);
+                                       y = sin(v1);
+                                       z = cos(h) * cos(v1);
+                                       if (motion_new.planet_rotation)
+                                               rotate_coordinate(0.0, inclination, azimuth, &x, &y, &z);
+                                       rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
+                                       opengl_render_point(1000000.0 * x, 1000000.0 * y, 1000000.0 * z, 0.0);
+                               }
+                               if (v2 < 0.934 && v2 > -0.934) {
+                                       /* be sure that v2 will not exceed PI/2 */
+                                       v2 = v2 / cos(v2) /* FIXME: there should be a better way to distribute stars equally */;
+                                       x = -sin(h) * cos(v2);
+                                       y = sin(v2);
+                                       z = cos(h) * cos(v2);
+                                       if (motion_new.planet_rotation)
+                                               rotate_coordinate(0.0, inclination, azimuth, &x, &y, &z);
+                                       rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
+                                       opengl_render_point(1000000.0 * x, 1000000.0 * y, 1000000.0 * z, 0.0);
+                               }
                        }
-                       /* 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 - x, 68.0 - y, z, 0.0);
                }
                break;
        }
@@ -2218,7 +2422,7 @@ void render_one_item(render_item_t *render_item)
                        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);
+                       opengl_render_point((160.0 - (double)render_item->u.interstars.x[i]) * 100, (68.0 - (double)render_item->u.interstars.y[i]) * 100, z * 100, 0.0);
                }
                break;
        }
@@ -2233,7 +2437,7 @@ void render_one_item(render_item_t *render_item)
                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);
+               opengl_render_point(0.0, 0.0, 1000000.0, 0.0);
                break;
        }
        case RENDER_ITEM_SIGHTS:
@@ -2245,19 +2449,19 @@ void render_one_item(render_item_t *render_item)
                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;
+               z[0] = z[1] = z[2] = z[3] = SIGHT_DIST;
 
                /* 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;
+               y[0] = y[3] = -1.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
+               y[1] = y[2] = 1.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
+               x[0] = x[1] = -16.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
+               x[2] = x[3] = -8.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
                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;
+               x[0] = x[1] = 8.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
+               x[2] = x[3] = 16.0 / 160.0 * SIGHT_DIST * frustum_slope_64;
                opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
                break;
        }
@@ -2362,9 +2566,6 @@ static render_item_t *interpolate_door(double inter)
 {
        static render_item_t interpolated;
        render_item_t *old_vertices = render_list_old, *new_vertices = render_list_new;
-       int nomatch_x_count = 0;
-       int nomatch_z_count = 0;
-       int nomatch_x[4], nomatch_z[4];
        int i, ii;
 
        /* find old and new vertices */
@@ -2377,51 +2578,29 @@ static render_item_t *interpolate_door(double inter)
        if (!old_vertices || !new_vertices)
                return NULL;
 
-       /* all verices must match except four */
+       memcpy(&interpolated, new_vertices, sizeof(interpolated));
        ii = MAX_INTERIOR_VERTEX >> 2;
        for (i = 0; i < ii; i++) {
+               /* vertex must exist in both frames */
                if (!old_vertices->u.vertices_interior.set[i] || !new_vertices->u.vertices_interior.set[i])
                        continue;
-               if (old_vertices->u.vertices_interior.x[i] != new_vertices->u.vertices_interior.x[i]) {
-                       if (nomatch_x_count == 4)
-                               return NULL;
-                       nomatch_x[nomatch_x_count++] = i;
-               }
+               /* all verices must not have be too far away */
+               if (fabs(old_vertices->u.vertices_interior.x[i] - new_vertices->u.vertices_interior.x[i]) > 100.0)
+                       return NULL;
+               if (fabs(old_vertices->u.vertices_interior.z[i] - new_vertices->u.vertices_interior.z[i]) > 100.0)
+                       return NULL;
+               /* interpolate */
+               interpolated.u.vertices_interior.x[i] =
+               (double)old_vertices->u.vertices_interior.x[i] * (1.0 - inter) +
+               (double)new_vertices->u.vertices_interior.x[i] * inter;
+               interpolated.u.vertices_interior.z[i] =
+               (double)old_vertices->u.vertices_interior.z[i] * (1.0 - inter) +
+               (double)new_vertices->u.vertices_interior.z[i] * inter;
        }
        for (i = 0; i < 4; i++) {
                if (old_vertices->u.vertices_interior.y[i] != new_vertices->u.vertices_interior.y[i])
                        return NULL;
        }
-       for (i = 0; i < ii; i++) {
-               if (!old_vertices->u.vertices_interior.set[i] || !new_vertices->u.vertices_interior.set[i])
-                       continue;
-               if (old_vertices->u.vertices_interior.z[i] != new_vertices->u.vertices_interior.z[i]) {
-                       if (nomatch_z_count == 4)
-                               return NULL;
-                       nomatch_z[nomatch_z_count++] = i;
-               }
-       }
-
-       /* copy, even if not interpolated */
-       memcpy(&interpolated, new_vertices, sizeof(interpolated));
-
-       /* only four x missmatch */
-       if (nomatch_x_count == 4 || nomatch_x_count == 2) {
-               for (i = 0; i < nomatch_x_count; i++) {
-                       interpolated.u.vertices_interior.x[nomatch_x[i]] =
-                       (double)old_vertices->u.vertices_interior.x[nomatch_x[i]] * (1.0 - inter) +
-                       (double)new_vertices->u.vertices_interior.x[nomatch_x[i]] * inter;
-               }
-       }
-
-       /* only four z missmatch */
-       if (nomatch_z_count == 4 || nomatch_z_count == 2) {
-               for (i = 0; i < nomatch_z_count; i++) {
-                       interpolated.u.vertices_interior.z[nomatch_z[i]] =
-                       (double)old_vertices->u.vertices_interior.z[nomatch_z[i]] * (1.0 - inter) +
-                       (double)new_vertices->u.vertices_interior.z[nomatch_z[i]] * inter;
-               }
-       }
 
        return &interpolated;
 }
@@ -2475,15 +2654,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 +2717,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 +2729,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 +2750,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)