OVR: Add patch to make game render planets behind observer
[mercenary-reloaded.git] / src / mercenary / render.c
index cd93995..8f0b140 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
@@ -532,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) */
@@ -1466,6 +1472,9 @@ void render_capture_event(int event)
        case STOP_AT_EXPLOSION:
                draw_explosion();
                break;
+       case STOP_AT_PATCH_RENDER:
+               mercenary_patch_render();
+               break;
        }
 }
 
@@ -1595,7 +1604,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:
@@ -2090,10 +2099,13 @@ void render_one_item(render_item_t *render_item)
        {
                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;
 
@@ -2118,13 +2130,19 @@ void render_one_item(render_item_t *render_item)
                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) {
@@ -2136,10 +2154,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];
+                       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! */
 
@@ -2159,34 +2206,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];
+                               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! */
@@ -2591,7 +2633,7 @@ static render_item_t *interpolate_planets(double inter)
  * 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
  */
-int 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;
@@ -2654,7 +2696,7 @@ int render_all_items(double inter)
                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;