Ejemplo n.º 1
0
    public static GeneratedTrack GenerateTrack(float length, float width, long seed)
    {
        float anglePeriod     = param_AnglePeriod;
        float angleAmplitude  = param_AngleAmplitude;
        float radiusPeriod    = param_RadiusPeriod;
        float radiusAmplitude = param_RadiusAmplitude;
        float radiusOffset    = param_RadiusOffset;

        // Segment Decider
        //
        // Decider works like this:
        //   If noise returns < -1, the segment is a straight
        //   If noise returns > 1, the segment is a turn
        //   Else, it is a combination of both
        //
        float segDecMin    = param_SegDecMin;
        float segDecMax    = param_SegDecMax;
        float segDecPeriod = param_SegDecPeriod;

        float modePeriod = param_ModePeriod;


        perlinNoise = new PerlinNoise(seed);
        GeneratedTrack track = new GeneratedTrack();

        track.Faulty = false;

        List <Circle> circles = new List <Circle>();

        circles.Add(new Circle(new Vector2(0f, 150f), 250f, true));
        circles.Add(new Circle(new Vector2(150f, -100f), 250f, true));
        circles.Add(new Circle(new Vector2(-150f, -100f), 250f, true));

        List <float> circleDirections = new List <float>();

        for (int i = 0; i < circles.Count; i++)
        {
            int i2 = (i + 1) % circles.Count;

            Vector2 c1Toc2   = circles[i2].Midpoint - circles[i].Midpoint;
            Vector2 c1ToLeft = (new Vector2(-c1Toc2.y, c1Toc2.x)).normalized * circles[i].Radius;
            Vector2 c2ToLeft = (new Vector2(-c1Toc2.y, c1Toc2.x)).normalized * circles[i2].Radius;

            Vector2 c1Outs = circles[i].Midpoint + c1ToLeft;
            Vector2 c2Outs = circles[i2].Midpoint + c2ToLeft;

            Vector2 vec = c2Outs - c1Outs;

            float zAngle          = Vector2.Angle(new Vector2(0f, 1f), vec);
            float xAngle          = Vector2.Angle(new Vector2(1f, 0f), vec);
            float circleDirection = zAngle;

            if (xAngle > 90f)
            {
                circleDirection = 360f - zAngle;
            }

            circleDirection = circleDirection - 90f;
            if (circleDirection < 0f)
            {
                circleDirection = 360f - circleDirection;
            }

            circleDirections.Add(circleDirection);
        }


        int angleStep   = 0;
        int radiusStep  = 0;
        int segmentStep = 0;

        int circleIndex = 0;

        float currentAngle = 0f;
        float startRadius  = perlinNoise.noise1(radiusStep * radiusPeriod) * radiusAmplitude + radiusOffset;

        Vector2 startPoint = new Vector2(Mathf.Sin((currentAngle * Mathf.PI) / 180f) * startRadius, Mathf.Cos((currentAngle * Mathf.PI) / 180f) * startRadius);

        while (true)
        {
            angleStep++;
            radiusStep++;
            segmentStep++;

            // Segment Decider is between [-1, 1]
            float segDec = perlinNoise.noise1(segmentStep * segDecPeriod) * ((Mathf.Abs(segDecMin) + Mathf.Abs(segDecMax)) / 2f);
            segDec = segDec + ((segDecMin + segDecMax) / 2f);
            segDec = segDec > 1f ? 1f : (segDec < -1f ? -1f : segDec);

            // Angle Delta between [0, angleAmplitude]
            float angleDelta = (perlinNoise.noise1(angleStep * anglePeriod) * 0.5f + 0.5f) * angleAmplitude;
            currentAngle += angleDelta;

            // Radius between [0, 2 * radiusAmplitude]
            float radius = perlinNoise.noise1(radiusStep * radiusPeriod) * radiusAmplitude + radiusOffset;

            // Mode is either PERFECT_PART_CIRCLES or BEZIER_SPLINES
            bool takeBezierSpline = false;

            if (generationMode == DiscreteGenerationMode.BEZIER_SPLINES)
            {
                takeBezierSpline = true;
            }
            else if (generationMode == DiscreteGenerationMode.PERFECT_PART_CIRCLES)
            {
                takeBezierSpline = false;
            }
            else
            {
                takeBezierSpline = perlinNoise.noise1(angleStep * modePeriod) >= 0f;
            }

            if (currentAngle >= circleDirections[circleIndex])
            {
                circleIndex++;
                if (circleIndex >= circles.Count)
                {
                    circleIndex = 0;
                }
            }

            //Debug.Log("TAKESPLINE: " + takeBezierSpline.ToString());


            Vector2 point = new Vector2(Mathf.Sin((currentAngle * Mathf.PI) / 180f) * radius, Mathf.Cos((currentAngle * Mathf.PI) / 180f) * radius);

            point += circles[circleIndex].Midpoint;

            //Debug.Log("Iteration: " + angleStep);
            //Debug.Log("CurrentAngle: " + currentAngle);
            //Debug.Log("Radius: " + radius);
            //Debug.Log("SegDec: " + segDec);

            bool  fixedEndpointDirection = false;
            float endpointDirection      = Mathf.PI * 0.5f;
            float endpointWidth          = width;

            if (currentAngle >= 360f)
            {
                fixedEndpointDirection = true;

                point             = new Vector2(track.Elements[0].Position.x, track.Elements[0].Position.z);
                endpointDirection = track.Elements[0].Direction;
                endpointWidth     = track.Elements[0].WidthStart;
            }

            Vector2 oldPoint;
            float   oldDirection;
            if (track.Elements.Length == 0)
            {
                oldPoint     = startPoint;
                oldDirection = Mathf.PI * 0.5f;
            }
            else
            {
                oldPoint     = new Vector2(track.Elements[track.Elements.Length - 1].EndPosition.x, track.Elements[track.Elements.Length - 1].EndPosition.z);
                oldDirection = track.Elements[track.Elements.Length - 1].EndDirection;
            }


            if (fixedEndpointDirection == false)
            {
                // Completely a turn
                if (segDec >= 1f)
                {
                    if (takeBezierSpline == false)
                    {
                        float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection);

                        float circleRadius = radiusAndDegree[0];
                        float circleDegree = radiusAndDegree[1];

                        int splinesAmount = (int)(Mathf.Abs(circleDegree) / 90f) + 1;

                        float degreeOneSpline = circleDegree / splinesAmount;

                        float tanValue = 360f / degreeOneSpline;
                        tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circleRadius);

                        Vector2 prevSplinePoint = oldPoint;

                        Debug.Log("Gonna do new");

                        for (int i = 0; i < splinesAmount; i++)
                        {
                            float   tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f);
                            Vector2 midToPoint   = (new Vector2(Mathf.Cos(tempStartDir) * Mathf.Sign(circleDegree), -Mathf.Sin(tempStartDir) * Mathf.Sign(circleDegree))).normalized * circleRadius;

                            float   tempEndDir    = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f);
                            Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir) * Mathf.Sign(circleDegree), -Mathf.Sin(tempEndDir) * Mathf.Sign(circleDegree))).normalized * circleRadius;

                            Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint;

                            GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue);

                            track.AddElement(spline);

                            prevSplinePoint = tempEndpoint;

                            //Debug.Log("Spline[" + i + "]");
                        }

                        /*GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circleRadius, circleDegree, width);
                         *
                         * Vector2 turnEndPoint = new Vector2(turn.EndPosition.x, turn.EndPosition.z);
                         * if (Vector2.Distance(turnEndPoint, point) > 1f)
                         * {
                         *  track.Faulty = true;
                         *  Debug.LogError("Too big distance");
                         * }
                         *
                         * track.AddElement(turn);*/
                    }
                    else
                    {
                        /*float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection);
                         *
                         * float circleRadius = radiusAndDegree[0];
                         * float circleDegree = radiusAndDegree[1];
                         *
                         * int splinesAmount = (int)(circleDegree / 90f) + 1;
                         *
                         * float degreeOneSpline = circleDegree / splinesAmount;
                         *
                         * float tanValue = 360f / degreeOneSpline;
                         * tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circleRadius);
                         *
                         * Vector2 prevSplinePoint = oldPoint;
                         *
                         * Debug.Log("Gonna do new");
                         *
                         * for (int i = 0; i < splinesAmount; i++)
                         * {
                         *  float tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f);
                         *  Vector2 midToPoint = (new Vector2(Mathf.Cos(tempStartDir), -Mathf.Sin(tempStartDir))).normalized * circleRadius;
                         *
                         *  float tempEndDir = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f);
                         *  Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir), -Mathf.Sin(tempEndDir))).normalized * circleRadius;
                         *
                         *  Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint;
                         *
                         *  GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue);
                         *
                         *  track.AddElement(spline);
                         *
                         *  prevSplinePoint = tempEndpoint;
                         *
                         *  Debug.Log("Spline[" + i + "]");
                         * }
                         */


                        Debug.Log("Did normal spline");

                        float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection);

                        float circleRadius = radiusAndDegree[0];
                        float circleDegree = radiusAndDegree[1];

                        GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circleRadius, circleDegree, width);

                        float turnEndDirection = turn.EndDirection;

                        float maxAngleToBeDoneBySpline = 90f;

                        if (Mathf.Abs(turnEndDirection) > maxAngleToBeDoneBySpline * Mathf.PI / 180f)
                        {
                            turnEndDirection = Mathf.Sign(turnEndDirection) * (Mathf.PI * maxAngleToBeDoneBySpline / 180f);
                        }

                        float interDirection = (perlinNoise.noise1(angleStep * anglePeriod) * 0.5f + 0.5f) * (oldDirection - turnEndDirection) + turnEndDirection;

                        GeneratedBezSpline turnSpline = new GeneratedBezSpline(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, new Vector3(point.x, 0f, point.y), interDirection, width, width);

                        track.AddElement(turnSpline);
                    }
                }

                // Part straight part turn
                else
                {
                    if (false && takeBezierSpline == false)
                    {
                        float maxWidth = width;
                        //TODO not only one width all the time

                        float minRadius = maxWidth + 0.8f;

                        float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection);

                        float circleRadius = radiusAndDegree[0];
                        float circleDegree = radiusAndDegree[1];

                        float maxRadius = circleRadius;

                        float circlePartRadius = (maxRadius - minRadius) * ((segDec + 1f) * 0.5f) + minRadius;

                        Vector2 circleMiddle = Vector2.zero;

                        float[] partcircleRadiusAndDegree = makeTurnFixedRadius(oldPoint, circlePartRadius, oldDirection, (circleDegree >= 0f), point);

                        float partcircleDegree   = partcircleRadiusAndDegree[0];
                        float partstraightLength = partcircleRadiusAndDegree[1];

                        GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circlePartRadius, partcircleDegree, width);
                        track.AddElement(turn);

                        GeneratedStraight straight = new GeneratedStraight(turn.EndPosition, turn.EndDirection, partstraightLength, width);
                        //straight.AddCurb(new GeneratedCurb(0.1f, 0.9f, true, true, true));
                        track.AddElement(straight);


                        Vector2 bothEndPoint = new Vector2(straight.EndPosition.x, straight.EndPosition.z);
                        if (Vector2.Distance(bothEndPoint, point) > 1f)
                        {
                            Debug.LogError("Too big distance");
                            track.Faulty = true;
                        }
                    }
                    else
                    {
                        // Only straight
                        if (false && segDec <= -1f && track.Elements.Length > 0 && track.Elements[track.Elements.Length - 1].GetType() == typeof(GeneratedBezSpline))
                        {
                            float angleBetween = Vector2.Angle(new Vector2(0f, 1f), point - oldPoint);
                            float angleRight   = Vector2.Angle(new Vector2(1f, 0f), point - oldPoint);
                            if (angleRight > 90f)
                            {
                                angleBetween = 360f - angleBetween;
                            }
                            float radianOldEndDirection = (angleBetween * Mathf.PI) / 180f;

                            track.Elements[track.Elements.Length - 1].ForceEndDirection(radianOldEndDirection);

                            GeneratedStraight straight = new GeneratedStraight(new Vector3(oldPoint.x, 0f, oldPoint.y), radianOldEndDirection, Vector2.Distance(oldPoint, point), width);

                            track.AddElement(straight);
                        }

                        // Really part turn part straight
                        else
                        {
                            float maxWidth = width;
                            //TODO not only one width all the time

                            float minRadius = maxWidth + 0.8f;

                            float[] radiusAndDegree = makeTurn(oldPoint, point, oldDirection);

                            float circleRadius = radiusAndDegree[0];
                            float circleDegree = radiusAndDegree[1];


                            float maxRadius = Mathf.Max(circleRadius * 0.4f, minRadius);

                            float circlePartRadius = (maxRadius - minRadius) * ((segDec + 1f) * 0.5f) + minRadius;

                            float[] partcircleRadiusAndDegree = makeTurnFixedRadius(oldPoint, circlePartRadius, oldDirection, (circleDegree >= 0f), point);

                            float partcircleDegree   = partcircleRadiusAndDegree[0];
                            float partstraightLength = partcircleRadiusAndDegree[1];



                            int splinesAmount = (int)(Mathf.Abs(partcircleDegree) / 90f) + 1;

                            float degreeOneSpline = partcircleDegree / splinesAmount;

                            float tanValue = 360f / degreeOneSpline;
                            tanValue = Mathf.Abs((4f / 3f) * Mathf.Tan(Mathf.PI / (2f * tanValue)) * circlePartRadius);

                            Vector2 prevSplinePoint = oldPoint;

                            Debug.Log("Gonna do new");

                            for (int i = 0; i < splinesAmount; i++)
                            {
                                float   tempStartDir = oldDirection + i * degreeOneSpline * (Mathf.PI / 180f);
                                Vector2 midToPoint   = (new Vector2(Mathf.Cos(tempStartDir) * Mathf.Sign(partcircleDegree), -Mathf.Sin(tempStartDir) * Mathf.Sign(partcircleDegree))).normalized * circlePartRadius;

                                float   tempEndDir    = oldDirection + (i + 1) * degreeOneSpline * (Mathf.PI / 180f);
                                Vector2 midToEndpoint = (new Vector2(Mathf.Cos(tempEndDir) * Mathf.Sign(partcircleDegree), -Mathf.Sin(tempEndDir) * Mathf.Sign(partcircleDegree))).normalized * circlePartRadius;

                                Vector2 tempEndpoint = (prevSplinePoint + midToPoint) - midToEndpoint;

                                GeneratedBezSpline spline = new GeneratedBezSpline(new Vector3(prevSplinePoint.x, 0f, prevSplinePoint.y), tempStartDir, new Vector3(tempEndpoint.x, 0f, tempEndpoint.y), tempEndDir, width, width, tanValue, tanValue);

                                track.AddElement(spline);

                                prevSplinePoint = tempEndpoint;

                                //Debug.Log("Spline[" + i + "]");
                            }



                            GeneratedStraight straight = new GeneratedStraight(track.Elements[track.Elements.Length - 1].EndPosition, track.Elements[track.Elements.Length - 1].EndDirection, Vector2.Distance(point, new Vector2(track.Elements[track.Elements.Length - 1].EndPosition.x, track.Elements[track.Elements.Length - 1].EndPosition.z)), width);
                            //straight.AddCurb(new GeneratedCurb(0.1f, 0.9f, true, true, true));
                            track.AddElement(straight);


                            Vector2 bothEndPoint = new Vector2(straight.EndPosition.x, straight.EndPosition.z);
                            if (Vector2.Distance(bothEndPoint, point) > 1f)
                            {
                                track.Faulty = true;
                                Debug.LogError("Too big distance");
                            }
                        }
                    }
                }
            }

            // Drive to a fixed endpoint
            else
            {
                // Two turns one straight
                if (false)
                {
                    float[] angleStraightAndAngle = makeTwoTurnsOneStraight(oldPoint, point, oldDirection, endpointDirection, 1f, 0.5f, Mathf.Max(endpointWidth, width));
                    float   circle1Radius         = angleStraightAndAngle[0];
                    float   circle1Degree         = angleStraightAndAngle[1];
                    float   straightLegnth        = angleStraightAndAngle[2];
                    float   circle2Radius         = angleStraightAndAngle[3];
                    float   circle2Degree         = angleStraightAndAngle[4];

                    if (circle1Radius == 0f && circle1Degree == 0f && straightLegnth == 0f && circle2Degree == 0f && circle2Radius == 0f)
                    {
                        track.Faulty = true;
                    }
                    else
                    {
                        GeneratedTurn turn = new GeneratedTurn(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, circle1Radius, circle1Degree, width);
                        track.AddElement(turn);

                        GeneratedStraight straight = new GeneratedStraight(turn.EndPosition, turn.EndDirection, straightLegnth, width);
                        track.AddElement(straight);

                        GeneratedTurn turn2 = new GeneratedTurn(straight.EndPosition, straight.EndDirection, circle2Radius, circle2Degree, width);
                        track.AddElement(turn2);
                    }
                }


                // Do it with Beziers
                else
                {
                    GeneratedBezSpline turnSpline = new GeneratedBezSpline(new Vector3(oldPoint.x, 0f, oldPoint.y), oldDirection, new Vector3(point.x, 0f, point.y), endpointDirection, width, width);

                    track.AddElement(turnSpline);
                }
            }



            if (currentAngle >= 360f)
            {
                break;
            }
        }

        return(track);
    }
