コード例 #1
0
        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);
        }
コード例 #2
0
        private void TriangulateRiver(RiverSpline riverSpline)
        {
            Vector3 riverYVector = Vector3.up * RenderConfig.WaterY;

            var centerSpline = riverSpline.CenterSpline;

            float maxSurfaceWidth = RenderConfig.RiverMaxSurfaceWidth
                                    * Mathf.Clamp01((float)centerSpline.CurveCount / RenderConfig.RiverCurvesForMaxWidth);

            float maxBankWidth = (RenderConfig.RiverMaxSurfaceWidth + RenderConfig.RiverMaxBankWidth)
                                 * Mathf.Clamp01((float)centerSpline.CurveCount / RenderConfig.RiverCurvesForMaxWidth);

            int riverQuadCount = centerSpline.CurveCount * RenderConfig.RiverQuadsPerCurve;

            float tDelta = 1f / riverQuadCount;

            float t = 0f;

            Vector3 surfacePortV1, surfaceStarboardV1, bankPortV1, bankStarboardV1, center1, duckPortV1, duckStarboardV1;

            Vector3 center2 = centerSpline.GetPoint(tDelta) + riverYVector;

            float noise = NoiseGenerator.SampleNoise(
                new Vector2(center2.x, center2.z), RenderConfig.GenericNoiseSource, RenderConfig.RiverWidthNoise, NoiseType.NegativeOneToOne
                ).x;

            Vector3 flow1 = centerSpline.GetDirection(t);
            Vector3 flow2 = centerSpline.GetDirection(tDelta);

            float surfaceWidth = maxSurfaceWidth * (Mathf.Clamp01(tDelta * RenderConfig.RiverWideningRate) + tDelta * noise);
            float bankWidth    = maxBankWidth * (Mathf.Clamp01(tDelta * RenderConfig.RiverWideningRate) + tDelta * noise);

            Vector3 surfacePortV2      = center2 + centerSpline.GetNormalXZ(tDelta) * surfaceWidth;
            Vector3 surfaceStarboardV2 = center2 - centerSpline.GetNormalXZ(tDelta) * surfaceWidth;

            Vector3 bankPortV2      = center2 + centerSpline.GetNormalXZ(tDelta) * bankWidth;
            Vector3 bankStarboardV2 = center2 - centerSpline.GetNormalXZ(tDelta) * bankWidth;

            Grid.RiverSurfaceMesh.AddTriangle(centerSpline.Points[0] + riverYVector, surfacePortV2, surfaceStarboardV2);
            Grid.RiverSurfaceMesh.AddTriangleUV3(flow1, flow2, flow2);
            Grid.RiverSurfaceMesh.AddTriangleColor(RenderConfig.RiverWaterColor);

            Grid.RiverBankMesh.AddTriangle(centerSpline.Points[0] + riverYVector, bankPortV2, bankStarboardV2);
            Grid.RiverBankMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero);

            Vector3 duckPortV2, duckStarboardV2;

            BuildDuckStartCap(
                center2, centerSpline, bankPortV2, bankStarboardV2, tDelta, riverYVector, out duckPortV2, out duckStarboardV2
                );

            //Triangulating the main body of the river
            for (int sectionIndex = 0; sectionIndex < riverSpline.WesternCells.Count; sectionIndex++)
            {
                List <Vector2> thisEdgeContour     = new List <Vector2>();
                List <Vector2> neighborEdgeContour = new List <Vector2>();

                if (sectionIndex == 0)
                {
                    thisEdgeContour.Add(new Vector2(centerSpline.Points[0].x, centerSpline.Points[0].z));
                    neighborEdgeContour.Add(new Vector2(centerSpline.Points[0].x, centerSpline.Points[0].z));
                }

                var sectionFlow = riverSpline.Flows[sectionIndex];

                for (int pointIndex = 0; pointIndex < RenderConfig.RiverQuadsPerCurve; pointIndex++)
                {
                    t += tDelta;

                    surfacePortV1      = surfacePortV2;
                    surfaceStarboardV1 = surfaceStarboardV2;

                    bankPortV1      = bankPortV2;
                    bankStarboardV1 = bankStarboardV2;

                    duckPortV1      = duckPortV2;
                    duckStarboardV1 = duckStarboardV2;

                    center1 = center2;

                    center2 = centerSpline.GetPoint(t) + riverYVector;

                    noise = NoiseGenerator.SampleNoise(
                        new Vector2(center2.x, center2.z), RenderConfig.GenericNoiseSource, RenderConfig.RiverWidthNoise, NoiseType.NegativeOneToOne
                        ).x;

                    surfaceWidth = maxSurfaceWidth * (Mathf.Clamp01(t * RenderConfig.RiverWideningRate) + t * noise);
                    bankWidth    = maxBankWidth * (Mathf.Clamp01(t * RenderConfig.RiverWideningRate) + t * noise);

                    flow1 = flow2;
                    flow2 = centerSpline.GetDirection(t);

                    surfacePortV2      = center2 + centerSpline.GetNormalXZ(t) * surfaceWidth;
                    surfaceStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * surfaceWidth;

                    bankPortV2      = center2 + centerSpline.GetNormalXZ(t) * bankWidth;
                    bankStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * bankWidth;

                    duckPortV2      = center2 + centerSpline.GetNormalXZ(t) * RenderConfig.RiverDuckWidth;
                    duckStarboardV2 = center2 - centerSpline.GetNormalXZ(t) * RenderConfig.RiverDuckWidth;

                    Grid.RiverSurfaceMesh.AddQuad(surfacePortV1, surfaceStarboardV1, surfacePortV2, surfaceStarboardV2);
                    Grid.RiverSurfaceMesh.AddQuadUV3(flow1, flow1, flow2, flow2);
                    Grid.RiverSurfaceMesh.AddQuadColor(RenderConfig.RiverWaterColor);

                    Grid.RiverBankMesh.AddQuad(center1, center2, bankPortV1, bankPortV2);
                    Grid.RiverBankMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero);

                    Grid.RiverBankMesh.AddQuad(center2, center1, bankStarboardV2, bankStarboardV1);
                    Grid.RiverBankMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero);

                    Grid.RiverDuckMesh.AddQuad(bankPortV1, bankPortV2, duckPortV1, duckPortV2);
                    Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero);

                    Grid.RiverDuckMesh.AddQuad(bankPortV2, bankPortV1, bankStarboardV2, bankStarboardV1);
                    Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.one, Vector2.one);

                    Grid.RiverDuckMesh.AddQuad(bankStarboardV2, bankStarboardV1, duckStarboardV2, duckStarboardV1);
                    Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero);

                    thisEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfacePortV1.ToXZ() : surfaceStarboardV1.ToXZ());
                    neighborEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfaceStarboardV1.ToXZ() : surfacePortV1.ToXZ());
                }

                thisEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfacePortV2.ToXZ() : surfaceStarboardV2.ToXZ());
                neighborEdgeContour.Add(sectionFlow == RiverFlow.Counterclockwise ? surfaceStarboardV2.ToXZ() : surfacePortV2.ToXZ());

                CellEdgeContourCanon.SetContourForCellEdge(
                    riverSpline.WesternCells[sectionIndex], riverSpline.Directions[sectionIndex], thisEdgeContour
                    );

                CellEdgeContourCanon.SetContourForCellEdge(
                    riverSpline.EasternCells[sectionIndex], riverSpline.Directions[sectionIndex].Opposite(), neighborEdgeContour
                    );
            }

            BuildDuckEndCap(riverSpline, duckPortV2, duckStarboardV2, bankPortV2, bankStarboardV2);
        }
コード例 #3
0
        /*
         * 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);
        }