/// <summary>
        /// Returns any and all neighbors adjacent to the given coordinates.
        /// </summary>
        /// <param name="column"></param>
        /// <param name="row"></param>
        /// <returns></returns>
        public IEnumerable <NeighborResult <T> > GetAllNeighbors(int column, int row)
        {
            T neighbor;

            foreach (HexDirection direction in HexDirectionUtils.All())
            {
                if (TryGet(HexUtils.MoveFrom(column, row, direction), out neighbor))
                {
                    yield return(new NeighborResult <T>(direction, neighbor));
                }
            }
        }
        //private List<HexTile> GetZBucket(int z) {
        //	List<HexTile> result;
        //	if (!zDict.TryGetValue(z, out result)) {
        //		result = new List<HexTile>();
        //		zDict[z] = result;
        //	}
        //	return result;
        //}

        /// <summary>
        /// Since the axis 2 only holds 3 values in order to avoid redundancy, the hex at the given coordinates only
        /// contains half the information. If the given direction is not one of the first three, we have to go to
        /// one of the three neighboring hexagons in order to find the common value.
        /// </summary>
        /// <param name="column"></param>
        /// <param name="row"></param>
        /// <param name="direction"></param>
        /// <returns></returns>
        public static Vector3Int Convert(int column, int row, HexDirection direction)
        {
            if ((int)direction >= 3)
            {
                Vector2Int move = HexUtils.MoveFrom(column, row, direction);
                return(new Vector3Int(move.x, move.y, (int)direction.Opposite()));
            }
            else
            {
                return(new Vector3Int(column, row, (int)direction));
            }
        }
        public bool IsWallAt(int column, int row, HexDirection direction)
        {
            int elevationA = GetElevationAt(column, row);

            int elevationB = GetElevationAt(HexUtils.MoveFrom(column, row, direction));

            int difference = Mathf.Abs(elevationB - elevationA);

            return(difference > 2);

            //if (isWallTable == null) {
            //	return false;
            //}
            //return isWallTable.Get(column, row, direction);
        }
        /// <summary>
        /// Returns the coords for tiles that have been affected by changes.
        /// </summary>
        /// <returns></returns>
        public IEnumerable <Vector2Int> EndChangeCheck()
        {
            HashSet <Vector2Int> tileCoords = new HashSet <Vector2Int>();

            foreach (var coord in changedCoords)
            {
                // take the coord + direction and add both tiles that touch that edge
                // first one's easy
                tileCoords.Add(new Vector2Int(coord.x, coord.y));
                // second one is move 1 tile in the given direction
                HexDirection direction = (HexDirection)coord.z;
                Vector2Int   move      = HexUtils.MoveFrom(coord.x, coord.y, direction);
                tileCoords.Add(move);
            }

            foreach (var coord in tileCoords)
            {
                yield return(coord);
            }
        }