Ejemplo n.º 2
0
    public CurvatureAnalyzer(GeneratedTrack track, int sampleRate)
    {
        curvatureValues  = new float[sampleRate];
        trackPartIndices = new float[sampleRate];

        for (int i = 0; i < sampleRate; i++)
        {
            curvatureValues[i] = float.MaxValue;
        }
        float walkedDistance = 0f;

        for (int i = 0; i < track.Elements.Length; i++)
        {
            if (track.Elements[i].GetType() == typeof(GeneratedStraight))
            {
                GeneratedStraight straight = (GeneratedStraight)track.Elements[i];

                int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate);
                int endIndex   = (int)(((walkedDistance + straight.Length) / track.TrackLength) * sampleRate);

                for (int j = startIndex; j < endIndex; j++)
                {
                    curvatureValues[j]  = 0f;
                    trackPartIndices[j] = i + ((float)(j - startIndex)) / ((float)(endIndex - startIndex));
                }

                walkedDistance += straight.Length;
            }

            else if (track.Elements[i].GetType() == typeof(GeneratedTurn))
            {
                GeneratedTurn turn = (GeneratedTurn)track.Elements[i];

                int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate);
                int endIndex   = (int)(((walkedDistance + turn.Length) / track.TrackLength) * sampleRate);

                for (int j = startIndex; j < endIndex; j++)
                {
                    curvatureValues[j] = (1f / turn.Radius) * Mathf.Sign(turn.Degree);
                }

                walkedDistance += turn.Length;
            }

            else if (track.Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline spline = (GeneratedBezSpline)track.Elements[i];

                int startIndex = (int)((walkedDistance / track.TrackLength) * sampleRate);
                int endIndex   = (int)(((walkedDistance + spline.Length) / track.TrackLength) * sampleRate);

                for (int j = startIndex; j < endIndex; j++)
                {
                    Vector3 tangent1 = spline.Spline.TangentAt(((((float)j) - startIndex + 0f)) / (endIndex - startIndex))[1] - spline.Spline.TangentAt(((((float)j) - startIndex + 0f)) / (endIndex - startIndex))[0];
                    Vector3 tangent2 = spline.Spline.TangentAt(((((float)j) - startIndex + 1f)) / (endIndex - startIndex))[1] - spline.Spline.TangentAt(((((float)j) - startIndex + 1f)) / (endIndex - startIndex))[0];
                    Vector2 pos1     = new Vector2(spline.Spline.At(((((float)j) - startIndex + 0f)) / (endIndex - startIndex)).x, spline.Spline.At(((((float)j) - startIndex + 0f)) / (endIndex - startIndex)).z);
                    Vector2 pos2     = new Vector2(spline.Spline.At(((((float)j) - startIndex + 1f)) / (endIndex - startIndex)).x, spline.Spline.At(((((float)j) - startIndex + 1f)) / (endIndex - startIndex)).z);
                    Vector2 dir1     = new Vector2(tangent1.z, -tangent1.x);
                    Vector2 dir2     = new Vector2(tangent2.z, -tangent2.x);
                    Ray2D   ray1     = new Ray2D(pos1, dir1);
                    Ray2D   ray2     = new Ray2D(pos2, dir2);

                    Ray2D straightRay = new Ray2D(pos1, tangent1);

                    bool    parallel;
                    Vector2 intersect = Utils.Intersect2D(ray1, ray2, out parallel);
                    if (parallel)
                    {
                        curvatureValues[j] = 0f;
                    }
                    else
                    {
                        float radius = (Vector2.Distance(intersect, pos1) + Vector2.Distance(intersect, pos2)) * 0.5f;

                        curvatureValues[j] = (1f / radius) * (Utils.PointRightTo(straightRay, intersect) ? 1f : -1f);
                    }

                    trackPartIndices[j] = i + ((float)(j - startIndex)) / ((float)(endIndex - startIndex));
                }

                walkedDistance += spline.Length;
            }
        }


        int notSet = 0;

        for (int i = 0; i < sampleRate; i++)
        {
            if (curvatureValues[i] == float.MaxValue)
            {
                notSet++;
            }
        }

        Debug.Log("NotSet: " + notSet);
    }
