Ejemplo n.º 1
0
    void TriangulateAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        //alter channel center
        if (cell.HasRoads)
        {
            TriangulateRoadAdjacentToRiver(direction, cell, center, e);
        }
        if (cell.HasRiverThroughEdge(direction.Next()))
        {
            if (cell.HasRiverThroughEdge(direction.Previous()))
            {
                center += HexMetric.GetSolidEdgeMiddle(direction) * (HexMetric.innerToOuter * 0.5f);
            }
            else if (cell.HasRiverThroughEdge(direction.Previous2()))
            {
                center += HexMetric.GetFirstSolidCorner(direction) * 0.25f;
            }
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()) && cell.HasRiverThroughEdge(direction.Next2()))
        {
            center += HexMetric.GetSecondSolidCorner(direction) * 0.25f;
        }

        EdgeVertices m = new EdgeVertices(Vector3.Lerp(center, e.v1, 0.5f), Vector3.Lerp(center, e.v5, 0.5f));

        TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex);
        TriangulateEdgeFan(center, m, cell.TerrainTypeIndex);
        if (!cell.IsUnderwater && !cell.HasRiverThroughEdge(direction))
        {
            features.AddFeature((center + e.v1 + e.v5) * (1f / 3f), cell);
        }
    }
Ejemplo n.º 2
0
    void TriangulateOpenWater(HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center)
    {
        Vector3 c1 = center + HexMetric.GetFirstWaterCorner(direction);
        Vector3 c2 = center + HexMetric.GetSecondWaterCorner(direction);

        water.AddTriangle(center, c1, c2);

        if (direction <= HexDirection.SE && neighbor != null)
        {
            Vector3 bridge = HexMetric.GetWaterBridge(direction);
            Vector3 e1     = c1 + bridge;
            Vector3 e2     = c2 + bridge;

            water.AddQuad(c1, c2, e1, e2);
            if (direction <= HexDirection.E)
            {
                HexCell nextNeighbor = cell.GetNeighbor(direction.Next());
                if (nextNeighbor == null || !nextNeighbor.IsUnderwater)
                {
                    return;
                }
                water.AddTriangle(
                    c2, e2, c2 + HexMetric.GetWaterBridge(direction.Next())
                    );
            }
        }
    }
Ejemplo n.º 3
0
    private void TriangulateCornerCliffTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell)
    {
        float b = 1f / (leftCell.Elevation - beginCell.Elevation);

        if (b < 0)
        {
            b = -b;
        }
        Vector3 boundary      = Vector3.Lerp(HexMetric.Perturb(begin), HexMetric.Perturb(left), b);
        Color   boundaryColor = Color.Lerp(color1, color2, b);
        Vector3 types;

        types.x = beginCell.TerrainTypeIndex;
        types.y = leftCell.TerrainTypeIndex;
        types.z = rightCell.TerrainTypeIndex;

        //lower connection
        TriangulateBoundaryTriangle(right, color3, begin, color1, boundary, boundaryColor, types);

        //upper terrace connection
        if (leftCell.GetEdgeType(rightCell) == HexEdgeType.Slope)
        {
            TriangulateBoundaryTriangle(left, color2, right, color3, boundary, boundaryColor, types);
        }
        else //upper cliff connection
        {
            terrain.AddTriangleUnperturbed(HexMetric.Perturb(left), HexMetric.Perturb(right), boundary);
            terrain.AddTriangleColor(color2, color3, boundaryColor);
            terrain.AddTriangleTerrainTypes(types);
        }
    }