Esempio n. 5
0
        public Mesh ElevatedTileHexagon(HexMetrics metrics, HexMap hexMap, int column, int row, Mesh recycleMesh = null)
        {
            ClearAndSetup("Hexagon Tile With Elevation", recycleMesh);

            Vector3 center = HexUtils.PositionFromCoordinates(column, row, metrics.tileSize);

            int elevation = hexMap.GetElevationAt(column, row);

            float elevationHeight = metrics.elevationStepHeight * elevation;

            Color baseColor = hexMap.tileset.GetColorForElevation(elevation, metrics.maxElevation);

            float centerHeight = metrics.XZPositionToHeight(center);

            float[] cornerHeights = new float[6];
            foreach (var corner in HexCornerUtils.AllCorners())
            {
                Vector3 vertex = HexUtils.CornerPosition((int)corner) * metrics.tileSize;
                cornerHeights[corner.GetInt()] = metrics.XZPositionToHeight(center + vertex);
            }

            #region Base Hexagon

            float baseHexagonPercentage = metrics.tileInnerRadiusPercent;

            // Add vertex data for each corner first in order to reduce redundancy (18 vertices -> 7)
            // Not making triangles yet
            foreach (HexCorner corner in HexCornerUtils.AllCorners())
            {
                // Vertice w/ height
                //Vector3 cornerPoint = SpokePoint(metrics, corner, baseHexagonPercentage, centerHeight, cornerHeights);
                // Base the height of the 'spokes' on the straight line from the center out to the corner of the whole tile
                Vector3 cornerVertex = HexUtils.CornerPosition((int)corner) * metrics.tileSize * baseHexagonPercentage;

                float projectedSpokeHeight = (cornerHeights[corner.GetInt()] - centerHeight)
                                             * baseHexagonPercentage;
                float   vertexHeight    = centerHeight + projectedSpokeHeight;
                Vector3 cornerPoint     = cornerVertex + Vector3.up * (vertexHeight * metrics.mapHeight + elevationHeight);
                float   textureGradient = vertexHeight;
                AddHexPointData(metrics, cornerPoint, center, baseColor, textureGradient);
            }

            // Add the center point last just so that we can use the HexCorner enums as indexes and the center is @ 6
            int Center = 6;             // just for readability
            // UV
            uvs.Add(metrics.XZPositionToUV(center));

            // Vertice
            Vector3 centerVertex = new Vector3(0, centerHeight * metrics.mapHeight + elevationHeight, 0);
            vertices.Add(centerVertex);

            // Color
            colors.Add(baseColor);

            // Gradient
            uvs2.Add(new Vector2(centerHeight, 0));

            // Make triangles
            foreach (HexCorner corner in HexCornerUtils.AllCorners())
            {
                triangles.Add((int)corner.Next());                 // Next first because of normals
                triangles.Add((int)corner);
                triangles.Add(Center);
            }

            #endregion

            // The starting index of the points for the outer ring
            int ringStartIndex = vertices.Count;             // should be 7 here

            // ----------Add another ring to the hexagon
            #region First Ring

            float firstRingPercentage = metrics.tileOuterRadiusPercent;

            // Add vertex data for each outside corner
            // Not making triangles yet
            // Add three points for each corner: the actual outside corner and then the two bridge points
            foreach (HexCorner corner in HexCornerUtils.AllCorners())
            {
                HexDirection direction = corner.GetDirection();

                float theta = HexUtils.CornerAngle((int)corner);

                //// We need to account for the three walls connecting to this corner:
                //// the wall on this hex going left,
                //// the wall on this hex going right,
                //// and the wall adjacent to this hex running out and away
                //bool leftWall = hexMap.IsWallAt(column, row, corner.GetDirection());
                //bool rightWall = hexMap.IsWallAt(column, row, corner.GetDirection().Last());
                //// move to the hex left of the given corner, turn two directions CW and check that wall
                //bool awayWall = hexMap.IsWallAt(HexUtils.MoveFrom(column, row, corner.GetDirection()), corner.GetDirection().Last2());



                // -------Actual Corner---------- -
                {
                    Vector3 cornerVertex = HexUtils.CornerPosition((int)corner) * metrics.tileSize * firstRingPercentage;

                    float nextNeighborElevationHeight = metrics.elevationStepHeight *
                                                        hexMap.GetElevationAt(HexUtils.MoveFrom(column, row, direction));
                    float lastNeighborElevationHeight = metrics.elevationStepHeight *
                                                        hexMap.GetElevationAt(HexUtils.MoveFrom(column, row, direction.Last()));
                    float heightModFromElevation =
                        (elevationHeight + nextNeighborElevationHeight + lastNeighborElevationHeight) * 0.33f;

                    float projectedSpokeHeight = (cornerHeights[corner.GetInt()] - centerHeight)
                                                 * firstRingPercentage;
                    float   vertexHeight = centerHeight + projectedSpokeHeight;
                    Vector3 cornerPoint  = cornerVertex +
                                           Vector3.up * (vertexHeight * metrics.mapHeight + heightModFromElevation);
                    float textureGradient = vertexHeight;

                    bool  isWall     = hexMap.IsWallAt(column, row, direction.Last());
                    Color slopeColor = baseColor;
                    if (isWall)
                    {
                        slopeColor = hexMap.tileset.steepSlopeColor;
                    }

                    AddHexPointData(metrics, cornerPoint, center, slopeColor, textureGradient);
                }

                //// ------- CCW Bridge Point -----------
                {
                    var fromCorner       = corner;
                    var towardCorner     = corner.Next();
                    var bridgePercentage = metrics.tileInnerRadiusPercent;

                    //Vector3 bridgePoint = BridgePoint(metrics, corner, corner.Next(), firstRingPercentage,
                    //	metrics.tileInnerRadiusPercent, centerVertex, cornerHeights);

                    float nextNeighborElevationHeight = metrics.elevationStepHeight *
                                                        hexMap.GetElevationAt(HexUtils.MoveFrom(column, row, direction));
                    float heightModFromElevation =
                        (elevationHeight + nextNeighborElevationHeight) * 0.5f;


                    Vector3 cornerVertex = HexUtils.CornerPosition((int)fromCorner) * metrics.tileSize;
                    cornerVertex = cornerVertex +
                                   Vector3.up * (cornerHeights[fromCorner.GetInt()] * metrics.mapHeight + heightModFromElevation);

                    Vector3 nextCornerPoint = HexUtils.CornerPosition(towardCorner.GetInt()) * metrics.tileSize;
                    nextCornerPoint = nextCornerPoint +
                                      Vector3.up * (cornerHeights[towardCorner.GetInt()] * metrics.mapHeight + heightModFromElevation);

                    Vector3 vector      = nextCornerPoint - cornerVertex;
                    float   bridgeMod   = 0.5f * (1f - bridgePercentage);
                    Vector3 bridgePoint = cornerVertex + vector * bridgeMod;

                    vector      = centerVertex - bridgePoint;
                    bridgePoint = bridgePoint + vector * (1f - firstRingPercentage);

                    bool  isWall     = hexMap.IsWallAt(column, row, direction);
                    Color slopeColor = baseColor;
                    if (isWall)
                    {
                        slopeColor = hexMap.tileset.steepSlopeColor;
                    }

                    AddHexPointData(metrics, bridgePoint, center, slopeColor, cornerHeights[corner.GetInt()]);
                }

                //// ------- CW Bridge Point -----------
                {
                    //Vector3 bridgePoint = BridgePoint(metrics, corner, corner.Last(), firstRingPercentage,
                    //	metrics.tileInnerRadiusPercent, centerVertex, cornerHeights);

                    var fromCorner       = corner;
                    var towardCorner     = corner.Last();
                    var bridgePercentage = metrics.tileInnerRadiusPercent;

                    //Vector3 bridgePoint = BridgePoint(metrics, corner, corner.Next(), firstRingPercentage,
                    //	metrics.tileInnerRadiusPercent, centerVertex, cornerHeights);

                    float neighborElevationHeight = metrics.elevationStepHeight *
                                                    hexMap.GetElevationAt(HexUtils.MoveFrom(column, row, direction.Last()));
                    float heightModFromElevation =
                        (elevationHeight + neighborElevationHeight) * 0.5f;

                    Vector3 cornerVertex = HexUtils.CornerPosition((int)fromCorner) * metrics.tileSize;
                    cornerVertex = cornerVertex +
                                   Vector3.up * (cornerHeights[fromCorner.GetInt()] * metrics.mapHeight + heightModFromElevation);

                    Vector3 nextCornerPoint = HexUtils.CornerPosition(towardCorner.GetInt()) * metrics.tileSize;
                    nextCornerPoint = nextCornerPoint + Vector3.up * (cornerHeights[towardCorner.GetInt()] * metrics.mapHeight + heightModFromElevation);

                    Vector3 vector      = nextCornerPoint - cornerVertex;
                    float   bridgeMod   = 0.5f * (1f - bridgePercentage);
                    Vector3 bridgePoint = cornerVertex + vector * bridgeMod;

                    vector      = centerVertex - bridgePoint;
                    bridgePoint = bridgePoint + vector * (1f - firstRingPercentage);

                    bool  isWall     = hexMap.IsWallAt(column, row, direction.Last());
                    Color slopeColor = baseColor;
                    if (isWall)
                    {
                        slopeColor = hexMap.tileset.steepSlopeColor;
                    }
                    AddHexPointData(metrics, bridgePoint, center, slopeColor, cornerHeights[corner.GetInt()]);
                }
            }

            // Make triangles, accounting for one corner and one side at a time

            // we actually need quads, so pairs of triangles
            foreach (HexCorner corner in HexCornerUtils.AllCorners())
            {
                // inside point is [corner], outside point is [corner * 3 + ORStart]
                int outerCorner = (int)corner * 3 + ringStartIndex + 0;
                // left bridge point is [corner * 3 + ORStart + 1], right bridge point is [corner * 3 + ORStart + 2]
                int rightBridgePoint = (int)corner * 3 + ringStartIndex + 2;
                int leftBridgePoint  = (int)corner * 3 + ringStartIndex + 1;
                // corner.Next() is the point CCW
                int nextRightBridgePoint = (int)corner.Next() * 3 + ringStartIndex + 2;

                // first half of the quad
                triangles.Add((int)corner);
                triangles.Add((int)corner.Next());
                triangles.Add(nextRightBridgePoint);

                // second half of the quad
                triangles.Add(nextRightBridgePoint);
                triangles.Add(leftBridgePoint);
                triangles.Add((int)corner);

                // span from the quad to the corner with a quad
                triangles.Add(leftBridgePoint);
                triangles.Add(outerCorner);
                triangles.Add((int)corner);

                // second part of corner span
                triangles.Add(rightBridgePoint);
                triangles.Add((int)corner);
                triangles.Add(outerCorner);
            }

            #endregion



            return(Build());
        }