Ejemplo n.º 3
0
    public DiscreteTrack(GeneratedTrack track, TerrainModifier terrainModifier)
    {
        List <Vector3> lefts        = new List <Vector3>();
        List <Vector3> rights       = new List <Vector3>();
        List <Vector3> leftsCurv    = new List <Vector3>();
        List <Vector3> rightsCurv   = new List <Vector3>();
        List <int>     indcs        = new List <int>();
        int            indcsCounter = 0;

        List <float> idealLineMeshList = new List <float>();
        int          idLineMeshCounter = 0;

        for (int i = 0; i < track.Elements.Length; i++)
        {
            if (track.Elements[i].GetType() == typeof(GeneratedStraight))
            {
                Vector3 middle = track.Elements[i].Position;

                Vector3 toRight = (new Vector3(Mathf.Cos(track.Elements[i].Direction), 0f, -Mathf.Sin(track.Elements[i].Direction))).normalized;
                Vector3 toFront = (new Vector3(Mathf.Sin(track.Elements[i].Direction), 0f, Mathf.Cos(track.Elements[i].Direction))).normalized;

                lefts.Add(middle - toRight * track.Elements[i].WidthStart);
                rights.Add(middle + toRight * track.Elements[i].WidthStart);
                indcsCounter = -1;

                GeneratedStraight straight = (GeneratedStraight)track.Elements[i];
                int segsAmount             = (int)(straight.Length / straightSegmentingFactorIdealline);

                int segmentsAmountMesh = (int)(straight.Length / straightSegmentingFactorMesh);
                for (int j = 0; j < segmentsAmountMesh; j++)
                {
                    //idealLineMesh[idLineMeshCounter] = 1f;
                    idealLineMeshList.Add(1f);
                    idLineMeshCounter++;
                }

                for (int j = 0; j < segsAmount; j++)
                {
                    leftsCurv.Add(middle - toRight * track.Elements[i].WidthStart + toFront * straight.Length * (((float)j) / ((float)segsAmount)));
                    rightsCurv.Add(middle + toRight * track.Elements[i].WidthStart + toFront * straight.Length * (((float)j) / segsAmount));
                    indcsCounter++;
                }

                indcs.Add(indcsCounter);
            }
            else if (track.Elements[i].GetType() == typeof(GeneratedTurn))
            {
                GeneratedTurn turn = (GeneratedTurn)track.Elements[i];

                bool rightTurn = turn.Degree >= 0f;

                Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f));
                Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f));

                Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f);

                int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / 30f)) + 1;

                for (int j = 0; j < segmentsAmount; j++)
                {
                    Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight;

                    Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius);

                    float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart;

                    lefts.Add(segmentPos + toRightTurned * currentWidth * -1f + turn.Position);
                    rights.Add(segmentPos + toRightTurned * currentWidth + turn.Position);
                    leftsCurv.Add(segmentPos + toRightTurned * currentWidth * -1f + turn.Position);
                    rightsCurv.Add(segmentPos + toRightTurned * currentWidth + turn.Position);
                    indcs.Add(0);
                }
            }
            else if (track.Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline bezierSpline = (GeneratedBezSpline)track.Elements[i];

                for (int j = 0; j < bezierSpline.RenderVertsLeft.Length - 1; j++)
                {
                    if (j == 0)
                    {
                        //idealLineMesh[idLineMeshCounter] = 2f;
                        idealLineMeshList.Add(2f);
                    }
                    else
                    {
                        //idealLineMesh[idLineMeshCounter] = 0f;
                        idealLineMeshList.Add(0f);
                    }
                    idLineMeshCounter++;

                    if (j % 3 == 0)
                    {
                        lefts.Add(bezierSpline.RenderVertsLeft[j]);
                        rights.Add(bezierSpline.RenderVertsRight[j]);
                        leftsCurv.Add(bezierSpline.RenderVertsLeft[j]);
                        rightsCurv.Add(bezierSpline.RenderVertsRight[j]);
                        indcs.Add(0);
                    }
                }
            }
        }

        idealLineMesh = idealLineMeshList.ToArray();

        leftPoints                 = lefts.ToArray();
        rightPoints                = rights.ToArray();
        leftPointsCurv             = leftsCurv.ToArray();
        rightPointsCurv            = rightsCurv.ToArray();
        indcsFromPathIntoCurvature = indcs.ToArray();

        shortestPathTrajectory = minimizePathTrajectory();
        if (false)
        {
            for (int i = 0; i < leftPoints.Length; i++)
            {
                int i2 = (i + 1) % leftPoints.Length;
                Debug.DrawLine(leftPoints[i], leftPoints[i2], Color.white, 10000f);
                Debug.DrawLine(rightPoints[i], rightPoints[i2], Color.white, 10000f);
                Debug.DrawLine(leftPoints[i], rightPoints[i], Color.white, 10000f);


                Debug.DrawLine(shortestPathTrajectory[i] * (leftPoints[i] - rightPoints[i]) + rightPoints[i], shortestPathTrajectory[i2] * (leftPoints[i2] - rightPoints[i2]) + rightPoints[i2], Color.green, 10000f);
            }
        }

        minimumCurvatureTrajectory = minimizeCurvatureTrajectory();

        if (false)
        {
            for (int i = 0; i < leftPointsCurv.Length; i++)
            {
                int i2 = (i + 1) % leftPointsCurv.Length;
                Debug.DrawLine(leftPointsCurv[i], leftPointsCurv[i2], Color.white, 10000f);
                Debug.DrawLine(rightPointsCurv[i], rightPointsCurv[i2], Color.white, 10000f);
                Debug.DrawLine(leftPointsCurv[i], rightPointsCurv[i], Color.white, 10000f);


                Debug.DrawLine(minimumCurvatureTrajectory[i] * (leftPointsCurv[i] - rightPointsCurv[i]) + rightPointsCurv[i], minimumCurvatureTrajectory[i2] * (leftPointsCurv[i2] - rightPointsCurv[i2]) + rightPointsCurv[i2], Color.green, 10000f);
            }
        }

        float epsilon = 0.1f;

        idealLine = applyEpsilon(shortestPathTrajectory, minimumCurvatureTrajectory, epsilon, indcsFromPathIntoCurvature);

        /*for (int i = 0; i < idealLine.Length; i++)
         * {
         *  Debug.Log("IL [" + i + "]: " + idealLine[i]);
         * }*/

        Debug.Log("cnter: " + idLineMeshCounter);

        transferToMeshIdealLine(track, idealLine, idealLineMesh);

        List <float>   cpsBankAngles  = new List <float>();
        List <Vector3> cpsMinDistance = new List <Vector3>();
        float          minDistance    = 15f;

        Vector3[] cps     = new Vector3[idealLine.Length];
        float[]   cpsBank = new float[idealLine.Length];
        cpsMinDistance.Add(idealLine[0] * (leftPointsCurv[0] - rightPointsCurv[0]) + rightPointsCurv[0]);
        for (int i = 1; i < idealLine.Length; i++)
        {
            Vector3 point = idealLine[i] * (leftPointsCurv[i] - rightPointsCurv[i]) + rightPointsCurv[i];
            //cps[i] = point;
            if (Vector3.Distance(cpsMinDistance[cpsMinDistance.Count - 1], point) > minDistance)
            {
                cpsBankAngles.Add(Vector3.Angle(new Vector3(rightPointsCurv[i].x - leftPointsCurv[i].x, terrainModifier.GetTensorHeight(rightPointsCurv[i].x, rightPointsCurv[i].z) - terrainModifier.GetTensorHeight(leftPointsCurv[i].x, leftPointsCurv[i].z), rightPointsCurv[i].z - leftPointsCurv[i].z), new Vector3((rightPointsCurv[i] - leftPointsCurv[i]).x, 0f, (rightPointsCurv[i] - leftPointsCurv[i]).z)) * Mathf.Sign((rightPointsCurv[i] - leftPointsCurv[i]).y));
                cpsMinDistance.Add(point);
            }
        }

        cps     = cpsMinDistance.ToArray();
        cpsBank = cpsBankAngles.ToArray();

        for (int i = 0; i < cps.Length; i++)
        {
            cps[i] = new Vector3(cps[i].x, terrainModifier.GetTensorHeight(cps[i].x, cps[i].z), cps[i].z);
        }

        idealLineSpline = new ClosedSpline <Vector3>(cps);
        ClosedSpline <float> bankSpline = new ClosedSpline <float>(cpsBank);

        curvatureAnalyzer = new CurvatureAnalyzer(idealLineSpline, 300);

        speedAnalyzer = new SpeedAnalyzer(idealLineSpline, bankSpline, curvatureAnalyzer, 300);

        curvatureAnalyzerTrack = new CurvatureAnalyzer(track, 300);

        curvatureIdealLineAnalyzer = new CurvatureIdeallineAnalyzer(idealLineSpline);

        float startFinishLength = 500f;
        float partStartFinish   = startFinishLength / track.TrackLength;

        int elementsStartFinishAmount = (int)(idealLineSpline.ControlPointsAmount * partStartFinish);

        elementsStartFinishAmount = (int)(partStartFinish * 300f);

        int startFinishIndex = minCurvatureForAmount(curvatureAnalyzerTrack.Curvature, elementsStartFinishAmount);

        float partpart = curvatureAnalyzerTrack.trackPartIndices[startFinishIndex];

        //Vector3 beginStartFinishPoint = idealLineSpline.controlPoints[startFinishIndex];

        Debug.Log("Start Finish point: " + partpart);


        int     elementStartFinishBeginIndex = (int)partpart;
        Vector3 elementStartPos = track.Elements[elementStartFinishBeginIndex].Position;

        startFinishLineIndex = partpart;
        //Debug.Log("Start Finish point: " + elementStartPos);
    }
