From 3864902683188eaf75a8b418f5e2ab6597db9224 Mon Sep 17 00:00:00 2001 From: Peter Nelson Date: Wed, 3 Jan 2024 18:36:34 +0000 Subject: [PATCH] Codechange: Use vehicle viewport hash to find clicked vehicle. (#11675) This avoids having to iterate all vehicles, which can be an performance improvement when there are many vehicles. --- src/vehicle.cpp | 41 ++++++++++++++++++++++++++++++----------- 1 file changed, 30 insertions(+), 11 deletions(-) diff --git a/src/vehicle.cpp b/src/vehicle.cpp index 386b956b4f..a202aa0cb3 100644 --- a/src/vehicle.cpp +++ b/src/vehicle.cpp @@ -1222,21 +1222,40 @@ Vehicle *CheckClickOnVehicle(const Viewport *vp, int x, int y) x = ScaleByZoom(x, vp->zoom) + vp->virtual_left; y = ScaleByZoom(y, vp->zoom) + vp->virtual_top; - for (Vehicle *v : Vehicle::Iterate()) { - if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 && - x >= v->coord.left && x <= v->coord.right && - y >= v->coord.top && y <= v->coord.bottom) { + /* Border size of MAX_VEHICLE_PIXEL_xy */ + const int xb = MAX_VEHICLE_PIXEL_X * ZOOM_LVL_BASE; + const int yb = MAX_VEHICLE_PIXEL_Y * ZOOM_LVL_BASE; - dist = std::max( - abs(((v->coord.left + v->coord.right) >> 1) - x), - abs(((v->coord.top + v->coord.bottom) >> 1) - y) - ); + /* The hash area to scan */ + int xl = GEN_HASHX(x - xb); + int xu = GEN_HASHX(x); + int yl = GEN_HASHY(y - yb); + int yu = GEN_HASHY(y); - if (dist < best_dist) { - found = v; - best_dist = dist; + for (int hy = yl;; hy = (hy + GEN_HASHY_INC) & GEN_HASHY_MASK) { + for (int hx = xl;; hx = (hx + GEN_HASHX_INC) & GEN_HASHX_MASK) { + Vehicle *v = _vehicle_viewport_hash[hx + hy]; // already masked & 0xFFF + + while (v != nullptr) { + if ((v->vehstatus & (VS_HIDDEN | VS_UNCLICKABLE)) == 0 && + x >= v->coord.left && x <= v->coord.right && + y >= v->coord.top && y <= v->coord.bottom) { + + dist = std::max( + abs(((v->coord.left + v->coord.right) >> 1) - x), + abs(((v->coord.top + v->coord.bottom) >> 1) - y) + ); + + if (dist < best_dist) { + found = v; + best_dist = dist; + } + } + v = v->hash_viewport_next; } + if (hx == xu) break; } + if (hy == yu) break; } return found;