#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
+#include <string.h>
#include <math.h>
#include <GL/glew.h>
#include "../libsdl/print.h"
//#define DEBUG_COLOR
//#define DEBUG_VERTEX
+#define DEBUG_ITEMS
-#define MAX_VERTEX 0x300
-static int coord_x[MAX_VERTEX >> 2];
-static int coord_y[MAX_VERTEX >> 2];
-static int coord_z[MAX_VERTEX >> 2];
+#define MAX_POLYGON 16 /* number of polygon complexity (vertices) */
+#define MAX_VERTEX 0x100 /* this is the value range, these are 64 vertices */
+#define MAX_INTERIOR_VERTEX 0x400 /* do we need that much? */
+#define MAX_INTERSTARS 80 /* always 80 stars */
+#define PLANET_VERTICES 128
+#define PLANET_ELIPSE 1.17
-#define MAX_INTERIOR_VERTEX 0x400 /* do we need that much? */
-static int interior_coord_x[MAX_INTERIOR_VERTEX >> 2];
-static int interior_coord_y[MAX_INTERIOR_VERTEX >> 2][4]; /* 4 levels (floor; ceiling; window or door top; window bottom) */
-static int interior_coord_z[MAX_INTERIOR_VERTEX >> 2];
static int extend_roads; /* extend roads in its original width, rather than just using a single point */
static double fov;
-static double transparency;
+static double debug_opacity;
static double frustum_slope_64, frustum_slope_fov;
+static double orientation_roll, orientation_pitch, orientation_yaw;
+static uint16_t orientation_raw_yaw;
+static int16_t orientation_raw_pitch;
+static double planet_inclination, planet_azimuth;
+
+enum render_item_type {
+ RENDER_ITEM_VERTICES_0,
+ RENDER_ITEM_VERTICES_1,
+ RENDER_ITEM_VERTICES_2,
+ RENDER_ITEM_VERTICES_INTERIOR,
+ RENDER_ITEM_SKY,
+ RENDER_ITEM_GROUND,
+ RENDER_ITEM_OBJECT_POLYGON,
+ RENDER_ITEM_OBJECT_LINE,
+ RENDER_ITEM_BEACON_POINT,
+ RENDER_ITEM_BUILDING_EXTERIOR_POLYGON,
+ RENDER_ITEM_BUILDING_EXTERIOR_LINE,
+ RENDER_ITEM_BUILDING_INTERIOR_1TO4,
+ RENDER_ITEM_BUILDING_INTERIOR_5TO6,
+ RENDER_ITEM_BUILDING_INTERIOR_WALL,
+ RENDER_ITEM_COMET_POLYGON,
+ RENDER_ITEM_ROAD_LINE,
+ RENDER_ITEM_ROAD_POLYGON,
+ RENDER_ITEM_TAG_LINE,
+ RENDER_ITEM_TAG_POLYGON,
+ RENDER_ITEM_PLANET,
+ RENDER_ITEM_STARS,
+ RENDER_ITEM_INTERSTELLAR_STARS,
+ RENDER_ITEM_INTERSTELLAR_SUN,
+ RENDER_ITEM_ISLAND_POLYGON,
+ RENDER_ITEM_SIGHTS,
+};
+
+struct render_item_vertices {
+ int32_t x[MAX_VERTEX >> 2], y[MAX_VERTEX >> 2], z[MAX_VERTEX >> 2];
+};
+
+struct render_item_vertices_interior {
+ int32_t x[MAX_INTERIOR_VERTEX >> 2], y[4], z[MAX_INTERIOR_VERTEX >> 2];
+};
+
+struct render_item_sky {
+ double red, green, blue;
+};
+
+struct render_item_ground {
+ double red, green, blue;
+};
+
+struct render_item_polygon {
+ double red, green, blue;
+ int vertices;
+ int vertex[MAX_POLYGON];
+};
+
+struct render_item_interior14 {
+ double red, green, blue;
+ int level;
+ int vertex[4];
+};
+
+struct render_item_interior56 {
+ double red, green, blue;
+ int level12;
+ int level34;
+ int vertex14;
+ int vertex23;
+};
+
+struct render_item_line {
+ double red, green, blue;
+ int vertex[2];
+};
+
+struct render_item_point {
+ double red, green, blue;
+ int vertex;
+};
+
+struct render_item_planet {
+ double front_red, front_green, front_blue;
+ double back_red, back_green, back_blue;
+ int vertex;
+ double size;
+};
+
+struct render_item_stars {
+ int16_t v_offset;
+ int tilt;
+ int32_t tilt_value;
+ int above_zenith;
+};
+
+struct render_item_interstars {
+ uint8_t color[MAX_INTERSTARS];
+ int16_t x[MAX_INTERSTARS], y[MAX_INTERSTARS];
+ int count;
+};
+
+typedef struct render_item {
+ struct render_item *next;
+ enum render_item_type type;
+ union {
+ struct render_item_vertices vertices;
+ struct render_item_vertices_interior vertices_interior;
+ struct render_item_sky sky;
+ struct render_item_ground ground;
+ struct render_item_polygon polygon;
+ struct render_item_line line;
+ struct render_item_point point;
+ struct render_item_interior14 interior14;
+ struct render_item_interior56 interior56;
+ struct render_item_planet planet;
+ struct render_item_stars stars;
+ struct render_item_interstars interstars;
+ } u;
+} render_item_t;
+
+static render_item_t *render_list_start = NULL, **render_list_end = &render_list_start;
+static render_item_t *render_item;
+static render_item_t *render_item_vertices_0, *render_item_vertices_1, *render_item_vertices_2;
+static render_item_t *render_item_vertices_interior;
+
+void render_item_add(enum render_item_type type)
+{
+ render_item = calloc(1, sizeof(render_item_t));
+ if (!render_item) {
+ print_error("No memory, must abort!\n");
+ abort();
+ }
+ render_item->type = type;
+ *render_list_end = render_item;
+ render_list_end = &render_item->next;
+}
/* rendering starts, initialize variables */
-void render_start(double _fov, int _extend_roads, int debug)
+void render_capture_start(double _fov, int _extend_roads, int debug)
{
#if defined(DEBUG_COLOR) || defined(DEBUG_VERTEX)
printf("start rendering a new frame...\n");
#endif
+ /* flush render list */
+ while (render_list_start) {
+ render_item = render_list_start;
+ render_list_start = render_list_start->next;
+ free(render_item);
+ }
+ render_list_end = &render_list_start;
+ render_item = NULL;
+
+ /* set rendering options */
fov = _fov;
extend_roads = _extend_roads;
-
- transparency = (debug) ? 0.5 : 0.0;
- opengl_transparency_set(transparency);
+ /* set some transpareny, if debugging is enabled */
+ debug_opacity = (debug) ? 0.5 : 1.0;
/* calculate slope of 64 degree frustum and current FOV's frustum */
frustum_slope_64 = tan(64.0 / 2.0 / 180.0 * M_PI);
frustum_slope_fov = tan(fov / 2.0 / 180.0 * M_PI);
+
+ /* get orientation */
+ mercenary_get_orientation(&orientation_roll, &orientation_pitch, &orientation_yaw);
+ mercenary_get_orientation_raw(&orientation_raw_pitch, &orientation_raw_yaw);
+ mercenary_get_orientation_planet(&planet_inclination, &planet_azimuth);
+
+ render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
+ render_item_vertices_interior = NULL;
}
-void render_finish(void)
+void render_capture_stop(void)
{
- opengl_transparency_set(0.0);
}
-static void gamecolor2gl_index(uint16_t index)
+static void gamecolor2gl_index(double *red, double *green, double *blue, uint16_t index)
{
uint32_t palette;
uint16_t color;
print_error("Use of color index from current palette, but index is not defined as being set!\n");
#endif
}
- opengl_render_color(
- (double)((color >> 8) & 0xf) / 15.0,
- (double)((color >> 4) & 0xf) / 15.0,
- (double)(color & 0xf) / 15.0
- );
+ *red = (double)((color >> 8) & 0xf) / 15.0;
+ *green = (double)((color >> 4) & 0xf) / 15.0;
+ *blue = (double)(color & 0xf) / 15.0;
}
-static void gamecolor2gl(uint16_t color)
+static void gamecolor2gl(double *red, double *green, double *blue, uint16_t color)
{
uint16_t index;
uint32_t palette;
printf("using given color, color is now 0x%04x\n", color);
#endif
} else if ((color & 0xff) < 0x80) {
- gamecolor2gl_index(color & 0xf);
+ gamecolor2gl_index(red, green, blue, color & 0xf);
return;
} else {
/* use given index from pre-defined palette */
}
goto again;
}
- opengl_render_color(
- (double)((color >> 8) & 0xf) / 15.0,
- (double)((color >> 4) & 0xf) / 15.0,
- (double)(color & 0xf) / 15.0
- );
+ *red = (double)((color >> 8) & 0xf) / 15.0;
+ *green = (double)((color >> 4) & 0xf) / 15.0;
+ *blue = (double)(color & 0xf) / 15.0;
}
-static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, double x, double y, double z)
+static void store_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z)
{
if ((vertex & 3)) {
print_error("Vertex %d is not a multiple of four!\n", vertex);
return;
}
- if (vertex >= MAX_VERTEX) {
- print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+ /* create new vertices item, if there was no vertex before, or if the vertex has different offet */
+ if (vertex < 0x100) {
+ 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;
+ }
+ } else
+ if (vertex < 0x200) {
+ if (!render_item || render_item->type != RENDER_ITEM_VERTICES_1) {
+ render_item_add(RENDER_ITEM_VERTICES_1);
+ /* copy vertices that have been captured already */
+ if (render_item_vertices_1)
+ memcpy(&render_item->u.vertices, &render_item_vertices_1->u.vertices, sizeof(render_item->u.vertices));
+ render_item_vertices_1 = render_item;
+ }
+ vertex -= 0x100;
+ } else
+ if (vertex < 0x300) {
+ if (!render_item || render_item->type != RENDER_ITEM_VERTICES_2) {
+ render_item_add(RENDER_ITEM_VERTICES_2);
+ /* copy vertices that have been captured already */
+ if (render_item_vertices_2)
+ memcpy(&render_item->u.vertices, &render_item_vertices_2->u.vertices, sizeof(render_item->u.vertices));
+ render_item_vertices_2 = render_item;
+ }
+ vertex -= 0x200;
+ } else {
+ print_error("Vertex %d exceeds maximum vertex number, please fix!\n", vertex);
return;
}
vertex >>= 2;
#ifdef DEBUG_VERTEX
printf("storing %s coordinates: vertex=%d, x=%.0f, y=%.0f, z=%.0f\n", what, vertex, x, y, z);
#endif
- coord_x[vertex] = x;
- coord_y[vertex] = y;
- coord_z[vertex] = z;
+ render_item->u.vertices.x[vertex] = x;
+ render_item->u.vertices.y[vertex] = y;
+ render_item->u.vertices.z[vertex] = z;
}
-static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z)
-{
- if ((vertex & 3)) {
- print_error("Vertex %d is not a multiple of four!\n", vertex);
- return -1;
- }
- if (vertex >= MAX_VERTEX) {
- print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
- return -1;
- }
- vertex >>= 2;
- *x = coord_x[vertex];
- *y = coord_y[vertex];
- *z = coord_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 void store_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, double x, double y1, double y2, double y3, double y4, double 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)) {
print_error("Vertex is not a multiple of four!\n");
print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_INTERIOR_VERTEX);
return;
}
+ if (!render_item || render_item->type != RENDER_ITEM_VERTICES_INTERIOR)
+ 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);
#endif
- interior_coord_x[vertex] = x;
- interior_coord_y[vertex][0] = y1;
- interior_coord_y[vertex][1] = y2;
- interior_coord_y[vertex][2] = y3;
- interior_coord_y[vertex][3] = y4;
- interior_coord_z[vertex] = z;
-}
-
-static int use_interior_coord(const char __attribute__((unused)) *what, uint32_t vertex, int level, double *x, double *y, double *z)
-{
- if ((vertex & 3)) {
- print_error("Vertex is not a multiple of four!\n");
- return -1;
- }
- if (vertex >= MAX_VERTEX) {
- print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
- return -1;
- }
- if (level < 1 || level > 4) {
- print_error("Level %d is out of range (1..4)!\n", level);
- return -1;
- }
- vertex >>= 2;
- *x = interior_coord_x[vertex];
- *y = interior_coord_y[vertex][level - 1];
- *z = interior_coord_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;
+ render_item->u.vertices_interior.x[vertex] = x;
+ render_item->u.vertices_interior.y[0] = y1;
+ render_item->u.vertices_interior.y[1] = y2;
+ render_item->u.vertices_interior.y[2] = y3;
+ render_item->u.vertices_interior.y[3] = y4;
+ render_item->u.vertices_interior.z[vertex] = z;
}
static int planet_rotation = 0;
*y = out_y;
}
-/* coordinates ready for an object */
-static void coord_object(void)
-{
- int32_t x, y, z;
-
- x = (int16_t)REG_D[3];
- x += (int32_t)REG_A[1];
- y = (int16_t)REG_D[4];
- y += (int32_t)REG_A[2];
- z = (int16_t)REG_D[5];
- z += (int32_t)REG_A[3];
- store_coord("object", REG_A[0], (double)x, (double)y, (double)z);
-}
-
static int ground_index;
-/* clear screen (sky / universe) */
+/* clear screen color (sky / universe) */
static void clear_screen(int index)
{
- double x[4], y[4], z[4];
-
#ifdef DEBUG_VERTEX
printf("clear screen:\n");
#endif
- opengl_transparency_set(0.0);
-
- /* create plane to fill view */
- x[0] = x[1] = y[1] = y[2] = -1000000;
- x[2] = x[3] = y[0] = y[3] = 1000000;
- z[0] = z[1] = z[2] = z[3] = 10;
- gamecolor2gl_index(8);
- opengl_render_polygon(x, y, z, 4, 0); /* no culling, because background is always visible! */
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_SKY);
- opengl_transparency_set(transparency);
+ /* set color */
+ gamecolor2gl_index(&render_item->u.ground.red, &render_item->u.ground.green, &render_item->u.ground.blue, 8);
/* store for later use after planets have been rendered */
ground_index = index;
}
-/* draw ground */
+/* ground color */
static void draw_ground(void)
{
- double roll, pitch, yaw, x[4], y[4], z[4];
-
/* no ground in space :) */
if (ground_index < 0)
return;
#ifdef DEBUG_VERTEX
- printf("draw ground plane:\n");
+ printf("add ground plane:\n");
#endif
- opengl_transparency_set(0.0);
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
- yaw = 0.0; /* no need to rotate x-z plane, we don't want look at a corner of the 'ground-square' */
-
- /* create huge square */
- x[0] = x[1] = z[1] = z[2] = -1000000;
- x[2] = x[3] = z[0] = z[3] = 1000000;
- y[0] = y[1] = y[2] = y[3] = -10;
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_GROUND);
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[0], &y[0], &z[0]);
- rotate_coordinate(roll, pitch, yaw, &x[1], &y[1], &z[1]);
- rotate_coordinate(roll, pitch, yaw, &x[2], &y[2], &z[2]);
- rotate_coordinate(roll, pitch, yaw, &x[3], &y[3], &z[3]);
+ /* set color */
+ gamecolor2gl_index(&render_item->u.ground.red, &render_item->u.ground.green, &render_item->u.ground.blue, ground_index);
+}
- gamecolor2gl_index(ground_index);
- opengl_render_polygon(x, y, z, 4, 0); /* no culling, because ground is always visible! */
+/* coordinates ready for an object */
+static void coord_object(void)
+{
+ int32_t x, y, z;
- opengl_transparency_set(transparency);
+ x = (int16_t)REG_D[3];
+ x += (int32_t)REG_A[1];
+ y = (int16_t)REG_D[4];
+ 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);
}
-/* render polygon of object */
+/* polygon of object */
static void poly_object(int mercenary)
{
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw object's polygon:\n");
+ printf("add object's polygon:\n");
#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_OBJECT_POLYGON);
+
+ /* set color */
if (mercenary == 3)
- gamecolor2gl(REG_D[0]);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, REG_D[0]);
else {
uint16_t color;
color = m68k_read_memory_8(vertex_address++) << 8;
color |= m68k_read_memory_8(vertex_address++);
- gamecolor2gl(color);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
}
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
-
/* the vertex list is zero-terminated */
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_POLYGON; i++) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
- /* get vertex */
- rc = use_coord("object", vertex, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ render_item->u.polygon.vertex[i] = vertex;
}
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+ render_item->u.polygon.vertices = i;
}
-/* render line of object */
+/* line of object */
static void line_object(void)
{
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
- double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw object's line:\n");
+ printf("add object's line:\n");
#endif
- gamecolor2gl(REG_D[0]);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_OBJECT_LINE);
+
+ /* set color */
+ gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
+ /* two vertices */
vertex = m68k_read_memory_8(vertex_address++);
- /* get vertex */
- rc = use_coord("object", vertex, &x1, &y1, &z1);
- if (rc < 0)
- return;
+ render_item->u.line.vertex[0] = vertex;
vertex = m68k_read_memory_8(vertex_address++);
- /* get vertex */
- rc = use_coord("object", vertex, &x2, &y2, &z2);
- if (rc < 0)
- return;
- /* rotate vertices */
- rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
- rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
- /* transfer line to OpenGL */
- opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+ render_item->u.line.vertex[1] = vertex;
}
/* coordinates ready for a beacon */
int32_t x, y, z;
/* only 28 bits seem to be a correct signed int value */
- x = (double)((int32_t)REG_D[3] << 4) / 16.0;
- y = (double)((int32_t)REG_D[4] << 4) / 16.0;
- z = (double)((int32_t)REG_D[5] << 4) / 16.0;
- store_coord("beacon", 0, (double)x, (double)y, (double)z);
+ 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);
}
-/* render point of beacon */
+/* point of beacon */
static void point_beacon(void)
{
- double roll, pitch, yaw, x, y, z;
- int rc;
-
#ifdef DEBUG_VERTEX
- printf("draw beacon's point:\n");
+ printf("add beacon's point:\n");
#endif
- gamecolor2gl(REG_D[2]);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BEACON_POINT);
- /* get vertex */
- rc = use_coord("beacon", 0, &x, &y, &z);
- if (rc < 0)
- return;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
- /* transfer point to OpenGL */
- opengl_render_point(x, y, z, 0.0);
+ /* set color */
+ gamecolor2gl(&render_item->u.point.red, &render_item->u.point.green, &render_item->u.point.blue, REG_D[2]);
+
+ /* one vertex */
+ render_item->u.point.vertex = 0;
}
/* coordinates ready for a building (exterior) */
static void coord_building_exterior(void)
{
- int x, y, z;
+ int32_t x, y, z;
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], (double)x, (double)y, (double)z);
+ store_coord("building exterior", REG_A[0], x, y, z);
}
-/* render polygon of building (exterior) */
+/* polygon of building (exterior) */
static void poly_building_exterior(void)
{
+ uint16_t color;
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw building's polygon:\n");
+ printf("add building's polygon:\n");
#endif
- uint16_t color;
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BUILDING_EXTERIOR_POLYGON);
+
+ /* set color */
color = m68k_read_memory_8(vertex_address++) << 8;
color |= m68k_read_memory_8(vertex_address++);
- gamecolor2gl(color);
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
/* the vertex list is zero-terminated */
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_POLYGON; i++) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
- vertex |= 0x100;
- /* get vertex */
- rc = use_coord("building exterior", vertex, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ render_item->u.polygon.vertex[i] = vertex | 0x100;
}
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+ render_item->u.polygon.vertices = i;
}
-/* render line of building (exterior) */
+/* line of building (exterior) */
static void line_building_exterior(void)
{
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
- double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw building's line:\n");
+ printf("add building's line:\n");
#endif
- gamecolor2gl(REG_D[0]);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BUILDING_EXTERIOR_LINE);
+ /* set color */
+ gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
+
+ /* two vertices */
vertex = m68k_read_memory_8(vertex_address++);
- vertex |= 0x100;
- /* get vertex */
- rc = use_coord("building line", vertex, &x1, &y1, &z1);
- if (rc < 0)
- return;
+ render_item->u.line.vertex[0] = vertex | 0x100;
vertex = m68k_read_memory_8(vertex_address++);
- vertex |= 0x100;
- /* get vertex */
- rc = use_coord("building line", vertex, &x2, &y2, &z2);
- if (rc < 0)
- return;
- /* rotate vertices */
- rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
- rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
- /* transfer line to OpenGL */
- opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+ render_item->u.line.vertex[1] = vertex | 0x100;
}
static int interior_level12 = 0;
int32_t height1, height2, height3, height4;
mercenary_coord_building_interior(&east, &height1, &height2, &height3, &height4, &north);
- store_interior_coord("interior", REG_A[0], (double)east, (double)height1, (double)height2, (double)height3, (double)height4, (double)north);
+ store_interior_coord("interior", REG_A[0], east, height1, height2, height3, height4, north);
}
-/* render polygon of building (interior) */
+/* polygon of building (interior) */
static void poly_building_interior1to4(int level)
{
uint16_t color;
uint32_t vertex;
int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw roof/floor's polygon at level %d:\n", level);
+ printf("add roof/floor's polygon at level %d:\n", level);
#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BUILDING_INTERIOR_1TO4);
+
+ /* set color */
color = m68k_read_memory_8(REG_A[0]) << 8;
color |= m68k_read_memory_8(REG_A[0] + 1);
- gamecolor2gl(color);
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ gamecolor2gl(&render_item->u.interior14.red, &render_item->u.interior14.green, &render_item->u.interior14.blue, color);
- /* the vertex list is zero-terminated */
+ /* four vertices, one level */
for (i = 0; i < 4; i++) {
vertex = REG_A[(2 + i)];
- /* get vertex */
- rc = use_interior_coord("interior", vertex, level, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ render_item->u.interior14.vertex[i] = vertex;
}
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+ render_item->u.interior14.level = level;
}
-/* render polygon of building (interior) */
+/* polygon of building (interior) */
static void poly_building_interior5to6(int level12, int level34)
{
uint16_t color;
- uint32_t vertex;
- int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw polygon above/below window/door at level %d/%d:\n", level12, level34);
+ printf("add polygon above/below window/door at level %d/%d:\n", level12, level34);
#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BUILDING_INTERIOR_5TO6);
+
+ /* set color */
color = m68k_read_memory_8(REG_A[0]) << 8;
color |= m68k_read_memory_8(REG_A[0] + 1);
- gamecolor2gl(color);
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ gamecolor2gl(&render_item->u.interior56.red, &render_item->u.interior56.green, &render_item->u.interior56.blue, color);
- /* the vertex list is zero-terminated */
- for (i = 0; i < 4; i++) {
- vertex = (i == 0 || i == 3) ? REG_A[2] : REG_A[3];
- /* get vertex */
- rc = use_interior_coord("interior", vertex, (i == 0 || i == 1) ? level12 : level34, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
- }
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+ /* two vertices, two levels */
+ render_item->u.interior56.vertex14 = REG_A[2];
+ render_item->u.interior56.vertex23 = REG_A[3];
+ render_item->u.interior56.level12 = level12;
+ render_item->u.interior56.level34 = level34;
}
+/* wall part of a building */
static void wall_building(void)
{
- double roll, pitch, yaw, x[4], y[4], z[4];
- double bottom1_x, bottom1_y, bottom1_z;
- double bottom2_x, bottom2_y, bottom2_z;
- double top1_x, top1_y, top1_z;
- double top2_x, top2_y, top2_z;
- int rc;
-
#ifdef DEBUG_VERTEX
- printf("draw wall:\n");
+ printf("add wall:\n");
#endif
- gamecolor2gl(REG_D[3]);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_BUILDING_INTERIOR_WALL);
- /* get bottom coordinate */
- rc = use_interior_coord("interior", REG_A[1], 1, &bottom1_x, &bottom1_y, &bottom1_z);
- if (rc < 0)
- return;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &bottom1_x, &bottom1_y, &bottom1_z);
- /* get top coordinate according to bit 12 in D3 */
- rc = use_interior_coord("interior", REG_A[1], (REG_D[3] & (1 << 12)) ? 3 : 2, &top1_x, &top1_y, &top1_z);
- if (rc < 0)
- return;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &top1_x, &top1_y, &top1_z);
- /* if wall is not just a strait line */
- if (REG_A[1] != REG_A[2]) {
- /* get bottom coordinate */
- rc = use_interior_coord("interior", REG_A[2], 1, &bottom2_x, &bottom2_y, &bottom2_z);
- if (rc < 0)
- return;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &bottom2_x, &bottom2_y, &bottom2_z);
- /* get top coordinate according to bit 12 in D3 */
- rc = use_interior_coord("interior", REG_A[2], (REG_D[3] & (1 << 12)) ? 3 : 2, &top2_x, &top2_y, &top2_z);
- if (rc < 0)
- return;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &top2_x, &top2_y, &top2_z);
- /* transfer vertex to OpenGL */
- x[0] = bottom1_x; y[0] = bottom1_y; z[0] = bottom1_z;
- x[1] = top1_x; y[1] = top1_y; z[1] = top1_z;
- x[2] = top2_x; y[2] = top2_y; z[2] = top2_z;
- x[3] = bottom2_x; y[3] = bottom2_y; z[3] = bottom2_z;
- /* render polygon to OpenGL */
- opengl_render_polygon_and_line(x, y, z, 4); /* no culling, because walls are always visible! */
- } else {
- /* transfer vertex to OpenGL */
- opengl_render_line(bottom1_x, bottom1_y, bottom1_z, top1_x, top1_y, top1_z, 0.0);
- }
+ /* set color */
+ gamecolor2gl(&render_item->u.interior56.red, &render_item->u.interior56.green, &render_item->u.interior56.blue, REG_D[3]);
+
+ /* two vertices, two levels */
+ render_item->u.interior56.vertex14 = REG_A[1];
+ render_item->u.interior56.vertex23 = REG_A[2];
+ /* get top level according to bit 12 in D3 */
+ render_item->u.interior56.level12 = (REG_D[3] & (1 << 12)) ? 3 : 2;
+ render_item->u.interior56.level34 = 1;
}
/* coordinates ready for comet tail */
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], (double)x, (double)y, (double)z);
+ store_coord("comet tail", REG_A[0], x, y, z);
}
-/* render polygon of comet tail */
+/* polygon of comet tail */
static void poly_comet(void)
{
uint16_t color;
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
int i;
- double roll, pitch, yaw;
- double inclination, rotation;
- double x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw comet's polygon:\n");
+ printf("add comet's polygon:\n");
#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_COMET_POLYGON);
+
+ /* set color */
color = m68k_read_memory_8(vertex_address++) << 8;
color |= m68k_read_memory_8(vertex_address++);
- gamecolor2gl(color);
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
- if (planet_rotation)
- mercenary_get_orientation_planet(&inclination, &rotation);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
/* the vertex list is zero-terminated */
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_POLYGON; i++) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
- /* get vertex */
- rc = use_coord("comet tail", vertex, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- if (planet_rotation)
- rotate_coordinate(0.0, inclination, rotation, &x[i], &y[i], &z[i]);
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ render_item->u.polygon.vertex[i] = vertex;
}
- /* render polygon to OpenGL */
- opengl_render_polygon_and_line(x, y, z, i); /* no culling, because we render only two (out of four) planes! */
+ render_item->u.polygon.vertices = i;
}
/* coordinates ready for lines of a road / ground surface */
mercenary_get_height(&y);
y = -y;
z = REG_D[5];
- store_coord("road", REG_A[0], (double)x, (double)y, (double)z);
+ store_coord("road", REG_A[0], x, y, z);
}
-/* render line of road */
+/* line of road */
static void line_road(void)
{
uint32_t vertex;
- double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw road's line:\n");
+ printf("add road's line:\n");
#endif
- gamecolor2gl_index(mercenary_street_color_index());
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_ROAD_LINE);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* set color */
+ gamecolor2gl_index(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, mercenary_street_color_index());
+ /* two vertices */
vertex = REG_A[1];
- /* get vertex */
- rc = use_coord("road", vertex, &x1, &y1, &z1);
- if (rc < 0)
- return;
+ render_item->u.line.vertex[0] = vertex;
vertex = REG_A[2];
- /* get vertex */
- rc = use_coord("road", vertex, &x2, &y2, &z2);
- if (rc < 0)
- return;
- /* rotate vertices */
- rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
- rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
- /* transfer line to OpenGL */
- opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+ render_item->u.line.vertex[1] = vertex;
}
/* coordinates ready for polygons of a road / ground surface */
y = -y;
z = m68k_read_memory_32(576 + REG_A[0]);
z -= REG_A[3];
- store_coord("road/place", REG_A[0], (double)x, (double)y, (double)z);
+ store_coord("road/place", REG_A[0], x, y, z);
}
-/* render polygon of road */
+/* polygon of road */
static void poly_road()
{
uint16_t color;
uint32_t vertex_address = REG_A[0];
- uint32_t vertex, vertex_prev, vertex_next;
- int i, v;
- double roll, pitch, yaw, x[16], y[16], z[16];
- double x_current, y_current, z_current;
- double x_prev, y_prev, z_prev;
- double x_next, y_next, z_next;
- uint32_t vertices[16];
- int vertices_num;
- int rc;
+ uint32_t vertex;
+ int i;
#ifdef DEBUG_VERTEX
- printf("draw road/place's polygon:\n");
+ printf("add road/place's polygon:\n");
#endif
- color = m68k_read_memory_8(vertex_address++) << 8;
- color |= m68k_read_memory_8(vertex_address++);
- gamecolor2gl(color);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_ROAD_POLYGON);
+ /* set color */
+ color = m68k_read_memory_8(vertex_address++) << 8;
+ color |= m68k_read_memory_8(vertex_address++);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
- /* count the vertex list, it is zero-terminated */
- vertices_num = 0;
- for (i = 0; i < 16; i++) {
+ /* the vertex list is zero-terminated */
+ for (i = 0; i < MAX_POLYGON; i++) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
- vertices[i] = vertex;
- vertices_num++;
+ render_item->u.polygon.vertex[i] = vertex;
}
-
- /* the vertex list is zero-terminated */
- i = 0;
- for (v = 0; v < vertices_num; v++) {
- vertex = vertices[v];
- rc = use_coord("road/place", vertex, &x_current, &y_current, &z_current);
- if (rc < 0)
- break;
- /* check for road extension, so we extend the road to the given end point */
- if (extend_roads && vertex >= 0xf0) {
- /* previous vertex */
- vertex_prev = vertices[(v + vertices_num - 1) % vertices_num];
- rc = use_coord("road/place", vertex_prev, &x_prev, &y_prev, &z_prev);
- if (rc < 0)
- break;
- /* next vertex */
- vertex_next = vertices[(v + 1) % vertices_num];
- rc = use_coord("road/place", vertex_next, &x_next, &y_next, &z_next);
- if (rc < 0)
- break;
- /* extend vertices to end point position
- * change x or z coordinate, whatever is greater
- */
- if (fabs(x_prev - x_current) > fabs(z_prev - z_current))
- x_prev = x_next = x_current;
- else
- z_prev = z_next = z_current;
- /* store vertices */
- x[i] = x_prev;
- y[i] = y_prev;
- z[i] = z_prev;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
- if (i++ == 16)
- break;
- x[i] = x_next;
- y[i] = y_next;
- z[i] = z_next;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
- if (i++ == 16)
- break;
- continue;
- } else {
- /* no extension, just keep the current point as is */
- x[i] = x_current;
- y[i] = y_current;
- z[i] = z_current;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
- if (i++ == 16)
- break;
- }
- }
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 0); /* no culling, because polygons lay on the gound and are always visible! */
+ render_item->u.polygon.vertices = i;
}
/* coordinates ready for tags */
y += (int32_t)REG_A[2];
z = (int16_t)REG_D[5];
z += (int32_t)REG_A[3];
- store_coord("tags", REG_A[0], (double)x, (double)y, (double)z);
+ store_coord("tags", REG_A[0], x, y, z);
}
/* coordinates ready for large tags */
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], (double)x, (double)y, (double)z);
+ store_coord("large tags", REG_A[0], x, y, z);
}
-/* render line of tag */
+/* line of tag */
static void line_tags(int last_color)
{
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
- double roll, pitch, yaw, x1, y1, z1, x2, y2, z2;
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw tag's line:\n");
+ printf("add tag's line:\n");
#endif
- if (!last_color) {
- gamecolor2gl(REG_D[0]);
- } else {
- gamecolor2gl_index(mercenary_line_tags_index());
- }
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_TAG_LINE);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* set color */
+ if (!last_color)
+ gamecolor2gl(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, REG_D[0]);
+ else
+ gamecolor2gl_index(&render_item->u.line.red, &render_item->u.line.green, &render_item->u.line.blue, mercenary_line_tags_index());
+ /* two vertices */
vertex = m68k_read_memory_8(vertex_address++);
- vertex |= 0x200;
- /* get vertex */
- rc = use_coord("tag", vertex, &x1, &y1, &z1);
- if (rc < 0)
- return;
+ render_item->u.line.vertex[0] = vertex | 0x200;
vertex = m68k_read_memory_8(vertex_address++);
- vertex |= 0x200;
- /* get vertex */
- rc = use_coord("tag", vertex, &x2, &y2, &z2);
- if (rc < 0)
- return;
- /* rotate vertices */
- rotate_coordinate(roll, pitch, yaw, &x1, &y1, &z1);
- rotate_coordinate(roll, pitch, yaw, &x2, &y2, &z2);
- /* transfer line to OpenGL */
- opengl_render_line(x1, y1, z1, x2, y2, z2, 0.0);
+ render_item->u.line.vertex[1] = vertex | 0x200;
}
-/* render polygon of tags */
+/* polygon of tags */
static void poly_tags(int last_color)
{
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw tag's polygon:\n");
+ printf("add tag's polygon:\n");
#endif
- if (!last_color) {
- gamecolor2gl(REG_D[0]);
- } else {
- gamecolor2gl(mercenary_poly_tags_color());
- }
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_TAG_POLYGON);
+ /* set color */
+ if (!last_color)
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, REG_D[0]);
+ else
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, mercenary_poly_tags_color());
/* the vertex list is zero-terminated */
- for (i = 0; i < 16; i++) {
+ for (i = 0; i < MAX_POLYGON; i++) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
- vertex |= 0x200;
- /* get vertex */
- rc = use_coord("tag", vertex, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ render_item->u.polygon.vertex[i] = vertex | 0x200;
}
- /* render polygon to OpenGL */
- opengl_render_polygon(x, y, z, i, 1); /* back face culling */
+ render_item->u.polygon.vertices = i;
}
/* coordinates ready for planet */
x = (int32_t)REG_D[3];
y = (int32_t)REG_D[4];
z = (int32_t)REG_D[5];
- store_coord("planet", REG_A[0], (double)x, (double)y, (double)z);
+ store_coord("planet", REG_A[0], x, y, z);
}
-#define PLANET_VERTICES 128
-#define PLANET_ELIPSE 1.17
-
-/* render planet */
+/* planet */
static void draw_planet(int comet)
{
- uint32_t color = REG_D[0];
- uint32_t vertex = REG_A[0];
+ uint32_t vertex;
uint32_t scale_index;
- int i;
- double scale1, scale2, size, angle;
- double roll, pitch, yaw;
- double inclination, rotation;
- 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];
- int rc;
+ double scale1, scale2;
+
+ vertex = REG_A[0];
/* fixing (not noticable) bug in game: don't render comet twice */
if (!comet && vertex == 116)
return;
- /* use background color for dark side */
- color |= (mercenary_background_index() << 16) | 0x80000000; /* shifted by 2 */
-
- /* make comet black on front side and bright on back */
- if (comet)
- color = 0x07770000;
-
#ifdef DEBUG_VERTEX
- printf("draw planet/comet/sun: vertex=%d color=%08x\n", vertex, color);
+ printf("add planet/comet/sun: vertex=%d color=%08x\n", vertex, color);
#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_PLANET);
+
+ /* set color */
+ if (comet) {
+ /* make comet black on front side and bright on back */
+ gamecolor2gl(&render_item->u.planet.front_red, &render_item->u.planet.front_green, &render_item->u.planet.front_blue, 0x000);
+ gamecolor2gl(&render_item->u.planet.back_red, &render_item->u.planet.back_green, &render_item->u.planet.back_blue, 0x777);
+
+ } else {
+ gamecolor2gl(&render_item->u.planet.front_red, &render_item->u.planet.front_green, &render_item->u.planet.front_blue, REG_D[0]);
+ /* use background color for dark side */
+ gamecolor2gl(&render_item->u.planet.back_red, &render_item->u.planet.back_green, &render_item->u.planet.back_blue, mercenary_background_index() | 0x8000);
+ }
+
+ /* set vertex */
+ render_item->u.planet.vertex = vertex;
+
/* I REVERSED THE F*CKING PLANET SIZE, took me half a day!
* the long word 21584(A0) contains two scales
* the lower word contains the scale between 4096 .. 8191, this is 1.0 .. 2.0
scale_index = mercenary_planet_scale_index();
scale1 = (double)(m68k_read_memory_16(scale_index + 2 + vertex) & 0x1fff) / 8192.0;
scale2 = (double)(1 << (uint16_t)m68k_read_memory_16(scale_index + vertex));
- size = scale1 * scale2 / 128.0;
-
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
- if (planet_rotation)
- mercenary_get_orientation_planet(&inclination, &rotation);
-
- /* get location */
- rc = use_coord("planet(sun)", 0, &sun_x, &sun_y, &sun_z);
- if (rc < 0)
- return;
- rc = use_coord("planet", vertex, &loc_x, &loc_y, &loc_z);
- if (rc < 0)
- return;
- /* rotate vertex */
- if (planet_rotation) {
- rotate_coordinate(0.0, inclination, rotation, &sun_x, &sun_y, &sun_z);
- rotate_coordinate(0.0, inclination, rotation, &loc_x, &loc_y, &loc_z);
- }
- rotate_coordinate(roll, pitch, yaw, &sun_x, &sun_y, &sun_z);
- 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;
- if (angle > M_PI)
- angle -= 2.0 * M_PI;
- if (angle < -M_PI)
- angle += 2.0 * M_PI;
-
- /* on which side are we (sun is always bright, vertex == 0) */
- if ((angle < M_PI / 2.0 && angle > -M_PI / 2.0) || vertex == 0) {
- /* set bright side */
- gamecolor2gl(color);
- } else {
- /* set dark side */
- gamecolor2gl(color >> 16);
- }
-
- /* create and render cicle */
- 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;
- }
- opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
-
- if (vertex == 0) {
- /* sun has no crescent */
- return;
- }
-
- /* on which side are we */
- if (angle < M_PI / 2.0 && angle > -M_PI / 2.0) {
- /* set dark side */
- gamecolor2gl(color >> 16);
- } else {
- /* set bright side */
- gamecolor2gl(color);
- }
-
- /* 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;
- }
- 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;
- }
- } 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;
- }
- 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;
- }
- }
- opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
- opengl_render_point(loc_x, loc_y, loc_z, 0.0); /* planet is visible at any distance - at least as a point */
+ render_item->u.planet.size = scale1 * scale2 / 128.0;
}
-/* draw stars */
+/* stars */
static void draw_stars(int16_t v_offset, int tilt, int above_zenith)
{
- int32_t tilt_value;
- int16_t tilt_offset = 0;
- int x_offset = 0;
- uint16_t color[16];
- uint16_t view_width, yaw;
- int16_t pitch;
- uint32_t table, table_start;
- int16_t x, y;
- double z;
- int i;
-
#ifdef DEBUG_VERTEX
- printf("draw stars\n");
+ printf("add stars\n");
#endif
- /* use default fov of 64 to calculate z distance */
- z = 160.0 / frustum_slope_64;
- view_width = (int)(320.0 / frustum_slope_64 * frustum_slope_fov);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_STARS);
- /* get palette */
- for (i = 0; i < 16; i++)
- color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+ /* vertical offset */
+ render_item->u.stars.v_offset = v_offset;
/* if we fly over the planet, we have tilt, so we get the calculated tilt value from game */
+ render_item->u.stars.tilt = tilt;
if (tilt)
- tilt_value = (int32_t)REG_A[4];
+ render_item->u.stars.tilt_value = (int32_t)REG_A[4];
- /* 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
- */
- mercenary_get_orientation_raw(&pitch, &yaw);
-
- if (above_zenith)
- yaw = 0x200 + yaw;
- yaw = (yaw + 91 - (int)(91.0 * (frustum_slope_fov / frustum_slope_64))) & 0x3ff;
- yaw <<= 1;
- table = mercenary_star_table();
- table_start = table + m68k_read_memory_16(table);
- table += m68k_read_memory_16(table + yaw);
- yaw = ((uint32_t)yaw * 0xe10e) >> 16;
-
- if (above_zenith)
- pitch = 0x200 - pitch;
- pitch = pitch & 0x3ff;
- pitch -= v_offset;
- pitch <<= 2;
- pitch = (pitch * 0x6ccc) >> 16;
-
- while (1) {
- x = m68k_read_memory_16(table);
- if (x >= 1800) {
- x_offset += 1800;
- table = table_start;
- }
- x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
- table += 2;
- if (x < 0)
- break;
- /* special case where we tilt the view when flying on the planet */
- if (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 = (int32_t)((x - (int16_t)(160.0 / frustum_slope_64 * frustum_slope_fov)) * tilt_value) >> 16;
- }
- y = ((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
- table += 2;
- if (above_zenith) {
- x = (view_width - 1) - x;
- y = ~y + 136;
- }
- /* get color */
- gamecolor2gl(color[(m68k_read_memory_8(table - 2) & 0x3c) >> 2]);
- /* render point */
- opengl_render_point(160.0 / frustum_slope_64 * frustum_slope_fov - (double)x, 68.0 - (double)y, z, 0.0);
- }
+ /* stars above zenith */
+ render_item->u.stars.above_zenith = above_zenith;
}
-/* draw stars of interstellar flight */
+/* stars of interstellar flight */
static void draw_stars_interstellar(void)
{
int i, count;
uint32_t table;
- uint16_t color[16];
- int16_t x, y;
- double z;
#ifdef DEBUG_VERTEX
- printf("draw interstellar stars\n");
+ printf("add interstellar stars\n");
#endif
- /* use default fov of 64 to calculate z distance */
- z = 160.0 / frustum_slope_64;
- /* get palette */
- for (i = 0; i < 16; i++)
- color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_INTERSTELLAR_STARS);
table = REG_A[0];
count = REG_D[5] + 1;
+ if (count > MAX_INTERSTARS) {
+ print_error("Expecting maximum of %d stars here, plese fix!\n", MAX_INTERSTARS);
+ return;
+ }
for (i = 0; i < count; i++) {
table += 12;
/* get color */
- gamecolor2gl(color[(m68k_read_memory_16(table) >> 5) & 0xf]);
+ render_item->u.interstars.color[i] = (m68k_read_memory_16(table) >> 5) & 0xf;
table += 2;
- x = m68k_read_memory_16(table);
+ render_item->u.interstars.x[i] = m68k_read_memory_16(table);
table += 2;
- y = m68k_read_memory_16(table);
+ render_item->u.interstars.y[i] = m68k_read_memory_16(table);
table += 2;
- /* render point */
- opengl_render_point(160.0 - (double)x, 68.0 - (double)y, z, 0.0);
}
-
+ render_item->u.interstars.count = count;
}
-/* draw sun of interstellar flight (center dot) */
+/* sun of interstellar flight (center dot) */
static void draw_sun_interstellar(void)
{
#ifdef DEBUG_VERTEX
- printf("draw interstellar sun\n");
+ printf("add interstellar sun\n");
#endif
- /* white */
- gamecolor2gl(0x777);
- /* render point */
- opengl_render_point(0.0, 0.0, 100.0, 0.0);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_INTERSTELLAR_SUN);
}
/* coordinates ready for polygons of islands */
y = -y;
z = ((int16_t)m68k_read_memory_16(REG_A[4]) * 65536);
z += (int32_t)REG_A[3];
- store_coord("island", REG_A[0], (double)x, (double)y, (double)z);
+ store_coord("island", REG_A[0], x, y, z);
}
-/* render polygon of island */
+/* polygon of island */
static void poly_island()
{
uint16_t color;
uint32_t vertex_address = REG_A[0];
uint32_t vertex;
int i;
- double roll, pitch, yaw, x[16], y[16], z[16];
- int rc;
#ifdef DEBUG_VERTEX
- printf("draw island:\n");
+ printf("add island:\n");
#endif
- color = m68k_read_memory_8(vertex_address++) << 8;
- color |= m68k_read_memory_8(vertex_address++);
- gamecolor2gl(color);
- /* get orientation */
- mercenary_get_orientation(&roll, &pitch, &yaw);
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_ISLAND_POLYGON);
+ /* set color */
+ color = m68k_read_memory_8(vertex_address++) << 8;
+ color |= m68k_read_memory_8(vertex_address++);
+ gamecolor2gl(&render_item->u.polygon.red, &render_item->u.polygon.green, &render_item->u.polygon.blue, color);
/* the vertex list is zero-terminated */
i = 0;
- while (1) {
+ while (i < MAX_POLYGON) {
vertex = m68k_read_memory_8(vertex_address++);
if (vertex == 0 && i)
break;
/* skip mysterious points when rendering island */
if (vertex >= 0xf0)
continue;
- rc = use_coord("island", vertex, &x[i], &y[i], &z[i]);
- if (rc < 0)
- break;
- /* rotate vertex */
- rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
- if (i++ == 16)
- break;
+ render_item->u.polygon.vertex[i] = vertex;
+ i++;
}
- /* render polygon to OpenGL */
- opengl_render_polygon_and_line(x, y, z, i); /* no culling, because polygons lay on the gound and are always visible! */
+ render_item->u.polygon.vertices = i;
}
-/* draw sights */
+/* sights */
static void draw_sights(void)
{
- double x[4], y[4], z[4];
-
- /* use default fov of 64 to calculate z distance */
- z[0] = z[1] = z[2] = z[3] = 160.0 / frustum_slope_64;
-
- /* white */
- gamecolor2gl(0x777);
-
- y[0] = y[3] = -1.0;
- y[1] = y[2] = 1.0;
- x[0] = x[1] = -16.0;
- x[2] = x[3] = -8.0;
- opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
- x[0] = x[1] = 8.0;
- x[2] = x[3] = 16.0;
- opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+#ifdef DEBUG_VERTEX
+ printf("add sights:\n");
+#endif
+
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_SIGHTS);
}
/* stop event from CPU received */
-void render_improved_event(int event)
+void render_capture_event(int event)
{
switch (event) {
case STOP_AT_CLEAR_SCREEN1:
}
}
+static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z)
+{
+ render_item_t *ri = NULL;
+
+ if ((vertex & 3)) {
+ print_error("Vertex %d is not a multiple of four!\n", vertex);
+ return -1;
+ }
+ if (vertex < 0x100) {
+ if (!render_item_vertices_0) {
+ print_error("Vertices item for vertex %d not yet set!\n", vertex);
+ return -1;
+ }
+ ri = render_item_vertices_0;
+ } else
+ if (vertex < 0x200) {
+ if (!render_item_vertices_1) {
+ print_error("Vertices item for vertex %d not yet set!\n", vertex);
+ return -1;
+ }
+ ri = render_item_vertices_1;
+ vertex -= 0x100;
+ } else
+ if (vertex < 0x300) {
+ if (!render_item_vertices_2) {
+ print_error("Vertices item for vertex %d not yet set!\n", vertex);
+ return -1;
+ }
+ ri = render_item_vertices_2;
+ vertex -= 0x200;
+ } else {
+ print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+ 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)) {
+ print_error("Vertex is not a multiple of four!\n");
+ return -1;
+ }
+ if (vertex >= MAX_VERTEX) {
+ print_error("Vertex %d exceeds maximum vertex number %d!\n", vertex, MAX_VERTEX);
+ return -1;
+ }
+ if (level < 1 || level > 4) {
+ print_error("Level %d is out of range (1..4)!\n", level);
+ return -1;
+ }
+ if (!render_item_vertices_interior) {
+ print_error("Vertices item for interior verticies not yet set!\n");
+ return -1;
+ }
+ vertex >>= 2;
+ *x = render_item_vertices_interior->u.vertices_interior.x[vertex];
+ *y = render_item_vertices_interior->u.vertices_interior.y[level - 1];
+ *z = render_item_vertices_interior->u.vertices_interior.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;
+}
+
+/* renders one item from render list */
+void render_one_item(render_item_t *render_item)
+{
+ switch (render_item->type) {
+ case RENDER_ITEM_VERTICES_0:
+ {
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_VERTICES_0\n");
+#endif
+ render_item_vertices_0 = render_item;
+ break;
+ }
+ case RENDER_ITEM_VERTICES_1:
+ {
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_VERTICES_1\n");
+#endif
+ render_item_vertices_1 = render_item;
+ break;
+ }
+ case RENDER_ITEM_VERTICES_2:
+ {
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_VERTICES_2\n");
+#endif
+ render_item_vertices_2 = render_item;
+ break;
+ }
+ case RENDER_ITEM_VERTICES_INTERIOR:
+ {
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_VERTICES_INTERIOR\n");
+#endif
+ render_item_vertices_interior = render_item;
+ break;
+ }
+ case RENDER_ITEM_SKY:
+ {
+ double x[4], y[4], z[4];
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_SKY\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.sky.red, render_item->u.sky.green, render_item->u.sky.blue, 1.0);
+ /* create plane to fill view */
+ x[0] = x[1] = y[1] = y[2] = -1000000;
+ x[2] = x[3] = y[0] = y[3] = 1000000;
+ z[0] = z[1] = z[2] = z[3] = 10;
+ /* render */
+ opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sky (background) is always visible! */
+ break;
+ }
+ case RENDER_ITEM_GROUND:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[4], y[4], z[4];
+ int i;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_GROUND\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.ground.red, render_item->u.ground.green, render_item->u.ground.blue, 1.0);
+ yaw = 0.0; /* no need to rotate x-z plane, we don't want look at a corner of the 'ground-square' */
+ /* create huge square */
+ x[0] = x[1] = z[1] = z[2] = -1000000;
+ x[2] = x[3] = z[0] = z[3] = 1000000;
+ y[0] = y[1] = y[2] = y[3] = -10;
+ /* rotate vertex */
+ for (i = 0; i < 4; i++)
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ /* render */
+ opengl_render_polygon(x, y, z, 4, 0); /* no culling, because gound is always visible! */
+ break;
+ }
+ case RENDER_ITEM_OBJECT_POLYGON:
+ case RENDER_ITEM_TAG_POLYGON:
+ case RENDER_ITEM_ISLAND_POLYGON:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ if (render_item->type == RENDER_ITEM_OBJECT_POLYGON)
+ printf("RENDER_ITEM_OBJECT_POLYGON\n");
+ if (render_item->type == RENDER_ITEM_TAG_POLYGON)
+ printf("RENDER_ITEM_TAG_POLYGON\n");
+ if (render_item->type == RENDER_ITEM_ISLAND_POLYGON)
+ printf("RENDER_ITEM_ISLAND_POLYGON\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < render_item->u.polygon.vertices; i++) {
+ /* get vertex */
+ rc = use_coord("object", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, render_item->u.polygon.vertices, 1); /* back face culling */
+ break;
+ }
+ case RENDER_ITEM_OBJECT_LINE:
+ case RENDER_ITEM_TAG_LINE:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[2], y[2], z[2];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ if (render_item->type == RENDER_ITEM_OBJECT_LINE)
+ printf("RENDER_ITEM_OBJECT_LINE\n");
+ if (render_item->type == RENDER_ITEM_TAG_LINE)
+ printf("RENDER_ITEM_TAG_LINE\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < 2; i++) {
+ /* get vertex */
+ rc = use_coord("object", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+ break;
+ }
+ case RENDER_ITEM_BEACON_POINT:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x, y, z;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BEACON_POINT\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.point.red, render_item->u.point.green, render_item->u.point.blue, debug_opacity);
+ /* get vertex */
+ rc = use_coord("beacon", render_item->u.point.vertex, &x, &y, &z);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x, &y, &z);
+ /* render */
+ opengl_render_point(x, y, z, 0.0);
+ break;
+ }
+ case RENDER_ITEM_BUILDING_EXTERIOR_POLYGON:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BUILDING_EXTERIOR_POLYGON\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < render_item->u.polygon.vertices; i++) {
+ /* get vertex */
+ rc = use_coord("building exterior", render_item->u.polygon.vertex[i], &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, render_item->u.polygon.vertices, 1); /* back face culling */
+ break;
+ }
+ case RENDER_ITEM_BUILDING_EXTERIOR_LINE:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[2], y[2], z[2];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BUILDING_EXTERIOR_LINE\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < 2; i++) {
+ /* get vertex */
+ rc = use_coord("building exterior", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+ break;
+ }
+ case RENDER_ITEM_BUILDING_INTERIOR_1TO4:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[4], y[4], z[4];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BUILDING_INTERIOR_1TO4\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.interior14.red, render_item->u.interior14.green, render_item->u.interior14.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < 4; i++) {
+ /* get vertex */
+ rc = use_interior_coord("building exterior", render_item->u.interior14.vertex[i], render_item->u.interior14.level, &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, 4, 1); /* back face culling */
+ break;
+ }
+ case RENDER_ITEM_BUILDING_INTERIOR_5TO6:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[4], y[4], z[4];
+ int i;
+ int vertex, level;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BUILDING_INTERIOR_5TO6\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.interior56.red, render_item->u.interior56.green, render_item->u.interior56.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < 4; i++) {
+ /* get vertex */
+ vertex = (i == 0 || i == 3) ? render_item->u.interior56.vertex14 : render_item->u.interior56.vertex23;
+ level = (i == 0 || i == 1) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+ rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, 4, 1); /* back face culling */
+ break;
+ }
+ case RENDER_ITEM_BUILDING_INTERIOR_WALL:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[4], y[4], z[4];
+ int i;
+ int vertex, level;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_BUILDING_INTERIOR_WALL\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.interior56.red, render_item->u.interior56.green, render_item->u.interior56.blue, debug_opacity);
+ /* chedck if wall is a rectangle or a line */
+ if (render_item->u.interior56.vertex14 != render_item->u.interior56.vertex23) {
+ /* get and rotate vertex */
+ for (i = 0; i < 4; i++) {
+ /* get vertex */
+ vertex = (i == 0 || i == 3) ? render_item->u.interior56.vertex14 : render_item->u.interior56.vertex23;
+ level = (i == 0 || i == 1) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+ rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon_and_line(x, y, z, 4); /* no culling, because walls are always visible! */
+ } else {
+ /* get and rotate vertex */
+ for (i = 0; i < 2; i++) {
+ /* get vertex */
+ vertex = render_item->u.interior56.vertex14;
+ level = (i == 0) ? render_item->u.interior56.level12 : render_item->u.interior56.level34;
+ rc = use_interior_coord("building interior", vertex, level, &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+ }
+ break;
+ }
+ case RENDER_ITEM_COMET_POLYGON:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double inclination = planet_inclination, azimuth = planet_azimuth;
+ double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_COMET_POLYGON\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+ /* 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]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ if (planet_rotation)
+ rotate_coordinate(0.0, inclination, azimuth, &x[i], &y[i], &z[i]);
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon_and_line(x, y, z, render_item->u.polygon.vertices); /* no culling, because we render only two (out of four) planes! */
+ break;
+ }
+ case RENDER_ITEM_ROAD_LINE:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[2], y[2], z[2];
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_ROAD_LINE\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.line.red, render_item->u.line.green, render_item->u.line.blue, debug_opacity);
+ /* get and rotate vertex */
+ for (i = 0; i < 2; i++) {
+ /* get vertex */
+ rc = use_coord("road", render_item->u.line.vertex[i], &x[i], &y[i], &z[i]);
+ if (rc < 0)
+ break;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_line(x[0], y[0], z[0], x[1], y[1], z[1], 0.0);
+ break;
+ }
+ case RENDER_ITEM_ROAD_POLYGON:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+ int i, v;
+ uint32_t vertex, vertex_prev, vertex_next;
+ double x_current, y_current, z_current;
+ double x_prev, y_prev, z_prev;
+ double x_next, y_next, z_next;
+ int vertices_num;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_ROAD_POLYGON\n");
+#endif
+ /* get color */
+ opengl_render_color(render_item->u.polygon.red, render_item->u.polygon.green, render_item->u.polygon.blue, debug_opacity);
+ /* get and rotate vertex */
+ i = 0;
+ vertices_num = render_item->u.polygon.vertices;
+ for (v = 0; v < vertices_num; v++) {
+ /* get vertex */
+ vertex = render_item->u.polygon.vertex[v];
+ rc = use_coord("road/place", vertex, &x_current, &y_current, &z_current);
+ if (rc < 0)
+ break;
+ /* check for road extension, so we extend the road to the given end point */
+ if (extend_roads && vertex >= 0xf0) {
+ /* previous vertex */
+ vertex_prev = render_item->u.polygon.vertex[(v + vertices_num - 1) % vertices_num];
+ rc = use_coord("road/place", vertex_prev, &x_prev, &y_prev, &z_prev);
+ if (rc < 0)
+ break;
+ /* next vertex */
+ vertex_next = render_item->u.polygon.vertex[(v + 1) % vertices_num];
+ rc = use_coord("road/place", vertex_next, &x_next, &y_next, &z_next);
+ if (rc < 0)
+ break;
+ /* extend vertices to end point position
+ * change x or z coordinate, whatever is greater
+ */
+ if (fabs(x_prev - x_current) > fabs(z_prev - z_current))
+ x_prev = x_next = x_current;
+ else
+ z_prev = z_next = z_current;
+ /* store vertices */
+ x[i] = x_prev;
+ y[i] = y_prev;
+ z[i] = z_prev;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ if (i++ == MAX_POLYGON)
+ break;
+ x[i] = x_next;
+ y[i] = y_next;
+ z[i] = z_next;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ if (i++ == MAX_POLYGON)
+ break;
+ continue;
+ } else {
+ /* no extension, just keep the current point as is */
+ x[i] = x_current;
+ y[i] = y_current;
+ z[i] = z_current;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ if (i++ == MAX_POLYGON)
+ break;
+ }
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, i, 0); /* no culling, because polygons lay on the gound and are always visible! */
+ break;
+ }
+ case RENDER_ITEM_PLANET:
+ {
+ double roll = orientation_roll, pitch = orientation_pitch, yaw = orientation_yaw;
+ double inclination = planet_inclination, azimuth = 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];
+ double size, angle;
+ int i;
+ int rc;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_PLANET\n");
+#endif
+ /* get location */
+ rc = use_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);
+ if (rc < 0)
+ break;
+ /* get size */
+ size = render_item->u.planet.size;
+ /* rotate vertex */
+ if (planet_rotation) {
+ rotate_coordinate(0.0, inclination, azimuth, &sun_x, &sun_y, &sun_z);
+ rotate_coordinate(0.0, inclination, azimuth, &loc_x, &loc_y, &loc_z);
+ }
+ rotate_coordinate(roll, pitch, yaw, &sun_x, &sun_y, &sun_z);
+ 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;
+ if (angle > M_PI)
+ angle -= 2.0 * M_PI;
+ if (angle < -M_PI)
+ angle += 2.0 * M_PI;
+
+ /* 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) {
+ /* get front side color */
+ opengl_render_color(render_item->u.planet.front_red, render_item->u.planet.front_green, render_item->u.planet.front_blue, debug_opacity);
+ } else {
+ /* get back side color */
+ opengl_render_color(render_item->u.planet.back_red, render_item->u.planet.back_green, render_item->u.planet.back_blue, debug_opacity);
+ }
+
+ /* create and render cicle */
+ 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;
+ }
+ opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
+
+ if (render_item->u.planet.vertex == 0) {
+ /* sun has no crescent */
+ break;
+ }
+
+ /* on which side are we */
+ if (angle < M_PI / 2.0 && angle > -M_PI / 2.0) {
+ /* get back side color */
+ opengl_render_color(render_item->u.planet.back_red, render_item->u.planet.back_green, render_item->u.planet.back_blue, debug_opacity);
+ } else {
+ /* get front side color */
+ opengl_render_color(render_item->u.planet.front_red, render_item->u.planet.front_green, render_item->u.planet.front_blue, debug_opacity);
+ }
+
+ /* 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;
+ }
+ 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;
+ }
+ } 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;
+ }
+ 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;
+ }
+ }
+ opengl_render_polygon_and_line(x, y, z, PLANET_VERTICES); /* no culling, its a planet! */
+ opengl_render_point(loc_x, loc_y, loc_z, 0.0); /* planet is visible at any distance - at least as a point */
+ break;
+ }
+ case RENDER_ITEM_STARS:
+ {
+ int16_t tilt_offset = 0;
+ int x_offset = 0;
+ uint16_t color[16];
+ uint16_t view_width, yaw = orientation_raw_yaw;
+ int16_t pitch = orientation_raw_pitch;
+ uint32_t table, table_start;
+ int16_t x, y;
+ double z;
+ int i;
+ double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_STARS\n");
+#endif
+ /* use default fov of 64 to calculate z distance */
+ z = 160.0 / frustum_slope_64;
+
+ view_width = (int)(320.0 / frustum_slope_64 * frustum_slope_fov);
+
+ /* get palette */
+ 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 = (yaw + 91 - (int)(91.0 * (frustum_slope_fov / frustum_slope_64))) & 0x3ff;
+ yaw <<= 1;
+ table = mercenary_star_table();
+ table_start = table + m68k_read_memory_16(table);
+ table += m68k_read_memory_16(table + yaw);
+ yaw = ((uint32_t)yaw * 0xe10e) >> 16;
+
+ if (render_item->u.stars.above_zenith)
+ pitch = 0x200 - pitch;
+ pitch = pitch & 0x3ff;
+ pitch -= render_item->u.stars.v_offset;
+ pitch <<= 2;
+ pitch = (pitch * 0x6ccc) >> 16;
+
+ while (1) {
+ x = m68k_read_memory_16(table);
+ if (x >= 1800) {
+ x_offset += 1800;
+ table = table_start;
+ }
+ x = (view_width - 1) - m68k_read_memory_16(table) - x_offset + yaw;
+ table += 2;
+ if (x < 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 = (int32_t)((x - (int16_t)(160.0 / frustum_slope_64 * frustum_slope_fov)) * render_item->u.stars.tilt_value) >> 16;
+ }
+ y = ((m68k_read_memory_16(table)) & 0x1ff) - pitch + tilt_offset;
+ table += 2;
+ if (render_item->u.stars.above_zenith) {
+ x = (view_width - 1) - x;
+ y = ~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 - (double)x, 68.0 - (double)y, z, 0.0);
+ }
+ break;
+ }
+ case RENDER_ITEM_INTERSTELLAR_STARS:
+ {
+ uint16_t color[16];
+ double z;
+ int i;
+ double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_INTERSTELLAR_STARS\n");
+#endif
+ /* use default fov of 64 to calculate z distance */
+ z = 160.0 / frustum_slope_64;
+
+ /* get palette */
+ for (i = 0; i < 16; i++)
+ color[i] = m68k_read_memory_16(mercenary_palette_stars() + (i << 2));
+
+ for (i = 0; i < render_item->u.interstars.count; i++) {
+ 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);
+ }
+ break;
+ }
+ case RENDER_ITEM_INTERSTELLAR_SUN:
+ {
+ double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_INTERSTELLAR_SUN\n");
+#endif
+ /* white */
+ gamecolor2gl(&red, &green, &blue, 0x777);
+ opengl_render_color(red, green, blue, debug_opacity);
+ /* render point */
+ opengl_render_point(0.0, 0.0, 100.0, 0.0);
+ break;
+ }
+ case RENDER_ITEM_SIGHTS:
+ {
+ double x[4], y[4], z[4];
+ double red, green, blue;
+
+#ifdef DEBUG_ITEMS
+ printf("RENDER_ITEM_SIGHTS\n");
+#endif
+ /* use default fov of 64 to calculate z distance */
+ z[0] = z[1] = z[2] = z[3] = 160.0 / frustum_slope_64;
+
+ /* white */
+ gamecolor2gl(&red, &green, &blue, 0x777);
+ opengl_render_color(red, green, blue, debug_opacity);
+
+ y[0] = y[3] = -1.0;
+ y[1] = y[2] = 1.0;
+ x[0] = x[1] = -16.0;
+ x[2] = x[3] = -8.0;
+ opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+ x[0] = x[1] = 8.0;
+ x[2] = x[3] = 16.0;
+ opengl_render_polygon(x, y, z, 4, 0); /* no culling, because sights are always visible! */
+ break;
+ }
+ default:
+ print_error("Unknown type, please fix!\n");
+ }
+}
+
+void render_all_items()
+{
+ render_item_vertices_0 = render_item_vertices_1 = render_item_vertices_2 = NULL;
+ render_item_vertices_interior = NULL;
+
+ for (render_item = render_list_start; render_item; render_item = render_item->next) {
+ render_one_item(render_item);
+ }
+}
+