OVR: Make interstellar stars appear infinitely away
[mercenary-reloaded.git] / src / mercenary / render.c
index 4acbb78..4e8b98e 100644 (file)
@@ -63,6 +63,7 @@
 #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
@@ -287,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");
@@ -320,7 +321,7 @@ void render_capture_start(double _fov, int _extend_roads, int debug)
        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 = motion_old.planet_rotation;
-       mercenary_get_orientation_planet(&motion_new.planet_inclination, &motion_new.planet_azimuth);
+       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;
@@ -419,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);
@@ -463,12 +464,9 @@ static void store_coord(const char __attribute__((unused)) *what, uint32_t verte
        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] = x;
-       render_item->u.vertices.y[vertex] = y;
-       render_item->u.vertices.z[vertex] = z;
+       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)
@@ -619,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 */
@@ -688,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 */
@@ -716,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) */
@@ -903,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 */
@@ -939,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 */
@@ -983,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 */
@@ -997,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 */
@@ -1188,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 */
@@ -1742,6 +1743,12 @@ void render_one_item(render_item_t *render_item, int vr)
                        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++) {
@@ -1794,6 +1801,12 @@ void render_one_item(render_item_t *render_item, int vr)
                        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++) {
@@ -2120,7 +2133,7 @@ void render_one_item(render_item_t *render_item, int vr)
                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, fabs_angle, crescent;
+               double dist, size, angle, fabs_angle, crescent;
                double _sin, _cos;
                int i;
                int rc;
@@ -2145,6 +2158,9 @@ void render_one_item(render_item_t *render_item, int vr)
                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_h = atan2(sun_x, sun_z);
                angle_loc_h = atan2(loc_x, loc_z);
@@ -2200,9 +2216,9 @@ void render_one_item(render_item_t *render_item, int vr)
                        }
                }
                for (i = 0; i < PLANET_VERTICES; i++) {
-                       x[i] = loc_x + circle_x[i];
-                       y[i] = loc_y + circle_y[i];
-                       z[i] = loc_z + circle_z[i];
+                       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! */
 
@@ -2224,27 +2240,27 @@ void render_one_item(render_item_t *render_item, int vr)
                if (angle > M_PI / 2.0 || (angle < 0.0 && angle > -M_PI / 2.0)) {
                        /* to the right */
                        for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
-                               x[i] = loc_x + circle_x[i];
-                               y[i] = loc_y + circle_y[i];
-                               z[i] = loc_z + circle_z[i];
+                               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 + crescent_x[i];
-                               y[i] = loc_y + crescent_y[i];
-                               z[i] = loc_z + crescent_z[i];
+                               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 {
                        /* to the left */
                        for (i = 0; i < PLANET_VERTICES / 2 + 1; i++) {
-                               x[i] = loc_x + crescent_x[i];
-                               y[i] = loc_y + crescent_y[i];
-                               z[i] = loc_z + crescent_z[i];
+                               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 + circle_x[i];
-                               y[i] = loc_y + circle_y[i];
-                               z[i] = loc_z + circle_z[i];
+                               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! */
@@ -2406,7 +2422,7 @@ void render_one_item(render_item_t *render_item, int vr)
                        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;
        }
@@ -2550,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 */
@@ -2565,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;
 }