summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/tile_type.h2
-rw-r--r--src/vehicle.cpp47
2 files changed, 37 insertions, 12 deletions
diff --git a/src/tile_type.h b/src/tile_type.h
index 0d720925d..eb5e8234c 100644
--- a/src/tile_type.h
+++ b/src/tile_type.h
@@ -18,6 +18,8 @@ static const uint TILE_PIXELS = 32; ///< Pixel distan
static const uint TILE_HEIGHT = 8; ///< Height of a height level in world coordinate AND in pixels in #ZOOM_LVL_BASE.
static const uint MAX_BUILDING_PIXELS = 200; ///< Maximum height of a building in pixels in #ZOOM_LVL_BASE. (Also applies to "bridge buildings" on the bridge floor.)
+static const int MAX_VEHICLE_PIXEL_X = 70; ///< Maximum width of a vehicle in pixels in #ZOOM_LVL_BASE.
+static const int MAX_VEHICLE_PIXEL_Y = 70; ///< Maximum height of a vehicle in pixels in #ZOOM_LVL_BASE.
static const uint MAX_TILE_HEIGHT = 255; ///< Maximum allowed tile height
diff --git a/src/vehicle.cpp b/src/vehicle.cpp
index e4a8c7bf1..be11e05be 100644
--- a/src/vehicle.cpp
+++ b/src/vehicle.cpp
@@ -57,7 +57,30 @@
#include "safeguards.h"
-#define GEN_HASH(x, y) ((GB((y), 6 + ZOOM_LVL_SHIFT, 6) << 6) + GB((x), 7 + ZOOM_LVL_SHIFT, 6))
+/* Number of bits in the hash to use from each vehicle coord */
+static const uint GEN_HASHX_BITS = 6;
+static const uint GEN_HASHY_BITS = 6;
+
+/* Size of each hash bucket */
+static const uint GEN_HASHX_BUCKET_BITS = 7;
+static const uint GEN_HASHY_BUCKET_BITS = 6;
+
+/* Compute hash for vehicle coord */
+#define GEN_HASHX(x) GB((x), GEN_HASHX_BUCKET_BITS + ZOOM_LVL_SHIFT, GEN_HASHX_BITS)
+#define GEN_HASHY(y) (GB((y), GEN_HASHY_BUCKET_BITS + ZOOM_LVL_SHIFT, GEN_HASHY_BITS) << GEN_HASHX_BITS)
+#define GEN_HASH(x, y) (GEN_HASHY(y) + GEN_HASHX(x))
+
+/* Maximum size until hash repeats */
+static const int GEN_HASHX_SIZE = 1 << (GEN_HASHX_BUCKET_BITS + GEN_HASHX_BITS + ZOOM_LVL_SHIFT);
+static const int GEN_HASHY_SIZE = 1 << (GEN_HASHY_BUCKET_BITS + GEN_HASHY_BITS + ZOOM_LVL_SHIFT);
+
+/* Increments to reach next bucket in hash table */
+static const int GEN_HASHX_INC = 1;
+static const int GEN_HASHY_INC = 1 << GEN_HASHX_BITS;
+
+/* Mask to wrap-around buckets */
+static const uint GEN_HASHX_MASK = (1 << GEN_HASHX_BITS) - 1;
+static const uint GEN_HASHY_MASK = ((1 << GEN_HASHY_BITS) - 1) << GEN_HASHX_BITS;
VehicleID _new_vehicle_id;
uint16 _returned_refit_capacity; ///< Stores the capacity after a refit operation.
@@ -618,7 +641,7 @@ static void UpdateVehicleTileHash(Vehicle *v, bool remove)
v->hash_tile_current = new_hash;
}
-static Vehicle *_vehicle_viewport_hash[0x1000];
+static Vehicle *_vehicle_viewport_hash[1 << (GEN_HASHX_BITS + GEN_HASHY_BITS)];
static void UpdateVehicleViewportHash(Vehicle *v, int x, int y)
{
@@ -1088,26 +1111,26 @@ void ViewportAddVehicles(DrawPixelInfo *dpi)
/* The hash area to scan */
int xl, xu, yl, yu;
- if (dpi->width + (70 * ZOOM_LVL_BASE) < (1 << (7 + 6 + ZOOM_LVL_SHIFT))) {
- xl = GB(l - (70 * ZOOM_LVL_BASE), 7 + ZOOM_LVL_SHIFT, 6);
- xu = GB(r, 7 + ZOOM_LVL_SHIFT, 6);
+ if (dpi->width + (MAX_VEHICLE_PIXEL_X * ZOOM_LVL_BASE) < GEN_HASHX_SIZE) {
+ xl = GEN_HASHX(l - MAX_VEHICLE_PIXEL_X * ZOOM_LVL_BASE);
+ xu = GEN_HASHX(r);
} else {
/* scan whole hash row */
xl = 0;
- xu = 0x3F;
+ xu = GEN_HASHX_MASK;
}
- if (dpi->height + (70 * ZOOM_LVL_BASE) < (1 << (6 + 6 + ZOOM_LVL_SHIFT))) {
- yl = GB(t - (70 * ZOOM_LVL_BASE), 6 + ZOOM_LVL_SHIFT, 6) << 6;
- yu = GB(b, 6 + ZOOM_LVL_SHIFT, 6) << 6;
+ if (dpi->height + (MAX_VEHICLE_PIXEL_Y * ZOOM_LVL_BASE) < GEN_HASHY_SIZE) {
+ yl = GEN_HASHY(t - MAX_VEHICLE_PIXEL_Y * ZOOM_LVL_BASE);
+ yu = GEN_HASHY(b);
} else {
/* scan whole column */
yl = 0;
- yu = 0x3F << 6;
+ yu = GEN_HASHY_MASK;
}
- for (int y = yl;; y = (y + (1 << 6)) & (0x3F << 6)) {
- for (int x = xl;; x = (x + 1) & 0x3F) {
+ for (int y = yl;; y = (y + GEN_HASHY_INC) & GEN_HASHY_MASK) {
+ for (int x = xl;; x = (x + GEN_HASHX_INC) & GEN_HASHX_MASK) {
const Vehicle *v = _vehicle_viewport_hash[x + y]; // already masked & 0xFFF
while (v != NULL) {