Beispiel #1
0
        public void TriangulateContoursBetween(
            IHexCell center, IHexCell right, HexDirection direction, Color centerWeights, Color rightWeights, IHexMesh mesh
            )
        {
            var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction);
            var rightCenterContour = CellContourCanon.GetContourForCellEdge(right, direction.Opposite());

            int centerRightIndex = 1, rightCenterIndex = rightCenterContour.Count - 1;

            while (centerRightIndex < centerRightContour.Count && rightCenterIndex > 0)
            {
                mesh.AddQuad(
                    centerRightContour[centerRightIndex - 1].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ(),
                    rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ()
                    );

                mesh.AddQuadColor(centerWeights, rightWeights);

                centerRightIndex++;
                rightCenterIndex--;
            }

            for (; centerRightIndex < centerRightContour.Count; centerRightIndex++)
            {
                mesh.AddTriangle(
                    centerRightContour[centerRightIndex - 1].ToXYZ(), rightCenterContour[0].ToXYZ(), centerRightContour[centerRightIndex].ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, centerWeights);
            }

            for (; rightCenterIndex > 0; rightCenterIndex--)
            {
                mesh.AddTriangle(
                    centerRightContour.Last().ToXYZ(), rightCenterContour[rightCenterIndex].ToXYZ(), rightCenterContour[rightCenterIndex - 1].ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights);
            }

            if (RiverCanon.HasRiverAlongEdge(right, direction.Next2()))
            {
                var nextRight = Grid.GetNeighbor(center, direction.Next());

                var rightNextRightContour = CellContourCanon.GetContourForCellEdge(right, direction.Next2());
                var nextRightRightContour = CellContourCanon.GetContourForCellEdge(nextRight, direction.Previous());

                mesh.AddTriangle(
                    centerRightContour.Last().ToXYZ(),
                    rightNextRightContour.Last().ToXYZ(),
                    nextRightRightContour.First().ToXYZ()
                    );

                mesh.AddTriangleColor(centerWeights, rightWeights, rightWeights);
            }
        }
Beispiel #2
0
        private bool ShouldAddQuad(
            List <IHexCell> farmBlob, Vector2 northVertex, Vector2 eastVertex, Vector2 southVertex, Vector2 westVertex
            )
        {
            bool northValid = false, eastValid = false, southValid = false, westValid = false;

            foreach (var cell in farmBlob)
            {
                foreach (var direction in EnumUtil.GetValues <HexDirection>())
                {
                    if (RiverCanon.HasRiverAlongEdge(cell, direction))
                    {
                        var contour = CellContourCanon.GetContourForCellEdge(cell, direction);

                        if (CellContourCanon.DoesSegmentCrossContour(northVertex, eastVertex, contour) ||
                            CellContourCanon.DoesSegmentCrossContour(northVertex, westVertex, contour) ||
                            CellContourCanon.DoesSegmentCrossContour(southVertex, eastVertex, contour) ||
                            CellContourCanon.DoesSegmentCrossContour(southVertex, westVertex, contour)
                            )
                        {
                            return(false);
                        }
                    }

                    northValid |= CellContourCanon.IsPointWithinContour(northVertex, cell, direction);
                    eastValid  |= CellContourCanon.IsPointWithinContour(eastVertex, cell, direction);
                    southValid |= CellContourCanon.IsPointWithinContour(southVertex, cell, direction);
                    westValid  |= CellContourCanon.IsPointWithinContour(westVertex, cell, direction);
                }
            }

            return(northValid && eastValid && southValid && westValid);
        }