Ejemplo n.º 4
0
    void TriangulateBoundaryTriangle(Vector3 begin, Color beginColor, Vector3 left, Color leftColor, Vector3 boundary, Color boundaryColor, Vector3 types)
    {
        Vector3 v2 = HexMetric.Perturb(HexMetric.TerraceLerp(begin, left, 1));
        Color   c2 = HexMetric.TerraceLerp(beginColor, leftColor, 1);

        // first triangle
        terrain.AddTriangleUnperturbed(HexMetric.Perturb(begin), v2, boundary);
        terrain.AddTriangleColor(beginColor, c2, boundaryColor);
        terrain.AddTriangleTerrainTypes(types);

        //connect terrace with cliff
        for (int i = 2; i < HexMetric.terraceSteps; i++)
        {
            Vector3 v1 = v2;
            Color   c1 = c2;
            v2 = HexMetric.Perturb(HexMetric.TerraceLerp(begin, left, i));
            c2 = HexMetric.TerraceLerp(beginColor, leftColor, i);
            terrain.AddTriangleUnperturbed(v1, v2, boundary);
            terrain.AddTriangleColor(c1, c2, boundaryColor);
            terrain.AddTriangleTerrainTypes(types);
        }
        //last triangle
        terrain.AddTriangleUnperturbed(v2, HexMetric.Perturb(left), boundary);
        terrain.AddTriangleColor(c2, leftColor, boundaryColor);
        terrain.AddTriangleTerrainTypes(types);
    }
Ejemplo n.º 5
0
 void OnEnable()
 {
     if (!HexMetric.noiseSource)
     {
         HexMetric.InitializeHashGrid(seed);
         HexMetric.noiseSource = noiseSource;
         //HexMetric.InitializeHashGrid(seed);
     }
 }
Ejemplo n.º 6
0
    public void AddTriangle(Vector3 v1, Vector3 v2, Vector3 v4)
    {
        int vertexIndex = vertices.Count;

        vertices.Add(HexMetric.Perturb(v1));
        vertices.Add(HexMetric.Perturb(v2));
        vertices.Add(HexMetric.Perturb(v4));
        triangles.Add(vertexIndex);
        triangles.Add(vertexIndex + 1);
        triangles.Add(vertexIndex + 2);
    }
Ejemplo n.º 7
0
    internal static EdgeVertices TerraceLerp(EdgeVertices a, EdgeVertices b, int step)
    {
        EdgeVertices result;

        result.v1 = HexMetric.TerraceLerp(a.v1, b.v1, step);
        result.v2 = HexMetric.TerraceLerp(a.v2, b.v2, step);
        result.v3 = HexMetric.TerraceLerp(a.v3, b.v3, step);
        result.v4 = HexMetric.TerraceLerp(a.v4, b.v4, step);
        result.v5 = HexMetric.TerraceLerp(a.v5, b.v5, step);
        return(result);
    }
Ejemplo n.º 8
0
    void TriangulateWaterfallInWater(Vector3 v1, Vector3 v2, Vector3 v3, Vector3 v4, float y1, float y2, float waterY)
    {
        v1.y = v2.y = y1;
        v3.y = v4.y = y2;
        v1   = HexMetric.Perturb(v1);
        v2   = HexMetric.Perturb(v2);
        v3   = HexMetric.Perturb(v3);
        v4   = HexMetric.Perturb(v4);
        float t = (waterY - y2) / (y1 - y2);

        v3 = Vector3.Lerp(v3, v1, t);
        v4 = Vector3.Lerp(v4, v2, t);
        rivers.AddQuadUnperturbed(v1, v2, v3, v4);
        rivers.AddQuadUV(0f, 1f, 0.8f, 1f);
    }
Ejemplo n.º 9
0
 Transform PickPrefab(int level, float hash, float choice)
 {
     if (level > 0)
     {
         float[] thresholds = HexMetric.GetFeatureThresholds(level - 1);
         for (int i = 0; i < thresholds.Length; i++)
         {
             if (hash < thresholds[i])
             {
                 return(urbanCollections[i].Pick(choice));
             }
         }
     }
     return(null);
 }
Ejemplo n.º 10
0
    public void AddFeature(Vector3 position, HexCell cell)
    {
        HexHash   hash   = HexMetric.SampleHashGrid(position);
        Transform prefab = PickPrefab(cell.UrbanLevel, 0, 0);

        if (!prefab)
        {
            return;
        }
        Transform instance = Instantiate(prefab);

        position.y            += instance.localScale.y * 0.5f;
        instance.localPosition = HexMetric.Perturb(position);
        instance.localRotation = Quaternion.Euler(0f, 360f, 0f);
        instance.SetParent(container, false);
    }
