changeset 1934:8ddd063bde66 draft

(svn r2440) - Fix: [newgrf] Fix the spritesorter to handle overlapping sprites properly, this fixes display problems with really short wagons. (algorithm by patchman, ported by therax) - Fix: [newgrf] Too short wagons could break the 'follow next vehicle' code used in the traincontroller. Clamp better to prevent this.
author hackykid <hackykid@openttd.org>
date Wed, 15 Jun 2005 14:04:48 +0000
parents 8bb890fcb745
children a3a3955723dc
files train_cmd.c viewport.c
diffstat 2 files changed, 29 insertions(+), 8 deletions(-) [+]
line wrap: on
line diff
--- a/train_cmd.c
+++ b/train_cmd.c
@@ -119,7 +119,7 @@
 			veh_len = GetCallBackResult(CBID_VEH_LENGTH,  u->engine_type, u);
 		if (veh_len == CALLBACK_FAILED)
 			veh_len = rvi_u->shorten_factor;
-		veh_len = clamp(veh_len, 0, 7);
+		veh_len = clamp(veh_len, 0, u->next == NULL ? 7 : 5); // the clamp on vehicles not the last in chain is stricter, as too short wagons can break the 'follow next vehicle' code
 		u->u.rail.cached_veh_length = 8 - veh_len;
 
 	};
--- a/viewport.c
+++ b/viewport.c
@@ -1079,16 +1079,37 @@
 			psd2 = psd;
 
 			while ( (ps2=*++psd2) != NULL) {
+				bool mustswap = false;
+
 				if (ps2->unk16 & 1)
 					continue;
 
-				if (ps->tile_right >= ps2->tile_x &&
-						ps->tile_bottom >= ps2->tile_y &&
-						ps->tile_z_bottom >= ps2->tile_z && (
-						ps->tile_x >= ps2->tile_right ||
-						ps->tile_y >= ps2->tile_bottom ||
-						ps->tile_z >= ps2->tile_z_bottom
-						)) {
+				// Decide which sort order algorithm to use, based on whether the sprites have some overlapping area.
+				if (((ps2->tile_x > ps->tile_x && ps2->tile_x < ps->tile_right) ||
+				    (ps2->tile_right > ps->tile_x && ps2->tile_x < ps->tile_right)) &&        // overlap in X
+				    ((ps2->tile_y > ps->tile_y && ps2->tile_y < ps->tile_bottom) ||
+				    (ps2->tile_bottom > ps->tile_y && ps2->tile_y < ps->tile_bottom)) &&      // overlap in Y
+				    ((ps2->tile_z > ps->tile_z && ps2->tile_z < ps->tile_z_bottom) ||
+				    (ps2->tile_z_bottom > ps->tile_z && ps2->tile_z < ps->tile_z_bottom)) ) { // overlap in Z
+					// Sprites overlap.
+					// Use X+Y+Z as the sorting order, so sprites nearer the bottom of the screen,
+					// and with higher Z elevation, draw in front.
+					// Here X,Y,Z are the coordinates of the "center of mass" of the sprite,
+					// i.e. X=(left+right)/2, etc.
+					// However, since we only care about order, don't actually calculate the division / 2.
+					mustswap = ps->tile_x + ps->tile_right + ps->tile_y + ps->tile_bottom + ps->tile_z + ps->tile_z_bottom >
+					           ps2->tile_x + ps2->tile_right + ps2->tile_y + ps2->tile_bottom + ps2->tile_z + ps2->tile_z_bottom;
+				} else {
+					// No overlap; use the original TTD sort algorithm.
+					mustswap = (ps->tile_right >= ps2->tile_x &&
+					            ps->tile_bottom >= ps2->tile_y &&
+					            ps->tile_z_bottom >= ps2->tile_z &&
+					           (ps->tile_x >= ps2->tile_right ||
+					            ps->tile_y >= ps2->tile_bottom ||
+					            ps->tile_z >= ps2->tile_z_bottom));
+				}
+				if (mustswap) {
+					// Swap the two sprites ps and ps2 using bubble-sort algorithm.
 					psd3 = psd;
 					do {
 						ps3 = *psd3;