private void BuildDuckEndCap(
            RiverSpline riverSpline, Vector3 duckPortV2, Vector3 duckStarboardV2, Vector3 bankPortV2, Vector3 bankStarboardV2
            )
        {
            Vector3 duckWrapPortStart = duckPortV2 - bankPortV2;
            Vector3 duckWrapPortEnd   = riverSpline.CenterSpline.GetDirection(1f) * RenderConfig.RiverDuckWidth;

            Vector3 duckCircleV2 = duckWrapPortStart;

            float duckCircleIncr = 2f / RenderConfig.RiverQuadsPerCurve;

            for (float circleParam = 0f; circleParam < 1; circleParam += duckCircleIncr)
            {
                Vector3 duckCircleV1 = duckCircleV2;

                duckCircleV2 = Vector3.Slerp(duckWrapPortStart, duckWrapPortEnd, circleParam);

                Grid.RiverDuckMesh.AddTriangle(bankPortV2, bankPortV2 + duckCircleV1, bankPortV2 + duckCircleV2);
                Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero);
            }

            Grid.RiverDuckMesh.AddTriangle(bankPortV2, bankPortV2 + duckCircleV2, bankPortV2 + duckWrapPortEnd);
            Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero);

            Vector3 duckWrapStarboardStart = duckStarboardV2 - bankStarboardV2;
            Vector3 duckWrapStarboardEnd   = riverSpline.CenterSpline.GetDirection(1f) * RenderConfig.RiverDuckWidth;

            duckCircleV2 = duckWrapPortStart;

            for (float circleParam = 0f; circleParam < 1; circleParam += duckCircleIncr)
            {
                Vector3 duckCircleV1 = duckCircleV2;

                duckCircleV2 = Vector3.Slerp(duckWrapStarboardStart, duckWrapStarboardEnd, circleParam);

                Grid.RiverDuckMesh.AddTriangle(bankStarboardV2, bankStarboardV2 + duckCircleV2, bankStarboardV2 + duckCircleV1);
                Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero);
            }

            Grid.RiverDuckMesh.AddTriangle(bankStarboardV2, bankStarboardV2 + duckWrapStarboardEnd, bankStarboardV2 + duckCircleV2);
            Grid.RiverDuckMesh.AddTriangleUV(Vector2.one, Vector2.zero, Vector2.zero);

            Grid.RiverDuckMesh.AddQuad(
                bankPortV2, bankStarboardV2, bankPortV2 + duckWrapPortEnd, bankStarboardV2 + duckWrapStarboardEnd
                );

            Grid.RiverDuckMesh.AddQuadUV(Vector2.one, Vector2.one, Vector2.zero, Vector2.zero);
        }
        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);
        }
Exemplo n.º 3
0
        private void AssembleRiverSplines()
        {
            RiverAssemblyCanon.RefreshRivers();

            foreach (var river in RiverAssemblyCanon.Rivers)
            {
                RiverSection section = river[0];

                var centerSpline = new BezierSpline(section.FlowFromOne == RiverFlow.Clockwise ? section.Start : section.End);

                Vector3 centerToV1Direction, centerToV4Direction;

                Vector3 v1Tangent, v4Tangent;

                Vector3 controlOne, controlTwo;

                Vector3 v1, v4;

                bool isV1Internal, isV4Internal;

                bool isControlOneNegative, isControlTwoNegative;

                for (int i = 0; i < river.Count; i++)
                {
                    section = river[i];

                    if (section.FlowFromOne == RiverFlow.Clockwise)
                    {
                        v1 = section.Start;
                        v4 = section.End;

                        isV1Internal = section.PreviousOnInternalCurve;
                        isV4Internal = section.NextOnInternalCurve;
                    }
                    else
                    {
                        v1 = section.End;
                        v4 = section.Start;

                        isV1Internal = section.NextOnInternalCurve;
                        isV4Internal = section.PreviousOnInternalCurve;
                    }

                    if (isV1Internal)
                    {
                        centerToV1Direction = (v1 - section.AdjacentCellOne.AbsolutePosition).normalized;
                    }
                    else
                    {
                        centerToV1Direction = (v1 - section.AdjacentCellTwo.AbsolutePosition).normalized;
                    }

                    if (isV4Internal)
                    {
                        centerToV4Direction = (v4 - section.AdjacentCellOne.AbsolutePosition).normalized;
                    }
                    else
                    {
                        centerToV4Direction = (v4 - section.AdjacentCellTwo.AbsolutePosition).normalized;
                    }

                    isControlOneNegative = (section.FlowFromOne == RiverFlow.Clockwise && isV1Internal) ||
                                           (section.FlowFromOne == RiverFlow.Counterclockwise && !isV1Internal);

                    isControlTwoNegative = (section.FlowFromOne == RiverFlow.Clockwise && !isV4Internal) ||
                                           (section.FlowFromOne == RiverFlow.Counterclockwise && isV4Internal);

                    v1Tangent = new Vector3(-centerToV1Direction.z, centerToV1Direction.y, centerToV1Direction.x);
                    v4Tangent = new Vector3(-centerToV4Direction.z, centerToV4Direction.y, centerToV4Direction.x);

                    controlOne = v1 + v1Tangent * RenderConfig.RiverCurveStrength * (isControlOneNegative ? -1f : 1f);
                    controlTwo = v4 + v4Tangent * RenderConfig.RiverCurveStrength * (isControlTwoNegative ? -1f : 1f);

                    centerSpline.AddCubicCurve(controlOne, controlTwo, v4);
                }

                var newRiverSpline = new RiverSpline()
                {
                    CenterSpline = centerSpline,
                    WesternCells = river.Select(riverSection => riverSection.AdjacentCellOne).ToList(),
                    EasternCells = river.Select(riverSection => riverSection.AdjacentCellTwo).ToList(),
                    Directions   = river.Select(riverSection => riverSection.DirectionFromOne).ToList(),
                    Flows        = river.Select(riverSection => riverSection.FlowFromOne).ToList()
                };

                RiverSplines.Add(newRiverSpline);
            }
        }