Ejemplo n.º 11
0
    void TriangulateWaterShore(HexDirection direction, HexCell cell, HexCell neighbor, Vector3 center)
    {
        EdgeVertices e1 = new EdgeVertices(
            center + HexMetric.GetFirstWaterCorner(direction),
            center + HexMetric.GetSecondWaterCorner(direction)
            );

        water.AddTriangle(center, e1.v1, e1.v2);
        water.AddTriangle(center, e1.v2, e1.v3);
        water.AddTriangle(center, e1.v3, e1.v4);
        water.AddTriangle(center, e1.v4, e1.v5);

        Vector3 center2 = neighbor.Position;

        center2.y = center.y;
        EdgeVertices e2 = new EdgeVertices(
            center2 + HexMetric.GetSecondSolidCorner(direction.Opposite()),
            center2 + HexMetric.GetFirstSolidCorner(direction.Opposite())
            );

        if (cell.HasRiverThroughEdge(direction))
        {
            TriangulateEstuary(e1, e2, cell.IncomingRiver == direction);
        }
        else
        {
            waterShore.AddQuad(e1.v1, e1.v2, e2.v1, e2.v2);
            waterShore.AddQuad(e1.v2, e1.v3, e2.v2, e2.v3);
            waterShore.AddQuad(e1.v3, e1.v4, e2.v3, e2.v4);
            waterShore.AddQuad(e1.v4, e1.v5, e2.v4, e2.v5);
            waterShore.AddQuadUV(0f, 0f, 0f, 1f);
            waterShore.AddQuadUV(0f, 0f, 0f, 1f);
            waterShore.AddQuadUV(0f, 0f, 0f, 1f);
            waterShore.AddQuadUV(0f, 0f, 0f, 1f);
        }

        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());

        if (nextNeighbor != null)
        {
            Vector3 v3 = nextNeighbor.Position + (nextNeighbor.IsUnderwater ? HexMetric.GetFirstWaterCorner(direction.Previous()) : HexMetric.GetFirstSolidCorner(direction.Previous()));
            v3.y = center.y;
            waterShore.AddTriangle(e1.v5, e2.v5, v3); waterShore.AddTriangleUV(new Vector2(0f, 0f), new Vector2(0f, 1f), new Vector2(0f, nextNeighbor.IsUnderwater ? 0f : 1f));
        }
    }
Ejemplo n.º 12
0
    internal void Refresh(int newx, int newz)
    {
        heightNoise      = new CoherentNoise.Generation.ValueNoise2D(seed);
        temperatureNoise = new CoherentNoise.Generation.ValueNoise2D(seed + 1);
        chunkCountX      = newx;
        chunkCountZ      = newz;
        UnityEngine.Random.InitState(seed);
        //component setup
        HexMetric.noiseSource = noiseSource;
        HexMetric.InitializeHashGrid(seed);
        // set grid size
        grid       = new HexCell[cellCountX * cellCountZ];
        cellCountX = chunkCountX * HexMetric.chunkSizeX;
        cellCountZ = chunkCountZ * HexMetric.chunkSizeZ;

        CreateChunks();
        CreateCells(true);
    }
Ejemplo n.º 13
0
    void Triangulate(HexDirection direction, HexCell cell)
    {
        Vector3      center = cell.Position;
        EdgeVertices e      = new EdgeVertices(
            center + HexMetric.GetFirstSolidCorner(direction),
            center + HexMetric.GetSecondSolidCorner(direction)
            );

        if (cell.HasRiver)
        {
            if (cell.HasRiverThroughEdge(direction))
            {
                e.v3.y = cell.StreamBedY;
                if (cell.HasRiverBeginOrEnd)
                {
                    TriangulateWithRiverBeginOrEnd(direction, cell, center, e);
                }
                else
                {
                    TriangulateWithRiver(direction, cell, center, e);
                }
            }
            else
            {
                TriangulateAdjacentToRiver(direction, cell, center, e);
            }
        }
        else
        {
            TriangulateWithoutRiver(direction, cell, center, e);
            if (!cell.IsUnderwater && !cell.HasRiverThroughEdge(direction))
            {
                features.AddFeature((center + e.v1 + e.v5) * (1f / 3f), cell);
            }
        }
        if (direction <= HexDirection.SE)
        {
            TriangulateConnection(direction, cell, e);
        }
        if (cell.IsUnderwater)
        {
            TriangulateWater(direction, cell, center);
        }
    }