Ejemplo n.º 4
0
    public void GenerateMesh()
    {
        // right Track Vertices
        List <Vector2> rT = new List <Vector2>();
        // left Track Vertices
        List <Vector2> lT = new List <Vector2>();
        // right Grass Vertices
        List <Vector2> rG = new List <Vector2>();
        // right Grass Vertices
        List <Vector2> lG = new List <Vector2>();


        /*if (Elements[0].GetType() == typeof(GeneratedStraight))
         * {
         *  GeneratedStraight straight = (GeneratedStraight)Elements[0];
         *
         *  Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthStart, 0f, 0f));
         *
         *  lT.Add(new Vector2((straight.Position - toRight).x, (straight.Position - toRight).z));
         *  rT.Add(new Vector2((straight.Position + toRight).x, (straight.Position + toRight).z));
         *
         * }
         * else if (Elements[0].GetType() == typeof(GeneratedTurn))
         * {
         *  GeneratedTurn turn = (GeneratedTurn)Elements[0];
         *
         *  Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(turn.WidthStart, 0f, 0f));
         *
         *  lT.Add(new Vector2((turn.Position - toRight).x, (turn.Position - toRight).z));
         *  rT.Add(new Vector2((turn.Position + toRight).x, (turn.Position + toRight).z));
         * }
         * else if (Elements[0].GetType() == typeof(GeneratedBezSpline))
         * {
         *  GeneratedBezSpline bezSpline = (GeneratedBezSpline)Elements[0];
         *
         *  lT.Add(new Vector2((bezSpline.RenderVertsLeft[0]).x, (bezSpline.RenderVertsLeft[0]).z));
         *  rT.Add(new Vector2((bezSpline.RenderVertsRight[0]).x, (bezSpline.RenderVertsRight[0]).z));
         * }*/


        for (int i = 0; i < Elements.Length; i++)
        {
            if (Elements[i].GetType() == typeof(GeneratedStraight))
            {
                GeneratedStraight straight = (GeneratedStraight)Elements[i];

                Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthEnd, 0f, 0f));
                Vector3 toFront = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, straight.Length));


                int segmentsAmount = (int)(straight.Length / DiscreteTrack.straightSegmentingFactorMesh);

                for (int j = 1; j <= segmentsAmount; j++)
                {
                    float s = ((float)j) / segmentsAmount;


                    lT.Add(new Vector2((straight.Position + (toFront * s) - toRight).x, (straight.Position + (toFront * s) - toRight).z));
                    rT.Add(new Vector2((straight.Position + (toFront * s) + toRight).x, (straight.Position + (toFront * s) + toRight).z));

                    /*
                     *  -2    -1
                     *   x-----x
                     *   |\    |
                     *   | \   |  / \
                     *   |  \  |   |  Drive Direction
                     *   |   \ |   |
                     *   |    \|
                     *   x-----x
                     *  -4    -3
                     *
                     * */
                }
            }
            else if (Elements[i].GetType() == typeof(GeneratedTurn))
            {
                GeneratedTurn turn = (GeneratedTurn)Elements[i];

                bool rightTurn = turn.Degree >= 0f;

                Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f));
                Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f));

                Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f);

                int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / maxTurnDegreeResolution)) + 1;

                for (int j = 1; j <= segmentsAmount; j++)
                {
                    Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight;

                    Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius);

                    float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart;

                    lT.Add(new Vector2((segmentPos + toRightTurned * currentWidth * -1f + turn.Position).x, (segmentPos + toRightTurned * currentWidth * -1f + turn.Position).z));
                    rT.Add(new Vector2((segmentPos + toRightTurned * currentWidth + turn.Position).x, (segmentPos + toRightTurned * currentWidth + turn.Position).z));
                }
            }
            else if (Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline bezierSpline = (GeneratedBezSpline)Elements[i];

                for (int j = 1; j < bezierSpline.RenderVertsLeft.Length; j++)
                {
                    lT.Add(new Vector2((bezierSpline.RenderVertsLeft[j]).x, (bezierSpline.RenderVertsLeft[j]).z));
                    rT.Add(new Vector2((bezierSpline.RenderVertsRight[j]).x, (bezierSpline.RenderVertsRight[j]).z));
                }
            }
        }



        // Cutting of the overlapping segments

        List <RenderVertexShortcut> lSCs = calculateShortcuts(lT);
        List <RenderVertexShortcut> rSCs = calculateShortcuts(rT);

        for (int i = 0; i < lSCs.Count; i++)
        {
            RenderVertexShortcut rvs = lSCs[i];
            for (int j = rvs.indexBefore + 1; j < (rvs.indexAfter < rvs.indexBefore ? lT.Count : rvs.indexAfter); j++)
            {
                lT[j] = rvs.intersectPoint;
            }
            for (int j = 0; j < (rvs.indexAfter < rvs.indexBefore ? rvs.indexAfter : 0); j++)
            {
                lT[j] = rvs.intersectPoint;
            }
        }
        for (int i = 0; i < rSCs.Count; i++)
        {
            RenderVertexShortcut rvs = rSCs[i];
            for (int j = rvs.indexBefore + 1; j < (rvs.indexAfter < rvs.indexBefore ? rT.Count : rvs.indexAfter); j++)
            {
                rT[j] = rvs.intersectPoint;
            }
            for (int j = 0; j < (rvs.indexAfter < rvs.indexBefore ? rvs.indexAfter : 0); j++)
            {
                rT[j] = rvs.intersectPoint;
            }
        }



        float grassWidth = 8f;

        List <Vector2> lGFull = new List <Vector2>();
        List <Vector2> rGFull = new List <Vector2>();

        for (int i = 0; i < lT.Count; i++)
        {
            int i0 = (i - 1) < 0 ? lT.Count - 1 : i - 1;
            int i2 = (i + 1) % lT.Count;

            Vector2 tangentLeft  = lT[i2] - lT[i0];
            Vector2 newVLeft     = (new Vector2(-tangentLeft.y, tangentLeft.x)).normalized * grassWidth + lT[i];
            Vector2 tangentRight = rT[i2] - rT[i0];
            Vector2 newVRight    = (new Vector2(tangentRight.y, -tangentRight.x)).normalized * grassWidth + rT[i];

            Vector2 vLeft  = (lT[i] - rT[i]).normalized * grassWidth + lT[i];
            Vector2 vRight = (rT[i] - lT[i]).normalized * grassWidth + rT[i];

            lG.Add(newVLeft);
            rG.Add(newVRight);
            lGFull.Add(newVLeft);
            rGFull.Add(newVRight);
        }

        int grassPlanesNewStartIndex = -1;

        if (discreteTrack != null)
        {
            Vector2 startFinishPos = new Vector2(elements[(int)discreteTrack.startFinishLineIndex].Position.x, elements[(int)discreteTrack.startFinishLineIndex].Position.z);


            float minDistance = float.MaxValue;

            for (int i = 0; i < lGFull.Count; i++)
            {
                if (Vector2.Distance(lGFull[i], startFinishPos) < minDistance)
                {
                    grassPlanesNewStartIndex = i;
                    minDistance = Vector2.Distance(lGFull[i], startFinishPos);
                }
            }

            Debug.Log("Grass start index: " + grassPlanesNewStartIndex);

            List <Vector2> lGFullNew = new List <Vector2>();
            List <Vector2> rGFullNew = new List <Vector2>();
            List <Vector2> rTNew     = new List <Vector2>();
            List <Vector2> lTNew     = new List <Vector2>();
            List <Vector2> rGNew     = new List <Vector2>();
            List <Vector2> lGNew     = new List <Vector2>();

            for (int i = 0; i < lGFull.Count; i++)
            {
                lGFullNew.Add(lGFull[(i + grassPlanesNewStartIndex) % lGFull.Count]);
                lTNew.Add(lT[(i + grassPlanesNewStartIndex) % lGFull.Count]);
                lGNew.Add(lG[(i + grassPlanesNewStartIndex) % lGFull.Count]);

                rGFullNew.Add(rGFull[(i + grassPlanesNewStartIndex) % lGFull.Count]);
                rTNew.Add(rT[(i + grassPlanesNewStartIndex) % lGFull.Count]);
                rGNew.Add(rG[(i + grassPlanesNewStartIndex) % lGFull.Count]);
            }

            lGFull = lGFullNew;
            rGFull = rGFullNew;
            rT     = rTNew;
            lT     = lTNew;
            lG     = lGNew;
            rG     = rGNew;
        }



        // Curbs


        curbsGenerator = new CurbsGenerator(lT.ToArray(), rT.ToArray(), grassPlanesNewStartIndex);

        curbsGenerator.CalculateCurbs(discreteTrack);



        /*lGFull.Add(lGFull[0]);
         * rGFull.Add(rGFull[0]);
         * lG.Add(lG[0]);
         * rG.Add(rG[0]);
         * lT.Add(lT[0]);
         * rT.Add(rT[0]);*/



        // Generating the grass zones on the sides

        List <GeneratedGrassPlane> grassplanes = new List <GeneratedGrassPlane>();


        GeneratedPlaneElement[] leftGrassPlanes  = generateGrassplanes(lGFull, lG, lT, 0, 0, 0);
        GeneratedPlaneElement[] rightGrassPlanes = generateGrassplanes(rGFull, rG, rT, 0, 0, 0);
        GeneratedPlaneElement[] combinedPlanes   = new GeneratedPlaneElement[leftGrassPlanes.Length + rightGrassPlanes.Length];
        for (int i = 0; i < leftGrassPlanes.Length; i++)
        {
            combinedPlanes[i] = leftGrassPlanes[i];
        }
        for (int i = 0; i < rightGrassPlanes.Length; i++)
        {
            combinedPlanes[i + leftGrassPlanes.Length] = rightGrassPlanes[i];
        }



        // Track vertices

        List <Vector3> vertices  = new List <Vector3>();
        List <int>     triangles = new List <int>();
        List <Vector2> uvs       = new List <Vector2>();

        float rightUvCounter = 0f;
        float leftUvCounter  = 0f;

        vertices.Add(new Vector3(lT[0].x, 0f, lT[0].y));
        uvs.Add(new Vector2(0f, leftUvCounter));
        vertices.Add(new Vector3(rT[0].x, 0f, rT[0].y));
        uvs.Add(new Vector2(1f, rightUvCounter));
        for (int i = 1; i < lT.Count; i++)
        {
            vertices.Add(new Vector3(lT[i].x, 0f, lT[i].y));
            leftUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f);
            uvs.Add(new Vector2(0f, leftUvCounter));
            vertices.Add(new Vector3(rT[i].x, 0f, rT[i].y));
            rightUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f);
            uvs.Add(new Vector2(1f, rightUvCounter));

            triangles.Add(vertices.Count - 4);
            triangles.Add(vertices.Count - 2);
            triangles.Add(vertices.Count - 3);
            triangles.Add(vertices.Count - 2);
            triangles.Add(vertices.Count - 1);
            triangles.Add(vertices.Count - 3);
        }


        vertices.Add(new Vector3(lT[0].x, 0f, lT[0].y));
        leftUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f);
        uvs.Add(new Vector2(0f, leftUvCounter));
        vertices.Add(new Vector3(rT[0].x, 0f, rT[0].y));
        rightUvCounter += (Vector3.Distance(vertices[vertices.Count - 3], vertices[vertices.Count - 1])) * (1f / 16f);
        uvs.Add(new Vector2(1f, rightUvCounter));

        triangles.Add(vertices.Count - 4);
        triangles.Add(vertices.Count - 2);
        triangles.Add(vertices.Count - 3);
        triangles.Add(vertices.Count - 2);
        triangles.Add(vertices.Count - 1);
        triangles.Add(vertices.Count - 3);



        RenderVerticesTrack  = vertices.ToArray();
        RenderTrianglesTrack = triangles.ToArray();
        RenderUVsTrack       = uvs.ToArray();


        // Grass vertices

        List <GeneratedGrassPlane> leftGrass = new List <GeneratedGrassPlane>();

        for (int i = 0; i < leftGrassPlanes.Length; i++)
        {
            GeneratedGrassPlane plane = new GeneratedGrassPlane();

            List <Vector3> verticesOutside    = new List <Vector3>();
            List <Vector3> directionsOutside  = new List <Vector3>();
            List <Vector3> verticesGrassLeft  = new List <Vector3>();
            List <int>     trianglesGrassLeft = new List <int>();
            List <Vector2> uvsGrassLeft       = new List <Vector2>();

            if (leftGrassPlanes[i].GetType() == typeof(GeneratedGrassPlane2D))
            {
                GeneratedGrassPlane2D ggp2d = (GeneratedGrassPlane2D)leftGrassPlanes[i];

                verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));

                verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                uvsGrassLeft.Add(ggp2d.vertices[0]);
                verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + 0].x, 0f, lT[ggp2d.trackStartIndex + 0].y));
                verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + 0]));
                uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + 0]);

                directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);

                for (int j = 1; j < ggp2d.vertices.Count; j++)
                {
                    bool locked = false;
                    for (int k = 0; k < ggp2d.jumpIndices.Count; k++)
                    {
                        if (j + ggp2d.trackStartIndex >= ggp2d.jumpIndices[k] && j + ggp2d.trackStartIndex < ggp2d.jumpIndices[k] + ggp2d.jumpWidths[k])
                        {
                            locked = true;
                        }
                    }


                    if (!locked)
                    {
                        verticesOutside.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y));

                        verticesGrassLeft.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y));
                        uvsGrassLeft.Add(ggp2d.vertices[j]);
                        verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + j].x, 0f, lT[ggp2d.trackStartIndex + j].y));
                        verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + j]));
                        uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + j]);

                        directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);

                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 4);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 1);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                    }
                }

                verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                uvsGrassLeft.Add(ggp2d.vertices[0]);
                verticesGrassLeft.Add(new Vector3(lT[ggp2d.trackStartIndex + 0].x, 0f, lT[ggp2d.trackStartIndex + 0].y));
                verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.LeftWidths[ggp2d.trackStartIndex + 0]));
                uvsGrassLeft.Add(lT[ggp2d.trackStartIndex + 0]);
                directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 4);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 1);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);



                plane.vertices          = verticesGrassLeft.ToArray();
                plane.triangles         = trianglesGrassLeft.ToArray();
                plane.uvs               = uvsGrassLeft.ToArray();
                plane.AllowBordercross  = true;
                plane.verticesOutside   = verticesOutside.ToArray();
                plane.directionsOutside = directionsOutside.ToArray();

                leftGrass.Add(plane);
            }
            else
            {
                GeneratedPlaneBetween gpb = (GeneratedPlaneBetween)leftGrassPlanes[i];

                for (int j = 0; j < gpb.vertices.Count; j++)
                {
                    verticesGrassLeft.Add(new Vector3(gpb.vertices[j].x, 0f, gpb.vertices[j].y));
                    uvsGrassLeft.Add(gpb.vertices[j]);
                }

                plane.vertices  = verticesGrassLeft.ToArray();
                plane.triangles = gpb.triangles.ToArray();
                plane.uvs       = uvsGrassLeft.ToArray();

                leftGrass.Add(plane);
            }
        }

        for (int i = 0; i < rightGrassPlanes.Length; i++)
        {
            GeneratedGrassPlane plane = new GeneratedGrassPlane();

            List <Vector3> verticesOutside    = new List <Vector3>();
            List <Vector3> directionsOutside  = new List <Vector3>();
            List <Vector3> verticesGrassLeft  = new List <Vector3>();
            List <int>     trianglesGrassLeft = new List <int>();
            List <Vector2> uvsGrassLeft       = new List <Vector2>();

            if (rightGrassPlanes[i].GetType() == typeof(GeneratedGrassPlane2D))
            {
                GeneratedGrassPlane2D ggp2d = (GeneratedGrassPlane2D)rightGrassPlanes[i];

                verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));

                verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                uvsGrassLeft.Add(ggp2d.vertices[0]);
                verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + 0].x, 0f, rT[ggp2d.trackStartIndex + 0].y));
                verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + 0]));
                uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + 0]);

                directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);

                for (int j = 1; j < ggp2d.vertices.Count; j++)
                {
                    bool locked = false;
                    for (int k = 0; k < ggp2d.jumpIndices.Count; k++)
                    {
                        if (j + ggp2d.trackStartIndex >= ggp2d.jumpIndices[k] && j + ggp2d.trackStartIndex < ggp2d.jumpIndices[k] + ggp2d.jumpWidths[k])
                        {
                            locked = true;
                        }
                    }


                    if (!locked)
                    {
                        verticesOutside.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y));

                        verticesGrassLeft.Add(new Vector3(ggp2d.vertices[j].x, 0f, ggp2d.vertices[j].y));
                        uvsGrassLeft.Add(ggp2d.vertices[j]);
                        verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + j].x, 0f, rT[ggp2d.trackStartIndex + j].y));
                        verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + j]));
                        uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + j]);

                        directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);

                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 4);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                        trianglesGrassLeft.Add(verticesGrassLeft.Count - 1);
                    }
                }
                verticesOutside.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                verticesGrassLeft.Add(new Vector3(ggp2d.vertices[0].x, 0f, ggp2d.vertices[0].y));
                uvsGrassLeft.Add(ggp2d.vertices[0]);
                verticesGrassLeft.Add(new Vector3(rT[ggp2d.trackStartIndex + 0].x, 0f, rT[ggp2d.trackStartIndex + 0].y));
                verticesGrassLeft[verticesGrassLeft.Count - 1] = verticesGrassLeft[verticesGrassLeft.Count - 2] + ((verticesGrassLeft[verticesGrassLeft.Count - 1] - verticesGrassLeft[verticesGrassLeft.Count - 2]).normalized * (Vector3.Distance(verticesGrassLeft[verticesGrassLeft.Count - 1], verticesGrassLeft[verticesGrassLeft.Count - 2]) - curbsGenerator.RightWidths[ggp2d.trackStartIndex + 0]));
                uvsGrassLeft.Add(rT[ggp2d.trackStartIndex + 0]);
                directionsOutside.Add((verticesGrassLeft[verticesGrassLeft.Count - 2] - verticesGrassLeft[verticesGrassLeft.Count - 1]).normalized);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 4);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 2);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 3);
                trianglesGrassLeft.Add(verticesGrassLeft.Count - 1);



                plane.vertices          = verticesGrassLeft.ToArray();
                plane.triangles         = trianglesGrassLeft.ToArray();
                plane.uvs               = uvsGrassLeft.ToArray();
                plane.AllowBordercross  = true;
                plane.verticesOutside   = verticesOutside.ToArray();
                plane.directionsOutside = directionsOutside.ToArray();

                leftGrass.Add(plane);
            }
            else
            {
                GeneratedPlaneBetween gpb = (GeneratedPlaneBetween)rightGrassPlanes[i];

                for (int j = 0; j < gpb.vertices.Count; j++)
                {
                    verticesGrassLeft.Add(new Vector3(gpb.vertices[j].x, 0f, gpb.vertices[j].y));
                    uvsGrassLeft.Add(gpb.vertices[j]);
                }
                for (int j = 0; j < gpb.triangles.Count; j += 3)
                {
                    trianglesGrassLeft.Add(gpb.triangles[j]);
                    trianglesGrassLeft.Add(gpb.triangles[j + 2]);
                    trianglesGrassLeft.Add(gpb.triangles[j + 1]);
                }

                plane.vertices         = verticesGrassLeft.ToArray();
                plane.triangles        = trianglesGrassLeft.ToArray();
                plane.uvs              = uvsGrassLeft.ToArray();
                plane.AllowBordercross = false;

                leftGrass.Add(plane);
            }
        }

        GrassPlanes = leftGrass.ToArray();
    }
