From 0b12076f2f8760aa4f136b996296ee943577c634 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=CE=B6eh=20Matt?= <5415177+ZehMatt@users.noreply.github.com> Date: Fri, 10 Sep 2021 17:19:30 +0300 Subject: [PATCH] Fix #15390: Revert quadrant distribution change and cleanup --- src/openrct2/paint/Paint.cpp | 42 +++++++++++++++++++++++------------- src/openrct2/paint/Paint.h | 9 ++++---- 2 files changed, 32 insertions(+), 19 deletions(-) diff --git a/src/openrct2/paint/Paint.cpp b/src/openrct2/paint/Paint.cpp index 6d64b750c2..96d662fcd8 100644 --- a/src/openrct2/paint/Paint.cpp +++ b/src/openrct2/paint/Paint.cpp @@ -56,27 +56,39 @@ static void PaintPSImageWithBoundingBoxes(rct_drawpixelinfo* dpi, paint_struct* static void PaintPSImage(rct_drawpixelinfo* dpi, paint_struct* ps, uint32_t imageId, int32_t x, int32_t y); static uint32_t PaintPSColourifyImage(uint32_t imageId, ViewportInteractionItem spriteType, uint32_t viewFlags); -static constexpr int32_t _PositionHashExtendsX[] = { - -0x2000, - 0x2000, - 0x4000, - 0x2000, -}; - -static constexpr uint32_t CalculatePositionHash(const paint_struct& ps, uint8_t rotation) +static int32_t RemapPositionToQuadrant(const paint_struct& ps, uint8_t rotation) { - auto pos = CoordsXY{ ps.bounds.x, ps.bounds.y }.Rotate(rotation); + constexpr auto MapRangeMax = MaxPaintQuadrants * COORDS_XY_STEP; + constexpr auto MapRangeCenter = MapRangeMax / 2; - // For corners to fall into the right buckets this extends the X axis. - pos.x += _PositionHashExtendsX[rotation]; - - return static_cast(pos.x + pos.y); + const auto x = ps.bounds.x; + const auto y = ps.bounds.y; + // NOTE: We are not calling CoordsXY::Rotate on purpose to mix in the additional + // value without a secondary switch. + switch (rotation & 3) + { + case 0: + return x + y; + case 1: + // Because one component may be the maximum we add the center to be a positive value. + return (y - x) + MapRangeCenter; + case 2: + // If both components would be the maximum it would be the negative xy, to be positive add max. + return (-(y + x)) + MapRangeMax; + case 3: + // Same as 1 but inverted. + return (x - y) + MapRangeCenter; + } + return 0; } static void PaintSessionAddPSToQuadrant(paint_session* session, paint_struct* ps) { - auto positionHash = CalculatePositionHash(*ps, session->CurrentRotation); - uint32_t paintQuadrantIndex = (positionHash / 32) % MAX_PAINT_QUADRANTS; + const auto positionHash = RemapPositionToQuadrant(*ps, session->CurrentRotation); + + // Values below zero or above MaxPaintQuadrants are void, corners also share the same quadrant as void. + const uint32_t paintQuadrantIndex = std::clamp(positionHash / COORDS_XY_STEP, 0, MaxPaintQuadrants); + ps->quadrant_index = paintQuadrantIndex; ps->next_quadrant_ps = session->Quadrants[paintQuadrantIndex]; session->Quadrants[paintQuadrantIndex] = ps; diff --git a/src/openrct2/paint/Paint.h b/src/openrct2/paint/Paint.h index 596208bfea..974b73f786 100644 --- a/src/openrct2/paint/Paint.h +++ b/src/openrct2/paint/Paint.h @@ -14,6 +14,7 @@ #include "../drawing/Drawing.h" #include "../interface/Colour.h" #include "../world/Location.hpp" +#include "../world/Map.h" #include #include @@ -113,9 +114,9 @@ struct tunnel_entry uint8_t type; }; -// NOTE: This should be preferably a prime number. This is the amount of -// buckets used with the position hash, so the bucket is hash % max. -#define MAX_PAINT_QUADRANTS 521 +// The maximum size must be MAXIMUM_MAP_SIZE_TECHNICAL multiplied by 2 because +// the quadrant index is based on the x and y components combined. +static constexpr int32_t MaxPaintQuadrants = MAXIMUM_MAP_SIZE_TECHNICAL * 2; #define TUNNEL_MAX_COUNT 65 @@ -171,7 +172,7 @@ public: struct PaintSessionCore { - paint_struct* Quadrants[MAX_PAINT_QUADRANTS]; + paint_struct* Quadrants[MaxPaintQuadrants]; paint_struct* LastPS; paint_string_struct* PSStringHead; paint_string_struct* LastPSString;