Replace MapGrid.CellCorners with a new CellRamp struct.
This commit is contained in:
@@ -263,7 +263,7 @@ namespace OpenRA.Graphics
|
|||||||
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.Ramp.Contains(uv) ? map.Ramp[uv] : 0;
|
||||||
var corners = map.Grid.CellCorners[ramp];
|
var corners = map.Grid.Ramps[ramp].Corners;
|
||||||
var pos = map.CenterOfCell(uv.ToCPos(map));
|
var pos = map.CenterOfCell(uv.ToCPos(map));
|
||||||
var screen = corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
|
var screen = corners.Select(c => worldRenderer.ScreenPxPosition(pos + c)).ToArray();
|
||||||
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@
|
|||||||
*/
|
*/
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
@@ -20,6 +19,81 @@ namespace OpenRA
|
|||||||
{
|
{
|
||||||
public enum MapGridType { Rectangular, RectangularIsometric }
|
public enum MapGridType { Rectangular, RectangularIsometric }
|
||||||
|
|
||||||
|
public enum RampSplit { Flat, X, Y }
|
||||||
|
public enum RampCornerHeight { Low = 0, Half = 1, Full = 2 }
|
||||||
|
|
||||||
|
public struct CellRamp
|
||||||
|
{
|
||||||
|
public readonly WVec[] Corners;
|
||||||
|
public readonly WVec[][] Polygons;
|
||||||
|
|
||||||
|
public CellRamp(MapGridType type, RampCornerHeight tl = RampCornerHeight.Low, RampCornerHeight tr = RampCornerHeight.Low, RampCornerHeight br = RampCornerHeight.Low, RampCornerHeight bl = RampCornerHeight.Low, RampSplit split = RampSplit.Flat)
|
||||||
|
{
|
||||||
|
if (type == MapGridType.RectangularIsometric)
|
||||||
|
{
|
||||||
|
Corners = new[]
|
||||||
|
{
|
||||||
|
new WVec(0, -724, 724 * (int)tl),
|
||||||
|
new WVec(724, 0, 724 * (int)tr),
|
||||||
|
new WVec(0, 724, 724 * (int)br),
|
||||||
|
new WVec(-724, 0, 724 * (int)bl),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Corners = new[]
|
||||||
|
{
|
||||||
|
new WVec(-512, -512, 512 * (int)tl),
|
||||||
|
new WVec(512, -512, 512 * (int)tr),
|
||||||
|
new WVec(512, 512, 512 * (int)br),
|
||||||
|
new WVec(-512, 512, 512 * (int)bl)
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (split == RampSplit.X)
|
||||||
|
{
|
||||||
|
Polygons = new[]
|
||||||
|
{
|
||||||
|
new[] { Corners[0], Corners[1], Corners[3] },
|
||||||
|
new[] { Corners[1], Corners[2], Corners[3] }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else if (split == RampSplit.Y)
|
||||||
|
{
|
||||||
|
Polygons = new[]
|
||||||
|
{
|
||||||
|
new[] { Corners[0], Corners[1], Corners[2] },
|
||||||
|
new[] { Corners[0], Corners[2], Corners[3] }
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
Polygons = new[] { Corners };
|
||||||
|
}
|
||||||
|
|
||||||
|
public WDist DistanceAboveTerrain(WVec delta)
|
||||||
|
{
|
||||||
|
// 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
|
||||||
|
WVec[] p = null;
|
||||||
|
var u = 0;
|
||||||
|
var v = 0;
|
||||||
|
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;
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public class MapGrid : IGlobalModData
|
public class MapGrid : IGlobalModData
|
||||||
{
|
{
|
||||||
public readonly MapGridType Type = MapGridType.Rectangular;
|
public readonly MapGridType Type = MapGridType.Rectangular;
|
||||||
@@ -41,43 +115,7 @@ namespace OpenRA
|
|||||||
new WVec(256, 256, 0), // bottom right - index 5
|
new WVec(256, 256, 0), // bottom right - index 5
|
||||||
};
|
};
|
||||||
|
|
||||||
public WVec[][] CellCorners { get; private set; }
|
public CellRamp[] Ramps { get; private set; }
|
||||||
|
|
||||||
readonly int[][] cellCornerHalfHeights = new int[][]
|
|
||||||
{
|
|
||||||
// Flat
|
|
||||||
new[] { 0, 0, 0, 0 },
|
|
||||||
|
|
||||||
// Slopes (two corners high)
|
|
||||||
new[] { 0, 0, 1, 1 },
|
|
||||||
new[] { 1, 0, 0, 1 },
|
|
||||||
new[] { 1, 1, 0, 0 },
|
|
||||||
new[] { 0, 1, 1, 0 },
|
|
||||||
|
|
||||||
// Slopes (one corner high)
|
|
||||||
new[] { 0, 0, 0, 1 },
|
|
||||||
new[] { 1, 0, 0, 0 },
|
|
||||||
new[] { 0, 1, 0, 0 },
|
|
||||||
new[] { 0, 0, 1, 0 },
|
|
||||||
|
|
||||||
// Slopes (three corners high)
|
|
||||||
new[] { 1, 0, 1, 1 },
|
|
||||||
new[] { 1, 1, 0, 1 },
|
|
||||||
new[] { 1, 1, 1, 0 },
|
|
||||||
new[] { 0, 1, 1, 1 },
|
|
||||||
|
|
||||||
// Slopes (two corners high, one corner double high)
|
|
||||||
new[] { 1, 0, 1, 2 },
|
|
||||||
new[] { 2, 1, 0, 1 },
|
|
||||||
new[] { 1, 2, 1, 0 },
|
|
||||||
new[] { 0, 1, 2, 1 },
|
|
||||||
|
|
||||||
// Slopes (two corners high, alternating)
|
|
||||||
new[] { 1, 0, 1, 0 },
|
|
||||||
new[] { 0, 1, 0, 1 },
|
|
||||||
new[] { 1, 0, 1, 0 },
|
|
||||||
new[] { 0, 1, 0, 1 }
|
|
||||||
};
|
|
||||||
|
|
||||||
internal readonly CVec[][] TilesByDistance;
|
internal readonly CVec[][] TilesByDistance;
|
||||||
|
|
||||||
@@ -96,34 +134,46 @@ namespace OpenRA
|
|||||||
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
|
throw new InvalidDataException("Subcell default index must be a valid index into the offset triples and must be greater than 0 for mods with subcells");
|
||||||
}
|
}
|
||||||
|
|
||||||
var makeCorners = Type == MapGridType.RectangularIsometric ?
|
// Slope types are hardcoded following the convention from the TS and RA2 map format
|
||||||
(Func<int[], WVec[]>)IsometricCellCorners : RectangularCellCorners;
|
Ramps = new[]
|
||||||
CellCorners = cellCornerHalfHeights.Select(makeCorners).ToArray();
|
{
|
||||||
|
// Flat
|
||||||
|
new CellRamp(Type),
|
||||||
|
|
||||||
|
// Two adjacent corners raised by half a cell
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, br: RampCornerHeight.Half),
|
||||||
|
new CellRamp(Type, br: RampCornerHeight.Half, bl: RampCornerHeight.Half),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, bl: RampCornerHeight.Half),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, tr: RampCornerHeight.Half),
|
||||||
|
|
||||||
|
// One corner raised by half a cell
|
||||||
|
new CellRamp(Type, br: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
new CellRamp(Type, bl: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
|
||||||
|
// Three corners raised by half a cell
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, tr: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
|
||||||
|
// Full tile sloped (mid corners raised by half cell, far corner by full cell)
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, br: RampCornerHeight.Full, bl: RampCornerHeight.Half),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, bl: RampCornerHeight.Full),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Full, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, tr: RampCornerHeight.Full, br: RampCornerHeight.Half),
|
||||||
|
|
||||||
|
// Two opposite corners raised by half a cell
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.Y),
|
||||||
|
new CellRamp(Type, tr: RampCornerHeight.Half, bl: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
new CellRamp(Type, tl: RampCornerHeight.Half, br: RampCornerHeight.Half, split: RampSplit.X),
|
||||||
|
};
|
||||||
|
|
||||||
TilesByDistance = CreateTilesByDistance();
|
TilesByDistance = CreateTilesByDistance();
|
||||||
}
|
}
|
||||||
|
|
||||||
static WVec[] IsometricCellCorners(int[] cornerHeight)
|
|
||||||
{
|
|
||||||
return new WVec[]
|
|
||||||
{
|
|
||||||
new WVec(-724, 0, 724 * cornerHeight[0]),
|
|
||||||
new WVec(0, -724, 724 * cornerHeight[1]),
|
|
||||||
new WVec(724, 0, 724 * cornerHeight[2]),
|
|
||||||
new WVec(0, 724, 724 * cornerHeight[3])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
static WVec[] RectangularCellCorners(int[] cornerHeight)
|
|
||||||
{
|
|
||||||
return new WVec[]
|
|
||||||
{
|
|
||||||
new WVec(-512, -512, 512 * cornerHeight[0]),
|
|
||||||
new WVec(512, -512, 512 * cornerHeight[1]),
|
|
||||||
new WVec(512, 512, 512 * cornerHeight[2]),
|
|
||||||
new WVec(-512, 512, 512 * cornerHeight[3])
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
CVec[][] CreateTilesByDistance()
|
CVec[][] CreateTilesByDistance()
|
||||||
{
|
{
|
||||||
var ts = new List<CVec>[MaximumTileSearchRange + 1];
|
var ts = new List<CVec>[MaximumTileSearchRange + 1];
|
||||||
|
|||||||
@@ -63,24 +63,27 @@ namespace OpenRA.Mods.Common.Traits
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
var height = (int)map.Height[uv];
|
var height = (int)map.Height[uv];
|
||||||
var corners = map.Grid.CellCorners[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));
|
||||||
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
|
||||||
for (var i = 0; i < 4; i++)
|
foreach (var p in r.Polygons)
|
||||||
{
|
{
|
||||||
var j = (i + 1) % 4;
|
for (var i = 0; i < p.Length; i++)
|
||||||
var start = pos + corners[i];
|
{
|
||||||
var end = pos + corners[j];
|
var j = (i + 1) % p.Length;
|
||||||
var startColor = colors[height + corners[i].Z / 512];
|
var start = pos + p[i];
|
||||||
var endColor = colors[height + corners[j].Z / 512];
|
var end = pos + p[j];
|
||||||
yield return new LineAnnotationRenderable(start, end, width, startColor, endColor);
|
var startColor = colors[height + p[i].Z / 512];
|
||||||
|
var endColor = colors[height + p[j].Z / 512];
|
||||||
|
yield return new LineAnnotationRenderable(start, end, width, startColor, endColor);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Projected cell coordinates for the current cell
|
// Projected cell coordinates for the current cell
|
||||||
var projectedCorners = map.Grid.CellCorners[0];
|
var projectedCorners = map.Grid.Ramps[0].Corners;
|
||||||
foreach (var puv in map.ProjectedCellsCovering(mouseCell))
|
foreach (var puv in map.ProjectedCellsCovering(mouseCell))
|
||||||
{
|
{
|
||||||
var pos = map.CenterOfCell(((MPos)puv).ToCPos(map));
|
var pos = map.CenterOfCell(((MPos)puv).ToCPos(map));
|
||||||
|
|||||||
Reference in New Issue
Block a user