Ejemplo n.º 14
0
    void TriangulateEdgeTerraces(EdgeVertices begin, HexCell beginCell, EdgeVertices end, HexCell endCell, bool hasRoad)
    {
        EdgeVertices e2 = EdgeVertices.TerraceLerp(begin, end, 1);
        Color        c2 = HexMetric.TerraceLerp(color1, color2, 1);
        float        t1 = beginCell.TerrainTypeIndex;
        float        t2 = endCell.TerrainTypeIndex;

        //first task
        TriangulateEdgeStrip(begin, color1, t1, e2, c2, t2, hasRoad);

        //process of creating actual steps
        for (int i = 2; i < HexMetric.terraceSteps; i++)
        {
            EdgeVertices e1 = e2;
            Color        c1 = c2;
            e2 = EdgeVertices.TerraceLerp(begin, end, i);
            c2 = HexMetric.TerraceLerp(color1, color2, i);
            TriangulateEdgeStrip(e1, c1, t1, e2, c2, t2, hasRoad);
        }

        //last task
        TriangulateEdgeStrip(e2, c2, t1, end, color2, t2, hasRoad);
    }
Ejemplo n.º 15
0
    void TriangulateCornerTerraces(Vector3 begin, HexCell beginCell, Vector3 left, HexCell leftCell, Vector3 right, HexCell rightCell)
    {
        Vector3 v3 = HexMetric.TerraceLerp(begin, left, 1);
        Vector3 v4 = HexMetric.TerraceLerp(begin, right, 1);
        Color   c3 = HexMetric.TerraceLerp(color1, color2, 1);
        Color   c4 = HexMetric.TerraceLerp(color1, color3, 1);

        Vector3 types;

        types.x = beginCell.TerrainTypeIndex;
        types.y = leftCell.TerrainTypeIndex;
        types.z = rightCell.TerrainTypeIndex;

        terrain.AddTriangle(begin, v3, v4);
        terrain.AddTriangleColor(color1, c3, c4);
        terrain.AddTriangleTerrainTypes(types);

        for (int i = 2; i < HexMetric.terraceSteps; i++)
        {
            Vector3 v1 = v3;
            Vector3 v2 = v4;
            Color   c1 = c3;
            Color   c2 = c4;
            v3 = HexMetric.TerraceLerp(begin, left, i);
            v4 = HexMetric.TerraceLerp(begin, right, i);
            c3 = HexMetric.TerraceLerp(color1, color2, i);
            c4 = HexMetric.TerraceLerp(color1, color3, i);
            terrain.AddQuad(v1, v2, v3, v4);
            terrain.AddQuadColor(c1, c2, c3, c4);
            terrain.AddQuadTerrainTypes(types);
        }

        terrain.AddQuad(v3, v4, left, right);
        terrain.AddQuadColor(c3, c4, color2, color3);
        terrain.AddQuadTerrainTypes(types);
    }
