Merge pull request #8518 from pchote/renderbounds

Fix screen bounds calculations
This commit is contained in:
Oliver Brakmann
2015-06-21 15:01:16 +02:00
2 changed files with 41 additions and 33 deletions

View File

@@ -207,14 +207,13 @@ namespace OpenRA.Graphics
// Rectangle (in viewport coords) that contains things to be drawn // Rectangle (in viewport coords) that contains things to be drawn
static readonly Rectangle ScreenClip = Rectangle.FromLTRB(0, 0, Game.Renderer.Resolution.Width, Game.Renderer.Resolution.Height); static readonly Rectangle ScreenClip = Rectangle.FromLTRB(0, 0, Game.Renderer.Resolution.Width, Game.Renderer.Resolution.Height);
public Rectangle ScissorBounds public Rectangle GetScissorBounds(bool insideBounds)
{
get
{ {
// Visible rectangle in world coordinates (expanded to the corners of the cells) // Visible rectangle in world coordinates (expanded to the corners of the cells)
var bounds = insideBounds ? VisibleCellsInsideBounds : AllVisibleCells;
var map = worldRenderer.World.Map; var map = worldRenderer.World.Map;
var ctl = map.CenterOfCell(VisibleCellsInsideBounds.TopLeft) - new WVec(512, 512, 0); var ctl = map.CenterOfCell(bounds.TopLeft) - new WVec(512, 512, 0);
var cbr = map.CenterOfCell(VisibleCellsInsideBounds.BottomRight) + new WVec(512, 512, 0); var cbr = map.CenterOfCell(bounds.BottomRight) + new WVec(512, 512, 0);
// Convert to screen coordinates // Convert to screen coordinates
var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl - new WVec(0, 0, ctl.Z))).Clamp(ScreenClip); var tl = WorldToViewPx(worldRenderer.ScreenPxPosition(ctl - new WVec(0, 0, ctl.Z))).Clamp(ScreenClip);
@@ -224,35 +223,44 @@ namespace OpenRA.Graphics
return Rectangle.FromLTRB(tl.X - tileSize.Width, tl.Y - tileSize.Height, return Rectangle.FromLTRB(tl.X - tileSize.Width, tl.Y - tileSize.Height,
br.X + tileSize.Width, br.Y + tileSize.Height); br.X + tileSize.Width, br.Y + tileSize.Height);
} }
}
CellRegion CalculateVisibleCells(bool insideBounds) CellRegion CalculateVisibleCells(bool insideBounds)
{ {
var map = worldRenderer.World.Map; var map = worldRenderer.World.Map;
var wtl = worldRenderer.Position(TopLeft);
var wbr = worldRenderer.Position(BottomRight);
// Map editor shows the full map (including the area outside the regular bounds) // Calculate the viewport corners in "projected wpos" (at ground level), and
Func<MPos, MPos> clamp = map.Clamp; // this to an equivalent projected cell for the two corners
if (!insideBounds) var tl = map.CellContaining(worldRenderer.Position(TopLeft)).ToMPos(map);
clamp = map.MapTiles.Value.Clamp; var br = map.CellContaining(worldRenderer.Position(BottomRight)).ToMPos(map);
// Due to diamond tile staggering, we need to adjust the top-left bounds outwards by half a cell. // Diamond tile shapes don't have straight edges, and so we need
// an additional cell margin to include the cells that are half
// visible on each edge.
if (map.TileShape == TileShape.Diamond) if (map.TileShape == TileShape.Diamond)
wtl -= new WVec(512, 512, 0); {
tl = new MPos(tl.U - 1, tl.V - 1);
br = new MPos(br.U + 1, br.V + 1);
}
// Visible rectangle in map coordinates. // Clamp to the visible map bounds, if requested
var dy = map.TileShape == TileShape.Diamond ? 512 : 1024; if (insideBounds)
var ctl = new MPos(wtl.X / 1024, wtl.Y / dy); {
var cbr = new MPos(wbr.X / 1024, wbr.Y / dy); tl = map.Clamp(tl);
br = map.Clamp(br);
}
var tl = clamp(ctl).ToCPos(map.TileShape); // Cells can be pushed up from below if they have non-zero height.
// Each height step is equivalent to 512 WRange units, which is
// one MPos step for diamond cells, but only half a MPos step
// for classic cells. Doh!
var heightOffset = map.TileShape == TileShape.Diamond ? maxGroundHeight : maxGroundHeight / 2;
br = new MPos(br.U, br.V + heightOffset);
// Also need to account for height of cells in rows below the bottom. // Finally, make sure that this region doesn't extend outside the map area.
var heightPadding = map.TileShape == TileShape.Diamond ? 3 : 0; tl = map.MapHeight.Value.Clamp(tl);
var br = clamp(new MPos(cbr.U, cbr.V + heightPadding + maxGroundHeight / 2 + 1)).ToCPos(map.TileShape); br = map.MapHeight.Value.Clamp(br);
return new CellRegion(map.TileShape, tl, br); return new CellRegion(map.TileShape, tl.ToCPos(map), br.ToCPos(map));
} }
public CellRegion VisibleCellsInsideBounds public CellRegion VisibleCellsInsideBounds
@@ -261,7 +269,7 @@ namespace OpenRA.Graphics
{ {
if (cellsDirty) if (cellsDirty)
{ {
cells = CalculateVisibleCells(false); cells = CalculateVisibleCells(true);
cellsDirty = false; cellsDirty = false;
} }

View File

@@ -132,7 +132,7 @@ namespace OpenRA.Graphics
return; return;
var renderables = GenerateRenderables(); var renderables = GenerateRenderables();
var bounds = Viewport.ScissorBounds; var bounds = Viewport.GetScissorBounds(World.Type != WorldType.Editor);
Game.Renderer.EnableScissor(bounds); Game.Renderer.EnableScissor(bounds);
terrainRenderer.Draw(this, Viewport); terrainRenderer.Draw(this, Viewport);