OVR: Fix planets for VR rendering: Planets are rotated towards observer
authorAndreas Eversberg <jolly@eversberg.eu>
Fri, 13 Apr 2018 16:14:40 +0000 (18:14 +0200)
committerAndreas Eversberg <jolly@eversberg.eu>
Sat, 14 Apr 2018 08:56:18 +0000 (10:56 +0200)
src/mercenary/render.c

index 673d413..f4af63c 100644 (file)
@@ -534,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) */
@@ -2092,10 +2096,13 @@ void render_one_item(render_item_t *render_item, int vr)
        {
                GET_ORIENTATION;
                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 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;
 
@@ -2120,13 +2127,19 @@ void render_one_item(render_item_t *render_item, int vr)
                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) {
@@ -2138,10 +2151,39 @@ void render_one_item(render_item_t *render_item, int vr)
                }
 
                /* 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! */
 
@@ -2161,34 +2203,29 @@ void render_one_item(render_item_t *render_item, int vr)
 
                /* 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! */