Ejemplo n.º 16
0
    void TriangulateConnection(HexDirection direction, HexCell cell, EdgeVertices e1)
    {
        //Is border cell?
        HexCell neighbor = cell.GetNeighbor(direction);

        if (neighbor == null)
        {
            return;
        }
        //create bridge between cells
        Vector3 bridge = HexMetric.GetBridge(direction);

        bridge.y = neighbor.Position.y - cell.Position.y;
        EdgeVertices e2 = new EdgeVertices(e1.v1 + bridge, e1.v5 + bridge);

        if (cell.HasRiverThroughEdge(direction))
        {
            e2.v3.y = neighbor.StreamBedY;
            if (!cell.IsUnderwater)
            {
                if (!neighbor.IsUnderwater)
                {
                    TriangulateRiverQuad(e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, 0.8f, cell.HasIncomingRiver && cell.IncomingRiver == direction);
                }
                else if (cell.Elevation > neighbor.WaterLevel)
                {
                    TriangulateWaterfallInWater(e1.v2, e1.v4, e2.v2, e2.v4, cell.RiverSurfaceY, neighbor.RiverSurfaceY, neighbor.WaterSurfaceY);
                }
            }
            else if (
                !neighbor.IsUnderwater && neighbor.Elevation > cell.WaterLevel)
            {
                TriangulateWaterfallInWater(e2.v4, e2.v2, e1.v4, e1.v2, neighbor.RiverSurfaceY, cell.RiverSurfaceY, cell.WaterSurfaceY);
            }
        }
        if (cell.GetEdgeType(direction) == HexEdgeType.Slope)
        {
            TriangulateEdgeTerraces(e1, cell, e2, neighbor, cell.HasRoadThroughEdge(direction));
        }
        else // cliffs or flat cells
        {
            TriangulateEdgeStrip(e1, color1, cell.TerrainTypeIndex, e2, color2, cell.TerrainTypeIndex, cell.HasRoadThroughEdge(direction));
        }
        //create triangle that connects three cells together
        HexCell nextNeighbor = cell.GetNeighbor(direction.Next());

        if (direction <= HexDirection.E && nextNeighbor != null)
        {
            Vector3 v5 = e1.v5 + HexMetric.GetBridge(direction.Next());
            v5.y = nextNeighbor.Position.y;
            if (cell.Elevation <= neighbor.Elevation)
            {
                if (cell.Elevation <= nextNeighbor.Elevation)
                {
                    TriangulateCorner(e1.v5, cell, e2.v5, neighbor, v5, nextNeighbor);
                }
                else
                {
                    TriangulateCorner(v5, nextNeighbor, e1.v5, cell, e2.v5, neighbor);
                }
            }
            else if (neighbor.Elevation <= nextNeighbor.Elevation)
            {
                TriangulateCorner(e2.v5, neighbor, v5, nextNeighbor, e1.v5, cell);
            }
            else
            {
                TriangulateCorner(v5, nextNeighbor, e1.v5, cell, e2.v5, neighbor);
            }
        }
    }
Ejemplo n.º 17
0
    void TriangulateWithRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        //outer walls
        Vector3 centerL, centerR;

        if (cell.HasRiverThroughEdge(direction.Opposite()))
        {
            centerL = center +
                      HexMetric.GetFirstSolidCorner(direction.Previous()) * 0.25f;
            centerR = center +
                      HexMetric.GetSecondSolidCorner(direction.Next()) * 0.25f;
        }
        // sharp turns
        else if (cell.HasRiverThroughEdge(direction.Next()))
        {
            centerL = center;
            centerR = Vector3.Lerp(center, e.v5, 2f / 3f);
        }
        else if (cell.HasRiverThroughEdge(direction.Previous()))
        {
            centerL = Vector3.Lerp(center, e.v1, 2f / 3f);
            centerR = center;
        }
        // two way turns
        else if (cell.HasRiverThroughEdge(direction.Next2()))
        {
            centerL = center;
            centerR = center + HexMetric.GetSolidEdgeMiddle(direction.Next()) * (0.5f * HexMetric.innerToOuter);
        }
        else
        {
            centerL = center + HexMetric.GetSolidEdgeMiddle(direction.Previous()) * (0.5f * HexMetric.innerToOuter);
            centerR = center;
        }

        //mid point of channel
        EdgeVertices m = new EdgeVertices(Vector3.Lerp(centerL, e.v1, 0.5f), Vector3.Lerp(centerR, e.v5, 0.5f), 1f / 6f);

        m.v3.y = center.y = e.v3.y;
        //fill area
        TriangulateEdgeStrip(m, color1, cell.TerrainTypeIndex, e, color1, cell.TerrainTypeIndex);
        terrain.AddTriangle(centerL, m.v1, m.v2);
        terrain.AddQuad(centerL, center, m.v2, m.v3);
        terrain.AddQuad(center, centerR, m.v3, m.v4);
        terrain.AddTriangle(centerR, m.v4, m.v5);

        terrain.AddTriangleColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddQuadColor(color1);
        terrain.AddTriangleColor(color1);

        Vector3 types;

        types.x = types.y = types.z = cell.TerrainTypeIndex;
        terrain.AddTriangleTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddQuadTerrainTypes(types);
        terrain.AddTriangleTerrainTypes(types);

        //river water quads
        if (!cell.IsUnderwater)
        {
            bool reversed = cell.IncomingRiver == direction;

            TriangulateRiverQuad(centerL, centerR, m.v2, m.v4, cell.RiverSurfaceY, 0.4f, reversed);
            TriangulateRiverQuad(m.v2, m.v4, e.v2, e.v4, cell.RiverSurfaceY, 0.6f, reversed);
        }
    }
