mirror of
https://github.com/OpenRCT2/OpenRCT2
synced 2026-01-15 11:03:00 +01:00
Optimise the algorithm for virtual floor invalidation.
This commit is contained in:
committed by
Aaron van Geffen
parent
ba1d269227
commit
c8328610ee
@@ -28,7 +28,14 @@ static uint16 _virtualFloorBaseSize = 5 * 32;
|
||||
static uint16 _virtualFloorHeight = 0;
|
||||
static LocationXYZ16 _virtualFloorLastMinPos;
|
||||
static LocationXYZ16 _virtualFloorLastMaxPos;
|
||||
static bool _virtualFloorVisible = false;
|
||||
static uint32 _virtualFloorFlags = 0;
|
||||
|
||||
enum VirtualFloorFlags
|
||||
{
|
||||
VIRTUAL_FLOOR_FLAG_NONE = 0,
|
||||
VIRTUAL_FLOOR_FLAG_ENABLED = (1 << 1),
|
||||
VIRTUAL_FLOOR_FORCE_INVALIDATION = (1 << 2),
|
||||
};
|
||||
|
||||
static constexpr const CoordsXY offsets[4] =
|
||||
{
|
||||
@@ -38,11 +45,15 @@ static constexpr const CoordsXY offsets[4] =
|
||||
{ 0, -32 }
|
||||
};
|
||||
|
||||
bool virtual_floor_is_enabled()
|
||||
{
|
||||
return (_virtualFloorFlags & VIRTUAL_FLOOR_FLAG_ENABLED) != 0;
|
||||
}
|
||||
|
||||
void virtual_floor_set_height(sint16 height)
|
||||
{
|
||||
if (!_virtualFloorVisible)
|
||||
if (virtual_floor_is_enabled())
|
||||
{
|
||||
// If the modifiers are not set we do not actually care as the floor is invisible.
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -53,51 +64,55 @@ void virtual_floor_set_height(sint16 height)
|
||||
}
|
||||
}
|
||||
|
||||
static void virtual_floor_reset()
|
||||
{
|
||||
_virtualFloorLastMinPos.x = std::numeric_limits<sint16>::max();
|
||||
_virtualFloorLastMinPos.y = std::numeric_limits<sint16>::max();
|
||||
_virtualFloorLastMaxPos.x = std::numeric_limits<sint16>::lowest();
|
||||
_virtualFloorLastMaxPos.y = std::numeric_limits<sint16>::lowest();
|
||||
_virtualFloorHeight = 0;
|
||||
}
|
||||
|
||||
void virtual_floor_enable()
|
||||
{
|
||||
if (_virtualFloorVisible)
|
||||
if (virtual_floor_is_enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Force invalidation on the next draw.
|
||||
_virtualFloorLastMinPos.z = std::numeric_limits<sint16>::max();
|
||||
_virtualFloorLastMaxPos.z = std::numeric_limits<sint16>::lowest();
|
||||
_virtualFloorVisible = true;
|
||||
virtual_floor_reset();
|
||||
_virtualFloorFlags |= VIRTUAL_FLOOR_FLAG_ENABLED;
|
||||
}
|
||||
|
||||
void virtual_floor_disable()
|
||||
{
|
||||
if (!_virtualFloorVisible)
|
||||
if (!virtual_floor_is_enabled())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Force invalidation, even if the position hasn't changed.
|
||||
_virtualFloorLastMinPos.z = std::numeric_limits<sint16>::max();
|
||||
_virtualFloorLastMaxPos.z = std::numeric_limits<sint16>::lowest();
|
||||
virtual_floor_invalidate();
|
||||
_virtualFloorFlags &= ~VIRTUAL_FLOOR_FLAG_ENABLED;
|
||||
|
||||
_virtualFloorHeight = 0;
|
||||
_virtualFloorVisible = false;
|
||||
// Force invalidation, even if the position hasn't changed.
|
||||
_virtualFloorFlags |= VIRTUAL_FLOOR_FORCE_INVALIDATION;
|
||||
virtual_floor_invalidate();
|
||||
_virtualFloorFlags &= ~VIRTUAL_FLOOR_FORCE_INVALIDATION;
|
||||
|
||||
virtual_floor_reset();
|
||||
}
|
||||
|
||||
void virtual_floor_invalidate()
|
||||
{
|
||||
if (!_virtualFloorVisible)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// First, let's figure out how big our selection is.
|
||||
LocationXY16 min_position = { std::numeric_limits<sint16>::max(), std::numeric_limits<sint16>::max() };
|
||||
LocationXY16 min_position = { std::numeric_limits<sint16>::max(), std::numeric_limits<sint16>::max() };
|
||||
LocationXY16 max_position = { std::numeric_limits<sint16>::lowest(), std::numeric_limits<sint16>::lowest() };
|
||||
|
||||
if ((gMapSelectFlags & MAP_SELECT_FLAG_ENABLE))
|
||||
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE)
|
||||
{
|
||||
min_position = gMapSelectPositionA;
|
||||
max_position = gMapSelectPositionB;
|
||||
min_position = gMapSelectPositionA;
|
||||
max_position = gMapSelectPositionB;
|
||||
}
|
||||
|
||||
if (gMapSelectFlags & MAP_SELECT_FLAG_ENABLE_CONSTRUCT)
|
||||
{
|
||||
for (LocationXY16 * tile = gMapSelectionTiles; tile->x != -1; tile++)
|
||||
@@ -110,12 +125,33 @@ void virtual_floor_invalidate()
|
||||
}
|
||||
|
||||
// Apply the virtual floor size to the computed invalidation area.
|
||||
min_position.x -= _virtualFloorBaseSize + 1;
|
||||
min_position.y -= _virtualFloorBaseSize + 1;
|
||||
max_position.x += _virtualFloorBaseSize + 1;
|
||||
max_position.y += _virtualFloorBaseSize + 1;
|
||||
min_position.x -= _virtualFloorBaseSize + 16;
|
||||
min_position.y -= _virtualFloorBaseSize + 16;
|
||||
max_position.x += _virtualFloorBaseSize + 16;
|
||||
max_position.y += _virtualFloorBaseSize + 16;
|
||||
|
||||
// Do not invalidate if floor hasn't moved.
|
||||
// Invalidate previous region if appropriate.
|
||||
if (_virtualFloorLastMinPos.x != std::numeric_limits<sint16>::max() &&
|
||||
_virtualFloorLastMinPos.y != std::numeric_limits<sint16>::max() &&
|
||||
_virtualFloorLastMaxPos.x != std::numeric_limits<sint16>::lowest() &&
|
||||
_virtualFloorLastMaxPos.y != std::numeric_limits<sint16>::lowest())
|
||||
{
|
||||
LocationXY16 prevMins = { _virtualFloorLastMinPos.x, _virtualFloorLastMinPos.y };
|
||||
LocationXY16 prevMaxs = { _virtualFloorLastMaxPos.x, _virtualFloorLastMaxPos.y };
|
||||
|
||||
if (prevMins.x != min_position.x ||
|
||||
prevMins.y != min_position.y ||
|
||||
prevMaxs.x != max_position.x ||
|
||||
prevMaxs.y != max_position.y ||
|
||||
(_virtualFloorFlags & VIRTUAL_FLOOR_FORCE_INVALIDATION) != 0)
|
||||
{
|
||||
log_verbose("Invalidating previous region, Min: %d %d, Max: %d %d",
|
||||
prevMins.x, prevMins.y, prevMaxs.x, prevMaxs.y);
|
||||
map_invalidate_region(prevMins, prevMaxs);
|
||||
}
|
||||
}
|
||||
|
||||
// Do not invalidate new region if floor hasn't moved.
|
||||
if (_virtualFloorLastMinPos.x == min_position.x &&
|
||||
_virtualFloorLastMinPos.y == min_position.y &&
|
||||
_virtualFloorLastMinPos.z == _virtualFloorHeight)
|
||||
@@ -123,40 +159,35 @@ void virtual_floor_invalidate()
|
||||
return;
|
||||
}
|
||||
|
||||
LocationXY16 corr_min_position = min_position;
|
||||
LocationXY16 corr_max_position = max_position;
|
||||
|
||||
// Invalidate previous locations, too, if appropriate.
|
||||
if (_virtualFloorLastMinPos.z != std::numeric_limits<sint16>::max() &&
|
||||
_virtualFloorLastMaxPos.z != std::numeric_limits<sint16>::lowest())
|
||||
if (!(_virtualFloorFlags & VIRTUAL_FLOOR_FLAG_ENABLED))
|
||||
{
|
||||
corr_min_position.x = std::min(min_position.x, _virtualFloorLastMinPos.x);
|
||||
corr_min_position.y = std::min(min_position.y, _virtualFloorLastMinPos.y);
|
||||
corr_max_position.x = std::max(max_position.x, _virtualFloorLastMaxPos.x);
|
||||
corr_max_position.y = std::max(max_position.y, _virtualFloorLastMaxPos.y);
|
||||
return;
|
||||
}
|
||||
|
||||
for (sint16 x = corr_min_position.x; x < corr_max_position.x; x++)
|
||||
log_verbose("Min: %d %d, Max: %d %d\n", min_position.x, min_position.y, max_position.x, max_position.y);
|
||||
|
||||
// Invalidate new region if coordinates are set.
|
||||
if (min_position.x != std::numeric_limits<sint16>::max() &&
|
||||
min_position.y != std::numeric_limits<sint16>::max() &&
|
||||
max_position.x != std::numeric_limits<sint16>::lowest() &&
|
||||
max_position.y != std::numeric_limits<sint16>::lowest())
|
||||
{
|
||||
for (sint16 y = corr_min_position.y; y < corr_max_position.y; y++)
|
||||
{
|
||||
map_invalidate_tile_full(x, y);
|
||||
}
|
||||
map_invalidate_region(min_position, max_position);
|
||||
|
||||
// Save minimal and maximal positions.
|
||||
_virtualFloorLastMinPos.x = min_position.x;
|
||||
_virtualFloorLastMinPos.y = min_position.y;
|
||||
_virtualFloorLastMinPos.z = _virtualFloorHeight;
|
||||
|
||||
_virtualFloorLastMaxPos.x = max_position.x;
|
||||
_virtualFloorLastMaxPos.y = max_position.y;
|
||||
_virtualFloorLastMaxPos.z = _virtualFloorHeight;
|
||||
}
|
||||
|
||||
// Save minimal and maximal positions. Note: not their corrected positions!
|
||||
_virtualFloorLastMinPos.x = min_position.x;
|
||||
_virtualFloorLastMinPos.y = min_position.y;
|
||||
_virtualFloorLastMinPos.z = _virtualFloorHeight;
|
||||
|
||||
_virtualFloorLastMaxPos.x = max_position.x;
|
||||
_virtualFloorLastMaxPos.y = max_position.y;
|
||||
_virtualFloorLastMaxPos.z = _virtualFloorHeight;
|
||||
}
|
||||
|
||||
bool virtual_floor_tile_is_floor(sint16 x, sint16 y)
|
||||
{
|
||||
if (!_virtualFloorVisible)
|
||||
if (!virtual_floor_is_enabled())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -150,11 +150,11 @@ money32 place_provisional_track_piece(sint32 rideIndex, sint32 trackType, sint32
|
||||
if (_currentTrackSlopeEnd != 0)
|
||||
viewport_set_visibility(2);
|
||||
|
||||
// Invalidate previous track piece (we may not be changing height!)
|
||||
virtual_floor_invalidate();
|
||||
|
||||
if (!scenery_tool_is_active())
|
||||
{
|
||||
// Invalidate previous track piece (we may not be changing height!)
|
||||
virtual_floor_invalidate();
|
||||
|
||||
// Set new virtual floor height.
|
||||
virtual_floor_set_height(z);
|
||||
}
|
||||
@@ -188,11 +188,11 @@ money32 place_provisional_track_piece(sint32 rideIndex, sint32 trackType, sint32
|
||||
if (_currentTrackSlopeEnd != 0)
|
||||
viewport_set_visibility(2);
|
||||
|
||||
// Invalidate previous track piece (we may not be changing height!)
|
||||
virtual_floor_invalidate();
|
||||
|
||||
if (!scenery_tool_is_active())
|
||||
{
|
||||
// Invalidate previous track piece (we may not be changing height!)
|
||||
virtual_floor_invalidate();
|
||||
|
||||
// Set height to where the next track piece would begin
|
||||
virtual_floor_set_height(z - z_begin + z_end);
|
||||
}
|
||||
|
||||
@@ -4130,6 +4130,33 @@ void map_invalidate_element(sint32 x, sint32 y, rct_tile_element *tileElement)
|
||||
map_invalidate_tile(x, y, tileElement->base_height * 8, tileElement->clearance_height * 8);
|
||||
}
|
||||
|
||||
void map_invalidate_region(const LocationXY16& mins, const LocationXY16& maxs)
|
||||
{
|
||||
sint32 x0, y0, x1, y1, left, right, top, bottom;
|
||||
|
||||
x0 = mins.x + 16;
|
||||
y0 = mins.y + 16;
|
||||
|
||||
x1 = maxs.x + 16;
|
||||
y1 = maxs.y + 16;
|
||||
|
||||
map_get_bounding_box(x0, y0, x1, y1, &left, &top, &right, &bottom);
|
||||
|
||||
left -= 32;
|
||||
right += 32;
|
||||
bottom += 32;
|
||||
top -= 32 + 2080;
|
||||
|
||||
for (sint32 i = 0; i < MAX_VIEWPORT_COUNT; i++)
|
||||
{
|
||||
rct_viewport *viewport = &g_viewport_list[i];
|
||||
if (viewport->width != 0)
|
||||
{
|
||||
viewport_invalidate(viewport, left, top, right, bottom);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sint32 map_get_tile_side(sint32 mapX, sint32 mapY)
|
||||
{
|
||||
sint32 subMapX = mapX & (32 - 1);
|
||||
|
||||
@@ -538,6 +538,7 @@ void map_invalidate_tile_zoom1(sint32 x, sint32 y, sint32 z0, sint32 z1);
|
||||
void map_invalidate_tile_zoom0(sint32 x, sint32 y, sint32 z0, sint32 z1);
|
||||
void map_invalidate_tile_full(sint32 x, sint32 y);
|
||||
void map_invalidate_element(sint32 x, sint32 y, rct_tile_element *tileElement);
|
||||
void map_invalidate_region(const LocationXY16& mins, const LocationXY16& maxs);
|
||||
|
||||
sint32 map_get_tile_side(sint32 mapX, sint32 mapY);
|
||||
sint32 map_get_tile_quadrant(sint32 mapX, sint32 mapY);
|
||||
|
||||
Reference in New Issue
Block a user