Beispiel #3
0
        public void TriangulateCultureInDirection(
            IHexCell center, HexDirection direction, IHexMesh cultureMesh
            )
        {
            var centerOwner = CivTerritoryLogic.GetCivClaimingCell(center);

            if (centerOwner == null)
            {
                return;
            }

            IHexCell left      = Grid.GetNeighbor(center, direction.Previous());
            IHexCell right     = Grid.GetNeighbor(center, direction);
            IHexCell nextRight = Grid.GetNeighbor(center, direction.Next());

            if (right == null)
            {
                return;
            }

            if (CivTerritoryLogic.GetCivClaimingCell(right) != centerOwner)
            {
                TriangulateCultureAlongContour(center, direction, centerOwner.Template.Color, cultureMesh);
            }
            else
            {
                var centerRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction);
                var rightCenterContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Opposite());

                if (rightCenterContour.Count <= 3)
                {
                    TriangulateCultureCorners_FlatEdge(
                        center, left, right, nextRight, direction, centerOwner, centerRightContour, rightCenterContour, cultureMesh
                        );
                }
                else
                {
                    TriangulateCultureCorners_River(
                        center, left, right, nextRight, direction, centerOwner, centerRightContour, cultureMesh
                        );
                }
            }
        }
        private void OnDrawGizmos_Contours()
        {
            Vector3 lineOne = Vector3.zero, lineTwo = Vector3.zero;

            foreach (var cell in Grid.Cells)
            {
                Vector3 center = cell.AbsolutePosition;

                foreach (var direction in EnumUtil.GetValues <HexDirection>())
                {
                    var contour = CellEdgeContourCanon.GetContourForCellEdge(cell, direction);

                    if (contour.Count == 0)
                    {
                        continue;
                    }

                    for (int i = 0; i < contour.Count - 1; i++)
                    {
                        Gizmos.color = Color.white;

                        lineOne.x = contour[i].x;
                        lineOne.z = contour[i].y;

                        lineTwo.x = contour[i + 1].x;
                        lineTwo.z = contour[i + 1].y;

                        Gizmos.DrawLine(lineOne, lineTwo);

                        Gizmos.color = Color.gray;

                        lineTwo.x = contour[i].x;
                        lineTwo.z = contour[i].y;

                        Gizmos.DrawLine(center, lineTwo);
                    }

                    lineTwo.x = contour.Last().x;
                    lineTwo.z = contour.Last().y;

                    Gizmos.DrawLine(center, lineTwo);

                    Gizmos.color = Color.red;
                    Gizmos.DrawLine(center, center + RenderConfig.GetFirstCorner(direction));
                    Gizmos.DrawLine(center, center + RenderConfig.GetSecondCorner(direction));
                }
            }
        }