Ejemplo n.º 5
0
    public BorderGenerator(TerrainModifier terrainModifier, List <GeneratedElement> elements, float startFinishLineIndex)
    {
        leftWall  = new List <Vector3>();
        rightWall = new List <Vector3>();

        List <Vector2> left  = new List <Vector2>();
        List <Vector2> right = new List <Vector2>();

        int startIndex = (int)startFinishLineIndex;

        for (int i = 0; i < elements.Count; i++)
        {
            if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedStraight))
            {
                GeneratedStraight straight = (GeneratedStraight)elements[(i + startIndex) % elements.Count];

                Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthEnd, 0f, 0f));
                Vector3 toFront = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, straight.Length));


                int segmentsAmount = (int)(straight.Length / 4f);

                for (int j = 1; j <= segmentsAmount; j++)
                {
                    float s = ((float)j) / segmentsAmount;


                    left.Add(new Vector2((straight.Position + (toFront * s) - toRight - (toRight.normalized * fixDistance)).x, (straight.Position + (toFront * s) - toRight - (toRight.normalized * fixDistance)).z));
                    right.Add(new Vector2((straight.Position + (toFront * s) + toRight + (toRight.normalized * fixDistance)).x, (straight.Position + (toFront * s) + toRight + (toRight.normalized * fixDistance)).z));
                }
            }
            else if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedTurn))
            {
                GeneratedTurn turn = (GeneratedTurn)elements[(i + startIndex) % elements.Count];

                bool rightTurn = turn.Degree >= 0f;

                Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(1f, 0f, 0f));
                Vector3 toFront = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(0f, 0f, 1f));

                Vector3 middlePoint = toRight * turn.Radius * (rightTurn ? 1f : -1f);

                int segmentsAmount = ((int)(Mathf.Abs(turn.Degree) / maxTurnDegreeResolution)) + 1;

                for (int j = 1; j <= segmentsAmount; j++)
                {
                    Vector3 toRightTurned = (Quaternion.Euler(0f, (turn.Degree / ((float)segmentsAmount)) * j, 0f)) * toRight;

                    Vector3 segmentPos = middlePoint + (toRightTurned * (rightTurn ? -1f : 1f) * turn.Radius);

                    float currentWidth = (turn.WidthEnd - turn.WidthStart) * (float)((float)j / (float)segmentsAmount) + turn.WidthStart;


                    left.Add(new Vector2((segmentPos + toRightTurned * currentWidth * -1f + (toRightTurned.normalized * fixDistance * -1f) + turn.Position).x, (segmentPos + toRightTurned * currentWidth * -1f + (toRightTurned.normalized * fixDistance * -1f) + turn.Position).z));
                    right.Add(new Vector2((segmentPos + toRightTurned * currentWidth + (toRightTurned.normalized * fixDistance) + turn.Position).x, (segmentPos + toRightTurned * currentWidth + (toRightTurned.normalized * fixDistance) + turn.Position).z));
                }
            }
            else if (elements[(i + startIndex) % elements.Count].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline bezierSpline = (GeneratedBezSpline)elements[(i + startIndex) % elements.Count];

                for (int j = 1; j < bezierSpline.RenderVertsLeft.Length; j++)
                {
                    Vector3 toRight = (bezierSpline.RenderVertsRight[j] - bezierSpline.RenderVertsLeft[j]).normalized;


                    left.Add(new Vector2((bezierSpline.RenderVertsLeft[j] + (toRight * -fixDistance)).x, (bezierSpline.RenderVertsLeft[j] + (toRight * -fixDistance)).z));
                    right.Add(new Vector2((bezierSpline.RenderVertsRight[j] + (toRight * fixDistance)).x, (bezierSpline.RenderVertsRight[j] + (toRight * fixDistance)).z));
                }
            }
        }


        bool[] leftIgnores  = new bool[left.Count];
        bool[] rightIgnores = new bool[right.Count];
        for (int i = 0; i < leftIgnores.Length; i++)
        {
            leftIgnores[i] = false;
        }
        for (int i = 0; i < rightIgnores.Length; i++)
        {
            rightIgnores[i] = false;
        }


        for (int i = 0; i < left.Count; i++)
        {
            int  i2         = (i + 1) % left.Count;
            Line lineToTest = new Line(left[i % left.Count], left[i2]);

            int jumpIndex = -1;

            for (int jT = 0 + 2; jT < left.Count - 40; jT++)
            {
                int j  = (jT + i) % left.Count;
                int j2 = (j + 1) % left.Count;
                if (leftIgnores[j] == false)
                {
                    Line other = new Line(left[j], left[j2]);

                    Vector2 intersectPoint;
                    if (lineToTest.Intersects(other, out intersectPoint))
                    {
                        jumpIndex = (j < i ? j + left.Count : j);
                        break;
                    }
                }
            }

            leftWall.Add(new Vector3(left[i].x, terrainModifier.GetTensorHeight(left[i].x, left[i].y), left[i].y));
            if (jumpIndex != -1)
            {
                for (int k = i; k < jumpIndex; k++)
                {
                    leftIgnores[k % leftIgnores.Length] = true;
                }

                i = jumpIndex;
                leftWall.Add(new Vector3(left[i % left.Count].x, terrainModifier.GetTensorHeight(left[i % left.Count].x, left[i % left.Count].y), left[i % left.Count].y));
            }
        }


        for (int i = 0; i < right.Count; i++)
        {
            int  i2         = (i + 1) % right.Count;
            Line lineToTest = new Line(right[i], right[i2]);

            int jumpIndex = -1;

            for (int jT = 0 + 2; jT < right.Count - 40; jT++)
            {
                int j  = (jT + i) % right.Count;
                int j2 = (j + 1) % right.Count;
                if (rightIgnores[j] == false)
                {
                    Line other = new Line(right[j], right[j2]);

                    Vector2 intersectPoint;
                    if (lineToTest.Intersects(other, out intersectPoint))
                    {
                        jumpIndex = (j < i ? j + right.Count : j);
                        break;
                    }
                }
            }

            rightWall.Add(new Vector3(right[i].x, terrainModifier.GetTensorHeight(right[i].x, right[i].y), right[i].y));
            if (jumpIndex != -1)
            {
                for (int k = i; k < jumpIndex; k++)
                {
                    rightIgnores[k % rightIgnores.Length] = true;
                }

                i = jumpIndex;
                rightWall.Add(new Vector3(right[i % right.Count].x, terrainModifier.GetTensorHeight(right[i % right.Count].x, right[i % right.Count].y), right[i % right.Count].y));
            }
        }
    }
Ejemplo n.º 6
0
    public override GeneratedElement Copy()
    {
        GeneratedTurn copy = new GeneratedTurn(position, direction, radius, degree, widthStart, widthEnd);

        return(copy);
    }