Account for ramps in terrain height calculations.
This commit is contained in:
@@ -68,8 +68,12 @@ namespace OpenRA.Graphics
|
|||||||
|
|
||||||
public void Update(CPos cell, Sprite sprite)
|
public void Update(CPos cell, Sprite sprite)
|
||||||
{
|
{
|
||||||
var xyz = sprite == null ? float3.Zero :
|
var xyz = float3.Zero;
|
||||||
worldRenderer.Screen3DPosition(map.CenterOfCell(cell)) + sprite.Offset - 0.5f * sprite.Size;
|
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);
|
Update(cell.ToMPos(map.Grid.Type), sprite, xyz);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -262,11 +262,9 @@ namespace OpenRA.Graphics
|
|||||||
var s = worldRenderer.ScreenPxPosition(p);
|
var s = worldRenderer.ScreenPxPosition(p);
|
||||||
if (Math.Abs(s.X - world.X) <= tileSize.Width && Math.Abs(s.Y - world.Y) <= tileSize.Height)
|
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 ramp = map.Grid.Ramps[map.Ramp.Contains(uv) ? map.Ramp[uv] : 0];
|
||||||
var corners = map.Grid.Ramps[ramp].Corners;
|
var pos = map.CenterOfCell(uv.ToCPos(map)) - new WVec(0, 0, ramp.CenterHeightOffset);
|
||||||
var pos = map.CenterOfCell(uv.ToCPos(map));
|
var screen = ramp.Corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
|
||||||
var screen = corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
|
|
||||||
|
|
||||||
if (screen.PolygonContains(world))
|
if (screen.PolygonContains(world))
|
||||||
return uv.ToCPos(map);
|
return uv.ToCPos(map);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -820,7 +820,7 @@ namespace OpenRA
|
|||||||
// (c) u, v coordinates run diagonally to the cell axes, and we define
|
// (c) u, v coordinates run diagonally to the cell axes, and we define
|
||||||
// 1024 as the length projected onto the primary cell axis
|
// 1024 as the length projected onto the primary cell axis
|
||||||
// - 512 * sqrt(2) = 724
|
// - 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);
|
return new WPos(724 * (cell.X - cell.Y + 1), 724 * (cell.X + cell.Y + 1), z);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -828,15 +828,39 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
var index = (int)subCell;
|
var index = (int)subCell;
|
||||||
if (index >= 0 && index < Grid.SubCellOffsets.Length)
|
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);
|
return CenterOfCell(cell);
|
||||||
}
|
}
|
||||||
|
|
||||||
public WDist DistanceAboveTerrain(WPos pos)
|
public WDist DistanceAboveTerrain(WPos pos)
|
||||||
{
|
{
|
||||||
|
if (Grid.Type == MapGridType.Rectangular)
|
||||||
|
return new WDist(pos.Z);
|
||||||
|
|
||||||
|
// Apply ramp offset
|
||||||
var cell = CellContaining(pos);
|
var cell = CellContaining(pos);
|
||||||
var delta = pos - CenterOfCell(cell);
|
var offset = pos - CenterOfCell(cell);
|
||||||
return new WDist(delta.Z);
|
|
||||||
|
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)
|
public WVec Offset(CVec delta, int dz)
|
||||||
|
|||||||
@@ -24,6 +24,7 @@ namespace OpenRA
|
|||||||
|
|
||||||
public struct CellRamp
|
public struct CellRamp
|
||||||
{
|
{
|
||||||
|
public readonly int CenterHeightOffset;
|
||||||
public readonly WVec[] Corners;
|
public readonly WVec[] Corners;
|
||||||
public readonly WVec[][] Polygons;
|
public readonly WVec[][] Polygons;
|
||||||
|
|
||||||
@@ -68,9 +69,13 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
Polygons = new[] { Corners };
|
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
|
// 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
|
// If the ramp is not split we will take the first three vertices of the corners as a valid triangle
|
||||||
@@ -80,8 +85,8 @@ namespace OpenRA
|
|||||||
for (var i = 0; i < Polygons.Length; i++)
|
for (var i = 0; i < Polygons.Length; i++)
|
||||||
{
|
{
|
||||||
p = Polygons[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;
|
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) * (delta.Y - p[2].Y) - (p[0].Y - p[2].Y) * (delta.X - p[2].X)) / 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
|
// Point is within the triangle if 0 <= u,v <= 1024
|
||||||
if (u >= 0 && u <= 1024 && v >= 0 && v <= 1024)
|
if (u >= 0 && u <= 1024 && v >= 0 && v <= 1024)
|
||||||
@@ -89,8 +94,7 @@ namespace OpenRA
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Calculate w from u,v and interpolate height
|
// 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 (u * p[0].Z + v * p[1].Z + (1024 - u - v) * p[2].Z) / 1024;
|
||||||
return new WDist(delta.Z - dz);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -464,6 +464,7 @@ namespace OpenRA.Mods.Common.Activities
|
|||||||
else
|
else
|
||||||
pos = WPos.Lerp(From, To, moveFraction, MoveFractionTotal);
|
pos = WPos.Lerp(From, To, moveFraction, MoveFractionTotal);
|
||||||
|
|
||||||
|
pos -= new WVec(WDist.Zero, WDist.Zero, self.World.Map.DistanceAboveTerrain(pos));
|
||||||
mobile.SetVisualPosition(self, pos);
|
mobile.SetVisualPosition(self, pos);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
|
|
||||||
var height = (int)map.Height[uv];
|
var height = (int)map.Height[uv];
|
||||||
var r = map.Grid.Ramps[map.Ramp[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;
|
var width = uv == mouseCell ? 3 : 1;
|
||||||
|
|
||||||
// Colors change between points, so render separately
|
// Colors change between points, so render separately
|
||||||
|
|||||||
Reference in New Issue
Block a user