* - interpolation for interpolated result
* 3. The complete scene is rendered:
* - render_all_items() calls the render_item() for each item
+ * - All items before shadows on the ground are rendered first
+ * - Then all items with shadows are rendered
+ * - Then all items after shadows are rendered
* - The recent capture (NEW) is rendered
* - Interpolation result is taken into account
+ *
*/
#include <stdio.h>
//#define DEBUG_COLOR
//#define DEBUG_VERTEX
//#define DEBUG_ITEMS
+//#define DEBUG_LIGHT
+
+#define ELEVATION_SKY_NIGHT -0.05 /* elevation of darkest sky */
+#define ELEVATION_SKY_DAY 0.3 /* elevation of brightest sky */
+#define ELEVATION_STARS_NIGHT -0.1 /* elevation of brightest stars */
+#define ELEVATION_STARS_DAY 0.1 /* elevation of no stars */
+#define ELEVATION_SHADOW_MIN 0.03 /* elevation of shadow begin */
+#define ELEVATION_SHADOW_MAX 0.3 /* elevation of darkest shadow */
+#define SHADOW_LEVEL 0.9 /* opacity of darkest shadow */
-#define MAX_POLYGON 16 /* number of polygon complexity (vertices) */
+#define MAX_POLYGON 16 /* number of polygon corners (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 FIX_OBJECT_SCALE 16 /* intercity... */
#define FIX_OBJECT_SCALE_TAG 2 /* line in faces of persons */
+enum render_shadow {
+ RENDER_BEFORE_SHADOW,
+ RENDER_AT_SHADOW,
+ RENDER_AFTER_SHADOW,
+};
+
/*
* render item definition and structures
*/
RENDER_ITEM_ISLAND_POLYGON,
RENDER_ITEM_SIGHTS,
RENDER_ITEM_EXPLOSION,
+ RENDER_ITEM_SHADOW_BUILDING_POLYGON,
+ RENDER_ITEM_SHADOW_BUILDING_LINE,
+ RENDER_ITEM_SHADOW_OBJECT_POLYGON,
+ RENDER_ITEM_SHADOW_OBJECT_LINE,
};
struct render_item_info {
int count;
};
+struct render_item_shadow_polygon {
+ int32_t x_pos, y_pos, z_pos;
+ int vertices;
+ int32_t x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+};
+
+struct render_item_shadow_line {
+ int32_t x_pos, y_pos, z_pos;
+ int32_t x[2], y[2], z[2];
+};
+
typedef struct render_item {
struct render_item *next;
enum render_item_type type;
struct render_item_stars stars;
struct render_item_interstars interstars;
struct render_item_explosion explosion;
+ struct render_item_shadow_polygon shadow_polygon;
+ struct render_item_shadow_line shadow_line;
} u;
} render_item_t;
static int extend_roads; /* extend roads in its original width, rather than just using a single point */
static int improve_stars; /* stars are rendered spherical */
static int fix_sky_rotation; /* sky will rotate correctly by rotating planets/comet by 180 degrees */
+static int draw_shadows; /* render shadows */
static double planet_aspect, explosion_aspect; /* aspect ratio */
static double fov;
static double debug_opacity;
static render_item_t *render_item_vertices_0, *render_item_vertices_1, *render_item_vertices_2;
static render_item_t *render_item_vertices_planets, *render_item_vertices_interior;
+/* states while rendering */
+int sun_valid = 0;
+double stars_bright; /* the brightness of stars */
+double shadow_level; /* how 'dark' the shadow is (that is darker at day) */
+double sun_pos_x, sun_pos_y, sun_pos_z;
+double sky_color_red, sky_color_green, sky_color_blue;
+
/*
* capturing
*/
}
/* rendering starts, initialize variables */
-void render_capture_start(double _fov, int _extend_roads, int _smooth_planets, int _improve_stars, int _fix_sky_rotation, int _round_planets, int debug)
+void render_capture_start(double _fov, int _extend_roads, int _smooth_planets, int _improve_stars, int _fix_sky_rotation, int _round_planets, int _shadows, int debug)
{
#if defined(DEBUG_COLOR) || defined(DEBUG_VERTEX)
printf("start rendering a new frame...\n");
improve_stars = _improve_stars;
planet_aspect = (_round_planets) ? 1.0 : PLANET_STRETCH;
explosion_aspect = (_round_planets) ? 1.0 : EXPLOSION_STRETCH;
+ draw_shadows = _shadows;
/* set some transpareny, if debugging is enabled */
debug_opacity = (debug) ? 0.5 : 1.0;
render_item->u.vertices.z[vertex] = (double)z * scale + motion_new.position_north;
}
+static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z, int fix);
+
static void store_planets_coord(const char __attribute__((unused)) *what, uint32_t vertex, int32_t x, int32_t y, int32_t z)
{
if ((vertex & 3)) {
render_item->u.info.moving = moving;
if (moving)
mercenary_get_object_info(&render_item->u.info.id, &render_item->u.info.east, &render_item->u.info.height, &render_item->u.info.north);
+ render_item_object_info = render_item;
}
/* coordinates ready for an object */
/* polygon of object */
static void poly_object(int mercenary)
{
- uint32_t vertex_address = REG_A[0];
+ uint32_t vertex_address = REG_A[0], va;
uint32_t vertex;
- int i;
+ double x, y, z;
+ int i, rc;
#ifdef DEBUG_VERTEX
printf("add object's polygon:\n");
}
/* the vertex list is zero-terminated */
+ va = vertex_address;
for (i = 0; i < MAX_POLYGON; i++) {
- vertex = m68k_read_memory_8(vertex_address++);
+ vertex = m68k_read_memory_8(va++);
if (vertex == 0 && i)
break;
render_item->u.polygon.vertex[i] = vertex;
}
render_item->u.polygon.vertices = i;
+
+ /* apply only to not fixed objects (a fixed may be taxi interior) */
+ if (render_item_object_info && render_item_object_info->u.info.moving) {
+ /* allocate shadow item */
+ render_item_add(RENDER_ITEM_SHADOW_OBJECT_POLYGON);
+ render_item->u.shadow_polygon.x_pos = -motion_new.position_east;
+ render_item->u.shadow_polygon.y_pos = -motion_new.position_height;
+ render_item->u.shadow_polygon.z_pos = -motion_new.position_north;
+
+ /* the vertex list is zero-terminated */
+ va = vertex_address;
+ for (i = 0; i < MAX_POLYGON; i++) {
+ vertex = m68k_read_memory_8(va++);
+ if (vertex == 0 && i)
+ break;
+ rc = use_coord("object", vertex, &x, &y, &z, 1);
+ if (rc < 0)
+ break;
+ render_item->u.shadow_polygon.x[i] = x + motion_new.position_east;
+ render_item->u.shadow_polygon.y[i] = y + motion_new.position_height;
+ render_item->u.shadow_polygon.z[i] = z + motion_new.position_north;
+ }
+ render_item->u.shadow_polygon.vertices = i;
+ }
}
/* line of object */
static void line_object(void)
{
- uint32_t vertex_address = REG_A[0];
+ uint32_t vertex_address = REG_A[0], va;
uint32_t vertex;
+ double x, y, z;
+ int rc;
#ifdef DEBUG_VERTEX
printf("add object's line:\n");
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++);
+ va = vertex_address;
+ vertex = m68k_read_memory_8(va++);
render_item->u.line.vertex[0] = vertex;
- vertex = m68k_read_memory_8(vertex_address++);
+ vertex = m68k_read_memory_8(va++);
render_item->u.line.vertex[1] = vertex;
+
+ /* allocate shadow item */
+ render_item_add(RENDER_ITEM_SHADOW_OBJECT_LINE);
+ render_item->u.shadow_line.x_pos = -motion_new.position_east;
+ render_item->u.shadow_line.y_pos = -motion_new.position_height;
+ render_item->u.shadow_line.z_pos = -motion_new.position_north;
+
+ /* apply only to not fixed objects (a fixed may be taxi interior) */
+ if (render_item_object_info && render_item_object_info->u.info.moving) {
+ va = vertex_address;
+ vertex = m68k_read_memory_8(va++);
+ rc = use_coord("object", vertex, &x, &y, &z, 1);
+ if (rc < 0)
+ x=y=z=0;
+ render_item->u.shadow_line.x[0] = x + motion_new.position_east;
+ render_item->u.shadow_line.y[0] = y + motion_new.position_height;
+ render_item->u.shadow_line.z[0] = z + motion_new.position_north;
+ vertex = m68k_read_memory_8(va++);
+ rc = use_coord("object", vertex, &x, &y, &z, 1);
+ if (rc < 0)
+ x=y=z=0;
+ render_item->u.shadow_line.x[1] = x + motion_new.position_east;
+ render_item->u.shadow_line.y[1] = y + motion_new.position_height;
+ render_item->u.shadow_line.z[1] = z + motion_new.position_north;
+ }
}
/* coordinates ready for a beacon */
render_item->u.explosion.count++;
}
+/* get building data out of game data, so we use it to render shadow */
+static void draw_shadow_building(void)
+{
+ int32_t scale_x, scale_y, scale_z;
+ int32_t x, y, z;
+ uint16_t anim_flag, anim_x, anim_y, anim_z, anim_phase;
+ uint32_t a0, a0s, a5, a6, a4;
+ uint16_t s;
+ int16_t d3, d4, d5;
+ int32_t d3x, d4x, d5x;
+ int d1index;
+ int line_from, line_to, point;
+ int i;
+ struct render_item_vertices vertex;
+
+ mercenary_get_building_exterior_info(&x, &z, &scale_x, &scale_y, &scale_z, &anim_flag, &anim_x, &anim_y, &anim_z, &anim_phase, &a4, &a0, &a5);
+ x -= motion_new.position_east;
+ y = -motion_new.position_height;
+ z -= motion_new.position_north;
+
+ /* list of all vetices */
+ for (i = 1; i < 64; i++) {
+ d3 = m68k_read_memory_16(a4);
+ a4 += 2;
+ if (d3 <= (int16_t)0x8001)
+ break;
+ d4 = m68k_read_memory_16(a4);
+ a4 += 2;
+ d5 = m68k_read_memory_16(a4);
+ a4 += 2;
+ if (d4 < 0) {
+ d4 = ~d4;
+ /* scale */
+ d3x = d3 * scale_x;
+ d4x = d4 * scale_y;
+ d5x = d5 * scale_z;
+ /* angle */
+ double angle = (double)anim_phase / 65536.0 * 2.0 * M_PI;
+ /* animate around what axis ? */
+ if ((int16_t)anim_flag > 0) {
+ /* rotate around z */
+ d3 = (d3x & 0xffff) - anim_x;
+ d4 = (d4x & 0xffff) - anim_y;
+ if (angle) {
+ double cosd4 = (double) d4 * cos(angle);
+ double sind3 = (double) d3 * sin(angle);
+ double cosd3 = (double) d3 * cos(angle);
+ double sind4 = (double) d4 * sin(angle);
+ d3 = cosd3 - sind4;
+ d4 = cosd4 + sind3;
+ }
+ d3x = d3 + anim_x;
+ d4x = d4 + anim_y;
+ }
+ if ((int16_t)anim_flag == 0) {
+ /* rotate around y */
+ d3 = (d3x & 0xffff) - anim_x;
+ d5 = (d5x & 0xffff) - anim_z;
+ if (angle) {
+ double cosd3 = (double) d3 * cos(angle);
+ double sind5 = (double) d5 * sin(angle);
+ double cosd5 = (double) d5 * cos(angle);
+ double sind3 = (double) d3 * sin(angle);
+ d3 = cosd3 + sind5;
+ d5 = cosd5 - sind3;
+ }
+ d3x = d3 + anim_x;
+ d5x = d5 + anim_z;
+ }
+ if ((int16_t)anim_flag < 0) {
+ /* rotate around x */
+ d4 = (d4x & 0xffff) - anim_y;
+ d5 = (d5x & 0xffff) - anim_z;
+ if (angle) {
+ double cosd5 = (double) d5 * cos(angle);
+ double sind4 = (double) d4 * sin(angle);
+ double cosd4 = (double) d4 * cos(angle);
+ double sind5 = (double) d5 * sin(angle);
+ d4 = cosd4 + sind5;
+ d5 = cosd5 - sind4;
+ }
+ d4x = d4 + anim_y;
+ d5x = d5 + anim_z;
+ }
+ } else {
+ /* scale */
+ d3x = d3 * scale_x;
+ d4x = d4 * scale_y;
+ d5x = d5 * scale_z;
+ }
+ vertex.x[i] = d3x;
+ vertex.y[i] = d4x;
+ vertex.z[i] = d5x;
+ }
+
+ /* get all data sets */
+ do {
+ s = m68k_read_memory_16(a0);
+ a0 += 2;
+ if (s) {
+ /* skip over distance cube */
+ a0 += 4 * 6;
+ }
+ /* get address pointer to data set */
+ a0s = m68k_read_memory_32(a0);
+ a0 += 4;
+
+ /* walk through primitives (polygons and lines) */
+ while ((d1index = m68k_read_memory_8(a0s++))) {
+ /* pointer to primitive */
+ a6 = m68k_read_memory_32(a5 + d1index*4);
+ if ((m68k_read_memory_8(a6) & 0x40) == 0) {
+ /* polygon */
+ a6 += 2;
+#ifdef DEBUG_VERTEX
+ printf("add object's shadow polygon:\n");
+#endif
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_SHADOW_BUILDING_POLYGON);
+ render_item->u.shadow_polygon.x_pos = x;
+ render_item->u.shadow_polygon.y_pos = y;
+ render_item->u.shadow_polygon.z_pos = z;
+ i = 0;
+ while ((point = m68k_read_memory_8(a6++) >> 2)) {
+ render_item->u.shadow_polygon.x[i] = vertex.x[point];
+ render_item->u.shadow_polygon.y[i] = vertex.y[point];
+ render_item->u.shadow_polygon.z[i] = vertex.z[point];
+ i++;
+ }
+ render_item->u.shadow_polygon.vertices = i;
+ } else if ((m68k_read_memory_16(a6) & 0x2000) == 0) {
+ /* line */
+ line_from = m68k_read_memory_8(a6 + 2) >> 2;
+ line_to = m68k_read_memory_8(a6 + 3) >> 2;
+ /* allocate render item */
+ render_item_add(RENDER_ITEM_SHADOW_BUILDING_LINE);
+ render_item->u.shadow_line.x_pos = x;
+ render_item->u.shadow_line.y_pos = y;
+ render_item->u.shadow_line.z_pos = z;
+ render_item->u.shadow_line.x[0] = vertex.x[line_from];
+ render_item->u.shadow_line.y[0] = vertex.y[line_from];
+ render_item->u.shadow_line.z[0] = vertex.z[line_from];
+ render_item->u.shadow_line.x[1] = vertex.x[line_to];
+ render_item->u.shadow_line.y[1] = vertex.y[line_to];
+ render_item->u.shadow_line.z[1] = vertex.z[line_to];
+ }
+ }
+ } while (s);
+}
+
/* stop event from CPU received */
void render_capture_event(int event)
{
case STOP_AT_POINT_BEACON:
point_beacon();
/* note: we may not call the point-renderer, because projected coordinates are invalid */
- mercenary_patch_render();
+ mercenary_patch_render(draw_shadows);
break;
case STOP_AT_COORD_BUILDING_EXTERIOR:
coord_building_exterior();
case STOP_AT_LINE_ISLANDS:
/* this is not used, as i had noticed so far */
puts("line island");
+#warning FIXME: this is used on LACHESIS to improve visibility of stripes on the ground. implement this and compate a version with lines to the version without lines
break;
case STOP_AT_DRAW_SIGHTS:
draw_sights();
draw_explosion();
break;
case STOP_AT_PATCH_RENDER:
- mercenary_patch_render();
+ mercenary_patch_render(draw_shadows);
+ break;
+ case STOP_AT_SHADOW_BUILDING:
+ draw_shadow_building();
break;
}
}
* rendering
*/
-static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z, int fix)
+static int use_coord(const char __attribute__((unused)) *what, uint32_t vertex, double *x, double *y, double *z, int no_inter)
{
render_item_t *ri = NULL;
*x = ri->u.vertices.x[vertex] - motion_new.position_east;
*y = ri->u.vertices.y[vertex] - motion_new.position_height;
*z = ri->u.vertices.z[vertex] - motion_new.position_north;
- if (!fix) {
+ if (!no_inter) {
/* translate to floating (interpolated) position offset */
*x -= interpolation.offset_east;
*y -= interpolation.offset_height;
return 0;
}
+/* this will calculate lighting parameters for sky and shadows */
+static void calculate_lighting(double sun_x, double sun_y, double sun_z, double *day, double *stars, double *shadow)
+{
+ double elevation;
+
+// azimuth = atan2(sun_z, sun_x);
+
+ /* how high is the sun (1.0 is zenith, < 0 is below horizon) */
+ elevation = atan2(sun_y, sqrt(sun_x * sun_x + sun_z * sun_z)) / (M_PI / 2);
+#ifdef DEBUG_LIGHT
+ printf("Elevation of SUN: %.3f\n", elevation);
+#endif
+
+ /* 'day' is how much day color is used for sky (1.0) or night color (0.0) */
+ *day = (elevation - ELEVATION_SKY_NIGHT) / (ELEVATION_SKY_DAY - ELEVATION_SKY_NIGHT);
+ if (*day < 0.0)
+ *day = 0.0;
+ if (*day > 1.0)
+ *day = 1.0;
+#ifdef DEBUG_LIGHT
+ printf("How much day: %.3f\n", *day);
+#endif
+
+ /* 'stars' is how much we see the stars (1.0) fully bright, (0.0) no stars */
+ *stars = (elevation - ELEVATION_STARS_DAY) / (ELEVATION_STARS_NIGHT - ELEVATION_STARS_DAY);
+ if (*stars < 0.0)
+ *stars = 0.0;
+ if (*stars > 1.0)
+ *stars = 1.0;
+#ifdef DEBUG_LIGHT
+ printf("How much stars: %.3f\n", *stars);
+#endif
+
+ /* 'shadow' is how much color (darkness) the shadow has (1.0) totally black, (0.0) not visible */
+ *shadow = (elevation - ELEVATION_SHADOW_MIN) / (ELEVATION_SHADOW_MAX - ELEVATION_SHADOW_MIN);
+ if (*shadow < 0.0)
+ *shadow = 0.0;
+ if (*shadow > 1.0)
+ *shadow = 1.0;
+ *shadow *= SHADOW_LEVEL;
+#ifdef DEBUG_LIGHT
+ printf("How much shadow: %.3f\n", *shadow);
+#endif
+
+}
+
/* renders one item from render list */
-void render_one_item(render_item_t *render_item, int vr)
+void render_one_item(render_item_t *render_item, int vr, enum render_shadow shadow)
{
switch (render_item->type) {
case RENDER_ITEM_OBJECT_INFO:
{
double x[4], y[4], z[4];
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#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);
+ if (draw_shadows && ground_index >= 0) {
+ uint16_t day, night;
+ double day_red, day_green, day_blue;
+ double night_red, night_green, night_blue;
+ double day_factor;
+
+ calculate_lighting(sun_pos_x, sun_pos_y, sun_pos_z, &day_factor, &stars_bright, &shadow_level);
+
+ /* sky color */
+ mercenary_get_sky_colors(&day, &night);
+ /* shift them to the original format (atari style) */
+ gamecolor2gl(&day_red, &day_green, &day_blue, day >> 1);
+ gamecolor2gl(&night_red, &night_green, &night_blue, night >> 1);
+ sky_color_red = day_red * day_factor + night_red * (1.0 - day_factor);
+ sky_color_green = day_green * day_factor + night_green * (1.0 - day_factor);
+ sky_color_blue = day_blue * day_factor + night_blue * (1.0 - day_factor);
+ opengl_render_color(sky_color_red, sky_color_green, sky_color_blue, 1.0);
+
+ } else
+ opengl_render_color(render_item->u.sky.red, render_item->u.sky.green, render_item->u.sky.blue, 1.0);
/* create box to fill view */
x[0] = x[1] = y[1] = y[2] = -1000;
x[2] = x[3] = y[0] = y[3] = 1000;
double x[4], y[4], z[4];
int i;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_GROUND\n");
#endif
int i, o;
int rc;
+ if (render_item->type == RENDER_ITEM_ISLAND_POLYGON) {
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+ } else {
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+ }
+
#ifdef DEBUG_ITEMS
if (render_item->type == RENDER_ITEM_OBJECT_POLYGON)
printf("RENDER_ITEM_OBJECT_POLYGON\n");
int i, o;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
if (render_item->type == RENDER_ITEM_OBJECT_LINE)
printf("RENDER_ITEM_OBJECT_LINE\n");
double x, y, z;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_BEACON_POINT\n");
#endif
int i;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_BUILDING_EXTERIOR_LINE\n");
#endif
int i;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_BUILDING_INTERIOR_1TO4\n");
#endif
int vertex, level;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_BUILDING_INTERIOR_5TO6\n");
#endif
int vertex, level;
int rc;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_BUILDING_INTERIOR_WALL\n");
#endif
int rc;
double rotate_sky = 0.0;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_COMET_POLYGON\n");
#endif
int i;
int rc;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_ROAD_LINE\n");
#endif
int vertices_num;
int rc;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_ROAD_POLYGON\n");
#endif
case RENDER_ITEM_PLANET:
{
GET_ORIENTATION;
+ double front_red, front_green, front_blue, back_red, back_green, back_blue;
double inclination = interpolation.planet_inclination, azimuth = interpolation.planet_azimuth;
double sun_x, sun_y, sun_z, angle_sun_h;
double loc_x, loc_y, loc_z, angle_loc_h, angle_loc_v;
int rc;
double rotate_sky = 0.0;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_PLANET\n");
#endif
+
+ /* color of planets */
+ front_red = render_item->u.planet.front_red;
+ front_green = render_item->u.planet.front_green;
+ front_blue = render_item->u.planet.front_blue;
+ back_red = render_item->u.planet.back_red;
+ back_green = render_item->u.planet.back_green;
+ back_blue = render_item->u.planet.back_blue;
+ if (draw_shadows && ground_index >= 0) {
+ /* front color is blended by sky */
+ front_red = front_red * (1.0 - sky_color_red) + sky_color_red;
+ front_green = front_green * (1.0 - sky_color_green) + sky_color_green;
+ front_blue = front_blue * (1.0 - sky_color_blue) + sky_color_blue;
+ back_red = sky_color_red * (1.0 - stars_bright);
+ back_green = sky_color_green * (1.0 - stars_bright);
+ back_blue = sky_color_blue * (1.0 - stars_bright);
+ }
+
/* get location */
rc = use_planet_coord("planet(sun)", 0, &sun_x, &sun_y, &sun_z);
if (rc < 0)
rotate_coordinate(0.0, inclination, azimuth, &sun_x, &sun_y, &sun_z);
rotate_coordinate(0.0, inclination, azimuth, &loc_x, &loc_y, &loc_z);
}
+ /* store sun location */
+ sun_valid = 1;
+ sun_pos_x = sun_x;
+ sun_pos_y = sun_y;
+ sun_pos_z = sun_z;
+ /* rotate sun */
rotate_coordinate(roll, pitch, yaw + rotate_sky, &sun_x, &sun_y, &sun_z);
rotate_coordinate(roll, pitch, yaw + rotate_sky, &loc_x, &loc_y, &loc_z);
/* 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);
+ opengl_render_color(front_red, front_green, 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);
+ opengl_render_color(back_red, back_green, back_blue, debug_opacity);
}
/* create and render cicle */
/* 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);
+ opengl_render_color(back_red, back_green, 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);
+ opengl_render_color(front_red, front_green, front_blue, debug_opacity);
}
/* create and render crescent */
double red, green, blue;
double rotate_sky = 0.0;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_STARS\n");
#endif
+
+ /* no stars at day */
+ if (stars_bright == 0.0)
+ break;
+
/* use default fov of 64 to calculate z distance */
z = 160.0 / frustum_slope_64;
}
/* get color */
gamecolor2gl(&red, &green, &blue, color[(m68k_read_memory_8(table - 2) & 0x3c) >> 2]);
- opengl_render_color(red, green, blue, debug_opacity);
+ opengl_render_color(red, green, blue, debug_opacity * stars_bright);
/* render point */
opengl_render_point(160.0 / frustum_slope_64 * frustum_slope_fov - x, 68.0 - y, z, 0.0);
}
table += 2;
/* get color */
gamecolor2gl(&red, &green, &blue, color[(m68k_read_memory_8(table - 2) & 0x3c) >> 2]);
- opengl_render_color(red, green, blue, debug_opacity);
+ opengl_render_color(red, green, blue, debug_opacity * stars_bright);
/* render point */
h = (900.0 - x + 160) / 900.0 * M_PI;
v1 = (68.0 - y) / 900.0 * M_PI;
int i;
double red, green, blue;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_INTERSTELLAR_STARS\n");
#endif
{
double red, green, blue;
+ if (shadow != RENDER_BEFORE_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_INTERSTELLAR_SUN\n");
#endif
double x[4], y[4], z[4];
double red, green, blue;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_SIGHTS\n");
#endif
double x[EXPLOSION_VERTICES], y[EXPLOSION_VERTICES], z[EXPLOSION_VERTICES];
int i, e;
+ if (shadow != RENDER_AFTER_SHADOW)
+ break;
+
#ifdef DEBUG_ITEMS
printf("RENDER_ITEM_EXPLOSION\n");
#endif
}
break;
}
+ case RENDER_ITEM_SHADOW_BUILDING_POLYGON:
+ case RENDER_ITEM_SHADOW_BUILDING_LINE:
+ case RENDER_ITEM_SHADOW_OBJECT_POLYGON:
+ case RENDER_ITEM_SHADOW_OBJECT_LINE:
+ {
+ GET_ORIENTATION;
+ double x[MAX_POLYGON], y[MAX_POLYGON], z[MAX_POLYGON];
+ double shadow_x, shadow_z;
+ int o;
+ int i;
+
+ if (shadow != RENDER_AT_SHADOW)
+ break;
+
+#ifdef DEBUG_ITEMS
+ if (render_item->type == RENDER_ITEM_SHADOW_POLYGON)
+ printf("RENDER_ITEM_SHADOW_POLYGON\n");
+ if (render_item->type == RENDER_ITEM_SHADOW_LINE)
+ printf("RENDER_ITEM_SHADOW_LINE\n");
+#endif
+
+ if (!sun_valid || sun_pos_y < 1.0)
+ return;
+
+ if (shadow_level == 0.0)
+ return;
+
+ /* calculate shadow */
+ shadow_x = -sun_pos_x / sun_pos_y;
+ shadow_z = -sun_pos_z / sun_pos_y;
+
+ opengl_render_color_alpha(0, 0, 0, shadow_level);
+
+ if (render_item->type == RENDER_ITEM_SHADOW_BUILDING_POLYGON
+ || render_item->type == RENDER_ITEM_SHADOW_OBJECT_POLYGON) {
+ /* get and rotate vertex */
+ for (i = 0; i < render_item->u.shadow_polygon.vertices; i++) {
+ x[i] = render_item->u.shadow_polygon.x[i];
+ y[i] = render_item->u.shadow_polygon.y[i];
+ z[i] = render_item->u.shadow_polygon.z[i];
+ /* interpolate motion, if object is moving */
+ if (render_item->type == RENDER_ITEM_SHADOW_OBJECT_POLYGON && render_item_object_info && render_item_object_info->u.info.moving) {
+ for (o = 0; o < interpolation.object_count; o++) {
+ if (interpolation.object_id[o] == render_item_object_info->u.info.id)
+ break;
+ }
+ if (o < interpolation.object_count) {
+ x[i] += interpolation.object_offset_east[o];
+ y[i] += interpolation.object_offset_height[o];
+ z[i] += interpolation.object_offset_north[o];
+ }
+ }
+ /* flatten polygon into shadow */
+ x[i] += y[i] * shadow_x;
+ z[i] += y[i] * shadow_z;
+ y[i] = 0.0;
+ /* apply interpolation */
+ x[i] -= interpolation.offset_east;
+ y[i] -= interpolation.offset_height;
+ z[i] -= interpolation.offset_north;
+ /* apply position */
+ x[i] += render_item->u.shadow_polygon.x_pos;
+ y[i] += render_item->u.shadow_polygon.y_pos;
+ z[i] += render_item->u.shadow_polygon.z_pos;
+ /* rotate vertex */
+ rotate_coordinate(roll, pitch, yaw, &x[i], &y[i], &z[i]);
+ }
+ /* render */
+ opengl_render_polygon(x, y, z, render_item->u.shadow_polygon.vertices, 0); /* no back face culling */
+ }
+ if (render_item->type == RENDER_ITEM_SHADOW_BUILDING_LINE
+ || render_item->type == RENDER_ITEM_SHADOW_OBJECT_LINE) {
+ /* get and rotate vertex */
+ for (i = 0; i < 2; i++) {
+ x[i] = render_item->u.shadow_line.x[i];
+ y[i] = render_item->u.shadow_line.y[i];
+ z[i] = render_item->u.shadow_line.z[i];
+ /* interpolate motion, if object is moving */
+ if (render_item->type == RENDER_ITEM_SHADOW_OBJECT_LINE && render_item_object_info && render_item_object_info->u.info.moving) {
+ for (o = 0; o < interpolation.object_count; o++) {
+ if (interpolation.object_id[o] == render_item_object_info->u.info.id)
+ break;
+ }
+ if (o < interpolation.object_count) {
+ x[i] += interpolation.object_offset_east[o];
+ y[i] += interpolation.object_offset_height[o];
+ z[i] += interpolation.object_offset_north[o];
+ }
+ }
+ /* flatten polygon into shadow */
+ x[i] += y[i] * shadow_x;
+ z[i] += y[i] * shadow_z;
+ y[i] = 0.0;
+ /* apply interpolation */
+ x[i] -= interpolation.offset_east;
+ y[i] -= interpolation.offset_height;
+ z[i] -= interpolation.offset_north;
+ /* apply position */
+ x[i] += render_item->u.shadow_line.x_pos;
+ y[i] += render_item->u.shadow_line.y_pos;
+ z[i] += render_item->u.shadow_line.z_pos;
+ /* 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;
+ }
default:
print_info("Unknown render item type, please fix!\n");
}
if (!render_list_new)
return -1;
+ sun_valid = 0;
+ stars_bright = 1.0;
+
+ for (render_item = render_list_new; render_item; render_item = render_item->next) {
+ render_one_item(render_item, vr, RENDER_BEFORE_SHADOW);
+ }
+ if (draw_shadows && ground_index >= 0) {
+ begin_shadow_render();
+ for (render_item = render_list_new; render_item; render_item = render_item->next) {
+ render_one_item(render_item, vr, RENDER_AT_SHADOW);
+ }
+ end_shadow_render();
+ }
for (render_item = render_list_new; render_item; render_item = render_item->next) {
- render_one_item(render_item, vr);
+ render_one_item(render_item, vr, RENDER_AFTER_SHADOW);
}
return 0;
sky_item.u.ground.green = 1.0;
sky_item.u.ground.blue = 1.0;
- render_one_item(&sky_item, vr);
+ render_one_item(&sky_item, vr, RENDER_BEFORE_SHADOW);
return 0;
}