Ejemplo n.º 18
0
    private void TriangulateRoadAdjacentToRiver(HexDirection direction, HexCell cell, Vector3 center, EdgeVertices e)
    {
        bool    hasRoadThroughEdge = cell.HasRoadThroughEdge(direction);
        bool    previousHasRiver   = cell.HasRiverThroughEdge(direction.Previous());
        bool    nextHasRiver       = cell.HasRiverThroughEdge(direction.Next());
        Vector2 interpolators      = GetRoadInterpolators(direction, cell);
        Vector3 roadCenter         = center;

        if (cell.HasRiverBeginOrEnd)
        {
            roadCenter += HexMetric.GetSolidEdgeMiddle(cell.RiverBeginOrEndDirection.Opposite()) * (1f / 3f);
        }
        else if (cell.IncomingRiver == cell.OutgoingRiver.Opposite())
        {
            Vector3 corner;
            if (previousHasRiver)
            {
                if (
                    !hasRoadThroughEdge &&
                    !cell.HasRoadThroughEdge(direction.Next())
                    )
                {
                    return;
                }
                corner = HexMetric.GetSecondSolidCorner(direction);
            }
            else
            {
                if (
                    !hasRoadThroughEdge &&
                    !cell.HasRoadThroughEdge(direction.Previous())
                    )
                {
                    return;
                }
                corner = HexMetric.GetFirstSolidCorner(direction);
            }
            roadCenter += corner * 0.5f;
            center     += corner * 0.25f;
        }

        else if (cell.IncomingRiver == cell.OutgoingRiver.Previous())
        {
            roadCenter -= HexMetric.GetSecondCorner(cell.IncomingRiver) * 0.2f;
        }

        else if (cell.IncomingRiver == cell.OutgoingRiver.Next())
        {
            roadCenter -= HexMetric.GetFirstCorner(cell.IncomingRiver) * 0.2f;
        }

        else if (previousHasRiver && nextHasRiver)
        {
            if (!hasRoadThroughEdge)
            {
                return;
            }

            Vector3 offset = HexMetric.GetSolidEdgeMiddle(direction) * HexMetric.innerToOuter;
            roadCenter += offset * 0.7f;
            center     += offset * 0.5f;
        }

        else
        {
            HexDirection middle;
            if (previousHasRiver)
            {
                middle = direction.Next();
            }
            else if (nextHasRiver)
            {
                middle = direction.Previous();
            }
            else
            {
                middle = direction;
            }
            if (
                !cell.HasRoadThroughEdge(middle) &&
                !cell.HasRoadThroughEdge(middle.Previous()) &&
                !cell.HasRoadThroughEdge(middle.Next())
                )
            {
                return;
            }
            roadCenter += HexMetric.GetSolidEdgeMiddle(middle) * 0.25f;
        }

        Vector3 mL = Vector3.Lerp(roadCenter, e.v1, interpolators.x);
        Vector3 mR = Vector3.Lerp(roadCenter, e.v5, interpolators.y);

        TriangulateRoad(roadCenter, mL, mR, e, hasRoadThroughEdge);
        if (previousHasRiver)
        {
            TriangulateRoadEdge(roadCenter, center, mL);
        }
        if (nextHasRiver)
        {
            TriangulateRoadEdge(roadCenter, mR, center);
        }
    }
Ejemplo n.º 19
0
 public HexEdgeType GetEdgeType(HexDirection direction)
 {
     return(HexMetric.GetEdgeType(info.elevation, neighbors[(int)direction].info.elevation));
 }
Ejemplo n.º 20
0
 public HexEdgeType GetEdgeType(HexCell otherCell)
 {
     return(HexMetric.GetEdgeType(info.elevation, otherCell.info.elevation));
 }