Beispiel #5
0
        private void TriangulateCellWeights_River(
            IHexCell center, IHexCell right, HexDirection direction, bool hasCenterRightRiver, IHexMesh weightsMesh
            )
        {
            var centerRightContour = CellContourCanon.GetContourForCellEdge(center, direction);

            Vector3 innerOne, innerTwo, contourOneXYZ, contourTwoXYZ;

            for (int i = 1; i < centerRightContour.Count; i++)
            {
                contourOneXYZ = centerRightContour[i - 1].ToXYZ();
                contourTwoXYZ = centerRightContour[i].ToXYZ();

                innerOne = Vector3.Lerp(center.AbsolutePosition, contourOneXYZ, RenderConfig.SolidFactor);
                innerTwo = Vector3.Lerp(center.AbsolutePosition, contourTwoXYZ, RenderConfig.SolidFactor);

                weightsMesh.AddTriangle(center.AbsolutePosition, innerOne, innerTwo);
                weightsMesh.AddTriangleColor(CenterWeights);

                weightsMesh.AddQuad(innerOne, innerTwo, contourOneXYZ, contourTwoXYZ);

                if (hasCenterRightRiver)
                {
                    weightsMesh.AddQuadColor(CenterWeights);
                }
                else
                {
                    weightsMesh.AddQuadColor(CenterWeights, CenterRightWeights);
                }
            }

            if (hasCenterRightRiver && direction <= HexDirection.SE)
            {
                ContourTriangulator.TriangulateContoursBetween(
                    center, right, direction, CenterWeights, RightWeights, weightsMesh
                    );
            }
        }
        public void TriangulateOrientation(IHexCell center, IHexMesh orientationMesh)
        {
            short indexOffset = (short)(center.Index + 1);

            foreach (var direction in EnumUtil.GetValues <HexDirection>())
            {
                byte[] rg = BitConverter.GetBytes(indexOffset);
                byte   b  = (byte)direction;

                var cellColor = new Color32(rg[0], rg[1], b, 0);

                var centerContour = CellContourCanon.GetContourForCellEdge(center, direction);

                for (int i = 1; i < centerContour.Count; i++)
                {
                    orientationMesh.AddTriangle(
                        center.AbsolutePosition, centerContour[i - 1].ToXYZ(), centerContour[i].ToXYZ()
                        );

                    orientationMesh.AddTriangleColor(cellColor);
                }

                if (direction <= HexDirection.SE && RiverCanon.HasRiverAlongEdge(center, direction))
                {
                    var right = Grid.GetNeighbor(center, direction);

                    ContourTriangulator.TriangulateContoursBetween(
                        center, right, direction, cellColor, cellColor, orientationMesh
                        );

                    if (direction <= HexDirection.E && RiverCanon.HasRiverAlongEdge(right, direction.Previous2()))
                    {
                    }
                }
            }
        }
        public void BuildNonRiverContour(IHexCell center, HexDirection direction)
        {
            if (RiverCanon.HasRiverAlongEdge(center, direction))
            {
                return;
            }

            var contourPoints = new List <Vector2>();

            IHexCell left      = Grid.GetNeighbor(center, direction.Previous());
            IHexCell right     = Grid.GetNeighbor(center, direction);
            IHexCell nextRight = Grid.GetNeighbor(center, direction.Next());

            bool hasCenterLeftRiver      = RiverCanon.HasRiverAlongEdge(center, direction.Previous());
            bool hasCenterNextRightRiver = RiverCanon.HasRiverAlongEdge(center, direction.Next());

            bool hasLeftRightRiver      = left != null && RiverCanon.HasRiverAlongEdge(left, direction.Next());
            bool hasNextRightRightRiver = nextRight != null && RiverCanon.HasRiverAlongEdge(nextRight, direction.Previous());

            if (hasCenterLeftRiver)
            {
                ICollection <Vector2> centerLeftContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Previous());

                contourPoints.Add(centerLeftContour.Last());
            }
            else if (hasLeftRightRiver)
            {
                ICollection <Vector2> rightLeftContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Previous2());

                contourPoints.Add(rightLeftContour.First());
            }
            else
            {
                contourPoints.Add(center.AbsolutePositionXZ + RenderConfig.GetFirstCornerXZ(direction));
            }

            if (hasCenterNextRightRiver ||
                (hasNextRightRightRiver && RiverCanon.GetFlowOfRiverAtEdge(nextRight, direction.Previous()) == RiverFlow.Clockwise)
                )
            {
                ICollection <Vector2> centerNextRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Next());

                contourPoints.Add(centerNextRightContour.First());
            }
            else if (hasNextRightRightRiver)
            {
                //We need to add two points here in case the edge is up against the
                //outflow of a river. We've decided to give the outflow over entirely
                //to one of the cells, but other constructions are possible.
                ICollection <Vector2> rightNextRightContour = CellEdgeContourCanon.GetContourForCellEdge(right, direction.Next2());
                ICollection <Vector2> nextRightRightContour = CellEdgeContourCanon.GetContourForCellEdge(nextRight, direction.Previous());

                contourPoints.Add(rightNextRightContour.Last());
                contourPoints.Add(nextRightRightContour.First());
            }
            else
            {
                contourPoints.Add(center.AbsolutePositionXZ + RenderConfig.GetSecondCornerXZ(direction));
            }

            CellEdgeContourCanon.SetContourForCellEdge(center, direction, contourPoints);
        }
        /*
         * There are a handful of possible cases for this method.
         *
         * In the first case, CenterLeftContour and CenterRightContour intersect each-other.
         * In that case, we want to remove all of the points in each contour beyond the other
         * and then join them at the intersect. We do this by checking the contours in opposite
         * directions. Because all contours are oriented clockwise around their cell, if we
         * check for line segment collision carefully we'll know exactly which points need to
         * be removed. Any intersection will appear close to the beginning of CenterRightContour
         * and the end of CenterLeftContour. Thus we work up CenterRightContour and down
         * CenterLeftContour. Once we find an intersection, we strip points from the beginning of
         * CenterRightContour and the end of CenterLeftContour and add the intersection point at
         * the beginning and end, respectively.
         *
         * In the second case, CenterLeftContour doesn't touch CenterRightContour but CenterRightContour
         * extends undesirably into the rivers. To handle this, we extrapolate forward from
         * CenterLeftContour using its last and second to last points, check for an intersection,
         * and then cull points and add the intersection as above.
         *
         * In the third case, CenterRightContour doesn't touch CenterLeftContour but CenterLeftContour
         * extends undesirably into the rivers. We handle this much the same way, extrapolating
         * backwards from the first and second points of CenterRightContour, checking for an intersecton,
         * and culling as needed.
         *
         * In the fourth case, neither contours touch each-other or extend into the rivers. In that case,
         * we extrapolate on both contours (forward for CenterLeft, backward for CenterRight) and add
         * their intersection without culling.
         */
        public void RationalizeCellContours(
            IHexCell center, HexDirection direction
            )
        {
            List <Vector2> centerLeftContour  = CellEdgeContourCanon.GetContourForCellEdge(center, direction.Previous()).ToList();
            List <Vector2> centerRightContour = CellEdgeContourCanon.GetContourForCellEdge(center, direction).ToList();

            int lastOutsideLeftIndex  = centerLeftContour.Count - 1;
            int lastOutsideRightIndex = 0;

            Vector2 contourIntersect = Vector2.zero;

            bool hasFoundIntersect = false;

            //We multiply our extrapolating vector by some relatively large number to make it more likely
            //that they intersect properly.
            for (; lastOutsideLeftIndex > 0; lastOutsideLeftIndex--)
            {
                if (Geometry2D.AreLineSegmentsCrossing(
                        centerLeftContour[lastOutsideLeftIndex], centerLeftContour [lastOutsideLeftIndex - 1], out contourIntersect,
                        centerRightContour[0], centerRightContour[0] + (centerRightContour[0] - centerRightContour[1]) * 10, out contourIntersect
                        ))
                {
                    hasFoundIntersect = true;
                    break;
                }

                for (lastOutsideRightIndex = 0; lastOutsideRightIndex < centerRightContour.Count - 1; lastOutsideRightIndex++)
                {
                    if (Geometry2D.AreLineSegmentsCrossing(
                            centerLeftContour [lastOutsideLeftIndex], centerLeftContour [lastOutsideLeftIndex - 1], out contourIntersect,
                            centerRightContour[lastOutsideRightIndex], centerRightContour[lastOutsideRightIndex + 1], out contourIntersect
                            ))
                    {
                        hasFoundIntersect = true;
                        break;
                    }
                }

                if (hasFoundIntersect)
                {
                    break;
                }
            }

            if (!hasFoundIntersect)
            {
                Vector2 lastLeft       = centerLeftContour.Last();
                Vector2 secondLastLeft = centerLeftContour[centerLeftContour.Count - 2];

                if (Geometry2D.AreLineSegmentsCrossing(
                        lastLeft, lastLeft + (lastLeft - secondLastLeft) * 10, out contourIntersect,
                        centerRightContour[0], centerRightContour[0] + (centerRightContour[0] - centerRightContour[1]) * 10, out contourIntersect
                        ))
                {
                    hasFoundIntersect = true;
                }

                for (lastOutsideRightIndex = 0; lastOutsideRightIndex < centerRightContour.Count - 1; lastOutsideRightIndex++)
                {
                    if (Geometry2D.AreLineSegmentsCrossing(
                            lastLeft, lastLeft + (lastLeft - secondLastLeft) * 10, out contourIntersect,
                            centerRightContour[lastOutsideRightIndex], centerRightContour[lastOutsideRightIndex + 1], out contourIntersect
                            ))
                    {
                        hasFoundIntersect = true;
                        break;
                    }
                }
            }

            if (lastOutsideLeftIndex > 0)
            {
                centerLeftContour.RemoveRange(lastOutsideLeftIndex, centerLeftContour.Count - lastOutsideLeftIndex);
            }

            if (lastOutsideRightIndex < centerRightContour.Count - 1)
            {
                centerRightContour.RemoveRange(0, lastOutsideRightIndex + 1);
            }

            if (hasFoundIntersect)
            {
                centerLeftContour.Add(contourIntersect);

                centerRightContour.Insert(0, contourIntersect);
            }

            CellEdgeContourCanon.SetContourForCellEdge(center, direction.Previous(), centerLeftContour);
            CellEdgeContourCanon.SetContourForCellEdge(center, direction, centerRightContour);
        }