Skip to content

Commit

Permalink
Account for ramps in terrain height calculations.
Browse files Browse the repository at this point in the history
  • Loading branch information
pchote committed May 3, 2020
1 parent 97d2b66 commit 8bc704a
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 17 deletions.
8 changes: 6 additions & 2 deletions OpenRA.Game/Graphics/TerrainSpriteLayer.cs
Expand Up @@ -68,8 +68,12 @@ void UpdatePaletteIndices()

public void Update(CPos cell, Sprite sprite)
{
var xyz = sprite == null ? float3.Zero :
worldRenderer.Screen3DPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size;
var xyz = float3.Zero;
if (sprite != null)
{
var cellOrigin = map.CenterOfCell(cell) - new WVec(0, 0, map.Grid.Ramps[map.Ramp[cell]].CenterHeightOffset);
xyz = worldRenderer.Screen3DPosition(cellOrigin) + sprite.Offset - 0.5f * sprite.Size;
}

Update(cell.ToMPos(map.Grid.Type), sprite, xyz);
}
Expand Down
8 changes: 3 additions & 5 deletions OpenRA.Game/Graphics/Viewport.cs
Expand Up @@ -260,11 +260,9 @@ public CPos ViewToWorld(int2 view)
var s = worldRenderer.ScreenPxPosition(p);
if (Math.Abs(s.X - world.X) <= tileSize.Width && Math.Abs(s.Y - world.Y) <= tileSize.Height)
{
var ramp = map.Ramp.Contains(uv) ? map.Ramp[uv] : 0;
var corners = map.Grid.Ramps[ramp].Corners;
var pos = map.CenterOfCell(uv.ToCPos(map));
var screen = corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();

var ramp = map.Grid.Ramps[map.Ramp.Contains(uv) ? map.Ramp[uv] : 0];
var pos = map.CenterOfCell(uv.ToCPos(map)) - new WVec(0, 0, ramp.CenterHeightOffset);
var screen = ramp.Corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
if (screen.PolygonContains(world))
return uv.ToCPos(map);
}
Expand Down
32 changes: 28 additions & 4 deletions OpenRA.Game/Map/Map.cs
Expand Up @@ -820,23 +820,47 @@ public WPos CenterOfCell(CPos cell)
// (c) u, v coordinates run diagonally to the cell axes, and we define
// 1024 as the length projected onto the primary cell axis
// - 512 * sqrt(2) = 724
var z = Height.Contains(cell) ? 724 * Height[cell] : 0;
var z = Height.Contains(cell) ? 724 * Height[cell] + Grid.Ramps[Ramp[cell]].CenterHeightOffset : 0;
return new WPos(724 * (cell.X - cell.Y + 1), 724 * (cell.X + cell.Y + 1), z);
}

public WPos CenterOfSubCell(CPos cell, SubCell subCell)
{
var index = (int)subCell;
if (index >= 0 && index < Grid.SubCellOffsets.Length)
return CenterOfCell(cell) + Grid.SubCellOffsets[index];
{
var center = CenterOfCell(cell);
var offset = Grid.SubCellOffsets[index];
var ramp = Ramp.Contains(cell) ? Ramp[cell] : 0;
if (ramp != 0)
{
var r = Grid.Ramps[ramp];
offset += new WVec(0, 0, r.HeightOffset(offset.X, offset.Y) - r.CenterHeightOffset);
}

return center + offset;
}

return CenterOfCell(cell);
}

public WDist DistanceAboveTerrain(WPos pos)
{
if (Grid.Type == MapGridType.Rectangular)
return new WDist(pos.Z);

// Apply ramp offset
var cell = CellContaining(pos);
var delta = pos - CenterOfCell(cell);
return new WDist(delta.Z);
var offset = pos - CenterOfCell(cell);

var ramp = Ramp[cell];
if (ramp != 0)
{
var r = Grid.Ramps[ramp];
return new WDist(offset.Z + r.CenterHeightOffset - r.HeightOffset(offset.X, offset.Y));
}

return new WDist(offset.Z);
}

public WVec Offset(CVec delta, int dz)
Expand Down
14 changes: 9 additions & 5 deletions OpenRA.Game/Map/MapGrid.cs
Expand Up @@ -24,6 +24,7 @@ public enum RampCornerHeight { Low = 0, Half = 1, Full = 2 }

public struct CellRamp
{
public readonly int CenterHeightOffset;
public readonly WVec[] Corners;
public readonly WVec[][] Polygons;

Expand Down Expand Up @@ -68,9 +69,13 @@ public CellRamp(MapGridType type, RampCornerHeight tl = RampCornerHeight.Low, Ra
}
else
Polygons = new[] { Corners };

// Initial value must be asigned before HeightOffset can be called
CenterHeightOffset = 0;
CenterHeightOffset = HeightOffset(0, 0);
}

public WDist DistanceAboveTerrain(WVec delta)
public int HeightOffset(int dX, int dY)
{
// Enumerate over the polygons, assuming that they are triangles
// If the ramp is not split we will take the first three vertices of the corners as a valid triangle
Expand All @@ -80,17 +85,16 @@ public WDist DistanceAboveTerrain(WVec delta)
for (var i = 0; i < Polygons.Length; i++)
{
p = Polygons[i];
u = ((p[1].Y - p[2].Y) * (delta.X - p[2].X) - (p[1].X - p[2].X) * (delta.Y - p[2].Y)) / 1024;
v = ((p[0].X - p[2].X) * (delta.Y - p[2].Y) - (p[0].Y - p[2].Y) * (delta.X - p[2].X)) / 1024;
u = ((p[1].Y - p[2].Y) * (dX - p[2].X) - (p[1].X - p[2].X) * (dY - p[2].Y)) / 1024;
v = ((p[0].X - p[2].X) * (dY - p[2].Y) - (p[0].Y - p[2].Y) * (dX - p[2].X)) / 1024;

// Point is within the triangle if 0 <= u,v <= 1024
if (u >= 0 && u <= 1024 && v >= 0 && v <= 1024)
break;
}

// Calculate w from u,v and interpolate height
var dz = (u * p[0].Z + v * p[1].Z + (1024 - u - v) * p[2].Z) / 1024;
return new WDist(delta.Z - dz);
return (u * p[0].Z + v * p[1].Z + (1024 - u - v) * p[2].Z) / 1024;
}
}

Expand Down
1 change: 1 addition & 0 deletions OpenRA.Mods.Common/Activities/Move/Move.cs
Expand Up @@ -464,6 +464,7 @@ void UpdateCenterLocation(Actor self, Mobile mobile)
else
pos = WPos.Lerp(From, To, moveFraction, MoveFractionTotal);

pos -= new WVec(WDist.Zero, WDist.Zero, self.World.Map.DistanceAboveTerrain(pos));
mobile.SetVisualPosition(self, pos);
}
else
Expand Down
2 changes: 1 addition & 1 deletion OpenRA.Mods.Common/Traits/World/TerrainGeometryOverlay.cs
Expand Up @@ -64,7 +64,7 @@ IEnumerable<IRenderable> IRenderAnnotations.RenderAnnotations(Actor self, WorldR

var height = (int)map.Height[uv];
var r = map.Grid.Ramps[map.Ramp[uv]];
var pos = map.CenterOfCell(uv.ToCPos(map));
var pos = map.CenterOfCell(uv.ToCPos(map)) - new WVec(0, 0, r.CenterHeightOffset);
var width = uv == mouseCell ? 3 : 1;

// Colors change between points, so render separately
Expand Down

0 comments on commit 8bc704a

Please sign in to comment.