OVR: Render stars spherical with VR
authorAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 Apr 2018 17:43:12 +0000 (19:43 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sun, 22 Apr 2018 10:02:45 +0000 (12:02 +0200)
src/mercenary/render.c

index abb9668..b0a35b1 100644 (file)
@@ -2257,8 +2257,7 @@ void render_one_item(render_item_t *render_item, int vr)
                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;
 
@@ -2274,55 +2273,113 @@ void render_one_item(render_item_t *render_item, int vr)
                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;
        }