Speed up Map.Contains checks for non-flat maps.
We observe that most cells within a map lie within a region where no matter their height, their projection would still remain in map bounds. We can utilise this to perform a fast check for such cells and skipping the expensive checks on their actual height. We only need to check the actual height of a cell if this could cause the projection to go out of bounds.
This commit is contained in:
committed by
Paul Chote
parent
d370cb48c5
commit
6f3b4ecae9
@@ -248,6 +248,7 @@ namespace OpenRA
|
|||||||
CellLayer<PPos[]> cellProjection;
|
CellLayer<PPos[]> cellProjection;
|
||||||
CellLayer<List<MPos>> inverseCellProjection;
|
CellLayer<List<MPos>> inverseCellProjection;
|
||||||
CellLayer<byte> projectedHeight;
|
CellLayer<byte> projectedHeight;
|
||||||
|
Rectangle projectionSafeBounds;
|
||||||
|
|
||||||
internal Translation Translation;
|
internal Translation Translation;
|
||||||
|
|
||||||
@@ -556,6 +557,7 @@ namespace OpenRA
|
|||||||
if (!mapHeight.Contains(uv))
|
if (!mapHeight.Contains(uv))
|
||||||
return NoProjectedCells;
|
return NoProjectedCells;
|
||||||
|
|
||||||
|
// Any changes to this function should be reflected when setting projectionSafeBounds.
|
||||||
var height = mapHeight[uv];
|
var height = mapHeight[uv];
|
||||||
if (height == 0)
|
if (height == 0)
|
||||||
return new[] { (PPos)uv };
|
return new[] { (PPos)uv };
|
||||||
@@ -838,6 +840,14 @@ namespace OpenRA
|
|||||||
if (Grid.MaximumTerrainHeight == 0)
|
if (Grid.MaximumTerrainHeight == 0)
|
||||||
return Bounds.Contains(uv.U, uv.V);
|
return Bounds.Contains(uv.U, uv.V);
|
||||||
|
|
||||||
|
// PERF: Most cells lie within a region where no matter their height,
|
||||||
|
// all possible projected cells would remain in the map area.
|
||||||
|
// For these, we can do a fast-path check.
|
||||||
|
if (projectionSafeBounds.Contains(uv.U, uv.V))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
// Now we need to do a slow-check. Determine the actual projected tiles
|
||||||
|
// as they may or may not be in bounds depending on height.
|
||||||
// If the cell has no valid projection, then we're off the map.
|
// If the cell has no valid projection, then we're off the map.
|
||||||
var projectedCells = ProjectedCellsCovering(uv);
|
var projectedCells = ProjectedCellsCovering(uv);
|
||||||
if (projectedCells.Length == 0)
|
if (projectedCells.Length == 0)
|
||||||
@@ -1029,6 +1039,22 @@ namespace OpenRA
|
|||||||
// is exclusive. Pad the right and bottom edges to match.
|
// is exclusive. Pad the right and bottom edges to match.
|
||||||
Bounds = Rectangle.FromLTRB(tl.U, tl.V, br.U + 1, br.V + 1);
|
Bounds = Rectangle.FromLTRB(tl.U, tl.V, br.U + 1, br.V + 1);
|
||||||
|
|
||||||
|
// See ProjectCellInner to see how any given position may be projected.
|
||||||
|
// U: May gain or lose 1, so bring in the left and right edge by 1.
|
||||||
|
// V: For an even height tile, this ranges from 0 to height
|
||||||
|
// For an odd tile, the height may get rounded up to next even.
|
||||||
|
// Then also it projects to four tiles which adds one more to the possible height change.
|
||||||
|
// So we get a range of 0 to height + 1 + 1.
|
||||||
|
// As the height only goes upwards, we only need to make room at the top of the map and not the bottom.
|
||||||
|
var maxHeight = Grid.MaximumTerrainHeight;
|
||||||
|
if ((maxHeight & 1) == 1)
|
||||||
|
maxHeight += 2;
|
||||||
|
projectionSafeBounds = Rectangle.FromLTRB(
|
||||||
|
Bounds.Left + 1,
|
||||||
|
Bounds.Top + maxHeight,
|
||||||
|
Bounds.Right - 1,
|
||||||
|
Bounds.Bottom);
|
||||||
|
|
||||||
// Directly calculate the projected map corners in world units avoiding unnecessary
|
// Directly calculate the projected map corners in world units avoiding unnecessary
|
||||||
// conversions. This abuses the definition that the width of the cell along the x world axis
|
// conversions. This abuses the definition that the width of the cell along the x world axis
|
||||||
// is always 1024 or 1448 units, and that the height of two rows is 2048 for classic cells and 724
|
// is always 1024 or 1448 units, and that the height of two rows is 2048 for classic cells and 724
|
||||||
|
|||||||
Reference in New Issue
Block a user