Make coordinates of planets and comet's tail interpolate between captures
authorAndreas Eversberg <jolly@eversberg.eu>
Tue, 10 Apr 2018 18:29:23 +0000 (20:29 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 Apr 2018 05:03:46 +0000 (07:03 +0200)
src/mercenary/render.c

index 5ac62a9..621db0d 100644 (file)
@@ -105,7 +105,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 +213,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 +255,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
@@ -319,6 +321,7 @@ void render_capture_start(double _fov, int _extend_roads, int debug)
 
        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 */
@@ -454,7 +457,7 @@ 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;
@@ -465,6 +468,33 @@ 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)) {
@@ -479,7 +509,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;
@@ -825,7 +855,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 +1056,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 */
@@ -1495,6 +1525,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)) {
@@ -1887,7 +1948,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 +1961,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,7 +2077,7 @@ 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 inclination = interpolation.planet_inclination, azimuth = interpolation.planet_azimuth;
                double sun_x, sun_y, sun_z, angle_sun;
                double loc_x, loc_y, loc_z, angle_loc;
                double x[PLANET_VERTICES], y[PLANET_VERTICES], z[PLANET_VERTICES];
@@ -2028,10 +2089,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 */
@@ -2475,6 +2536,44 @@ 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
@@ -2485,6 +2584,7 @@ int render_all_items(double inter)
        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)
@@ -2499,6 +2599,8 @@ int 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 */
@@ -2509,6 +2611,8 @@ int 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);
@@ -2528,6 +2632,9 @@ int render_all_items(double inter)
 
                /* interpolate objects */
                interpolate_objects(inter);
+
+               /* interpolate planets */
+               interpolation.planets = interpolate_planets(inter);
        }
 
        /* return failure, if nothing can be rendered */