Exemple #1
0
    private void transferToMeshIdealLine(GeneratedTrack track, float[] idealline, float[] ideallineMeshp)
    {
        int idLineMeshCounter = 0;
        int idLineCounter     = 0;

        for (int i = 0; i < track.Elements.Length; i++)
        {
            if (track.Elements[i].GetType() == typeof(GeneratedStraight))
            {
                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++)
                {
                    float s        = ((float)j) / segmentsAmountMesh;
                    int   bef      = (int)(s * segsAmount);
                    int   aft      = bef + 1;
                    float partialS = aft - (s * segsAmount);

                    ideallineMeshp[idLineMeshCounter] = idealline[bef + idLineCounter] * partialS + idealline[aft + idLineCounter] * (1f - partialS);
                    idLineMeshCounter++;
                }

                idLineCounter += segsAmount;
            }
            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 % 3 == 0 && idLineMeshCounter < ideallineMeshp.Length)
                    {
                        ideallineMeshp[idLineMeshCounter] = idealline[idLineCounter];
                        idLineMeshCounter++;
                        idLineCounter++;
                    }
                    else if (j % 3 == 1 && (idLineCounter + 1) < idealline.Length && idLineMeshCounter < ideallineMeshp.Length)
                    {
                        ideallineMeshp[idLineMeshCounter] = idealline[idLineCounter] * (2f / 3f) + idealline[idLineCounter + 1] * (1f / 3f);
                        idLineMeshCounter++;
                    }
                    else if (j % 3 == 2 && (idLineCounter + 1) < idealline.Length && idLineMeshCounter < ideallineMeshp.Length)
                    {
                        ideallineMeshp[idLineMeshCounter] = idealline[idLineCounter] * (1f / 3f) + idealline[idLineCounter + 1] * (2f / 3f);
                        idLineMeshCounter++;
                    }
                }
            }

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

        /*for (int i = 0; i < ideallineMeshp.Length; i++)
         * {
         *  Debug.Log("IdlLineMsh [" + i + "]: " + ideallineMeshp[i]);
         * }*/
    }
    public void InsertInbetween(bool straight)
    {
        int insertIndex = recentlyHovered.GetComponent <InteractiveCheckpoint>().ElementsIndex;
        int indexBefore = (insertIndex - 1) < 0 ? copy.Elements.Length - 1 : insertIndex - 1;
        int indexAfter  = (insertIndex + 1) % copy.Elements.Length;

        if (straight == false || (straight && copy.Elements[indexBefore].GetType() == typeof(GeneratedBezSpline) && copy.Elements[insertIndex].GetType() == typeof(GeneratedBezSpline)))
        {
            List <GeneratedElement> newElements = new List <GeneratedElement>();
            for (int i = 0; i < insertIndex; i++)
            {
                newElements.Add(copy.Elements[i]);
            }

            GeneratedElement newElement = null;
            if (straight)
            {
                GeneratedStraight newStraight = new GeneratedStraight(copy.Elements[indexBefore].EndPosition, copy.Elements[indexBefore].EndDirection, 0f, copy.Elements[indexBefore].WidthEnd);
                newElement = newStraight;
            }
            else
            {
                GeneratedBezSpline newSpline = new GeneratedBezSpline(copy.Elements[indexBefore].EndPosition, copy.Elements[indexBefore].EndDirection, copy.Elements[indexBefore].EndPosition, copy.Elements[indexBefore].EndDirection, copy.Elements[indexBefore].WidthEnd, copy.Elements[indexBefore].WidthEnd);
                newElement = newSpline;
            }

            newElements.Add(newElement);

            for (int i = insertIndex; i < copy.Elements.Length; i++)
            {
                newElements.Add(copy.Elements[i]);
            }

            GeneratedTrack newTrack = new GeneratedTrack();
            for (int i = 0; i < newElements.Count; i++)
            {
                newTrack.AddElement(newElements[i]);
            }

            newTrack.SetTerrainModifier(copy.TerrainModifier);
            newTrack.Analyze();

            SetTrack(newTrack);

            MakeEditable();

            genRendererGUI.EnableEditButtons();
        }
    }
    public void MakeEditable()
    {
        copy = copy.Copy();

        for (int i = 0; i < copy.Elements.Length; i++)
        {
            int        i2     = (i + 1) % copy.Elements.Length;
            int        i0     = i - 1 < 0 ? copy.Elements.Length - 1 : i - 1;
            GameObject instCP = Instantiate(prefabControlpoint);
            instCP.layer = 9;
            instCP.GetComponent <InteractiveCheckpoint>().Moveable       = true;
            instCP.GetComponent <InteractiveCheckpoint>().ElementsIndex  = i;
            instCP.GetComponent <InteractiveCheckpoint>().CpRole         = IntCpRole.MIDPOINT;
            instCP.GetComponent <InteractiveCheckpoint>().Position       = copy.Elements[i].Position;
            instCP.GetComponent <InteractiveCheckpoint>().GenTrack       = this;
            instCP.GetComponent <InteractiveCheckpoint>().ParamDirection = copy.Elements[i].Direction;


            instCP.GetComponent <InteractiveCheckpoint>().ParamDistancePrev = 4f;
            instCP.GetComponent <InteractiveCheckpoint>().ParamDistanceNext = 4f;

            if (copy.Elements[i0].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline spline = (GeneratedBezSpline)copy.Elements[i0];
                instCP.GetComponent <InteractiveCheckpoint>().ParamDistancePrev = spline.LastTwoCpsDistance;
            }
            if (copy.Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline spline = (GeneratedBezSpline)copy.Elements[i];
                instCP.GetComponent <InteractiveCheckpoint>().ParamDistanceNext = spline.FirstTwoCpsDistance;
            }

            if (copy.Elements[i0].GetType() == typeof(GeneratedBezSpline) && copy.Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                instCP.GetComponent <InteractiveCheckpoint>().Turnable = true;
            }
            else
            {
                instCP.GetComponent <InteractiveCheckpoint>().Turnable = false;
            }

            instObjects.Add(instCP);
        }


        linesRenderer.RefreshTrack(copy);
    }
Exemple #4
0
    public override GeneratedElement Copy()
    {
        GeneratedBezSpline copy = new GeneratedBezSpline(position, direction, endPosition, endDirection, widthStart, widthEnd, firstTwoCpsDistance, lastTwoCpsDistance);

        copy.b0         = b0;
        copy.b1         = b1;
        copy.b2         = b2;
        copy.b3         = b3;
        copy.bezier.b0  = b0;
        copy.bezier.b1  = b1;
        copy.bezier.b2  = b2;
        copy.bezier.b3  = b3;
        copy.resolution = resolution;
        copy.fillVerts();

        return(copy);
    }
Exemple #5
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);
    }
    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);
    }
    // Use this for initialization
    void Start()
    {
        if (sappSpline != null)
        {
            GeneratedTrack generatedTrack = new GeneratedTrack();

            for (int i = 0; i < sappSpline.controlPoints.Length; i++)
            {
                float s  = ((float)i) / sappSpline.controlPoints.Length;
                int   i2 = (i + 1) % sappSpline.controlPoints.Length;
                float s2 = ((float)i2) / sappSpline.controlPoints.Length;

                Vector3 pos1     = sappSpline.controlPoints[i].transform.position;
                Vector3 pos2     = sappSpline.controlPoints[i2].transform.position;
                Vector3 tangent1 = (sappSpline.TangentAt(s)[1] - sappSpline.TangentAt(s)[0]).normalized;
                Vector3 tangent2 = (sappSpline.TangentAt(s2)[1] - sappSpline.TangentAt(s2)[0]).normalized;
                float   dir1     = Mathf.Acos(tangent1.z);
                // TODO restilche werte ausrechnen, und den entsprechenden GeneratedBezSpline erstellen
                GeneratedBezSpline bezSpline = new GeneratedBezSpline(pos1, dir1, pos2, dir1, 1f, 1f);
                generatedTrack.AddElement(bezSpline);
            }

            curvativeBins = new float[17];
            for (int i = -8; i <= 8; i++)
            {
                curvativeBins[i + 8] = (((float)i) * maxBinValue) / 8.0f;
            }

            if (curvativeBins != null && curvativeBins.Length > 0)
            {
                curvativeProfile = new int[curvativeBins.Length];
                for (int i = 0; i < curvativeProfile.Length; i++)
                {
                    curvativeProfile[i] = 0;
                }
            }

            for (int i = 0; i < sampleRate; i++)
            {
                float curPos  = ((float)i) / ((float)sampleRate);
                float nextPos = ((float)(i + 1)) / ((float)sampleRate);

                Vector3 pos1 = sappSpline.SplineAt(curPos);
                Vector3 pos2 = sappSpline.SplineAt(nextPos);

                Vector3 tangent1 = sappSpline.TangentAt(curPos)[1] - sappSpline.TangentAt(curPos)[0];
                Vector3 tangent2 = sappSpline.TangentAt(nextPos)[1] - sappSpline.TangentAt(nextPos)[0];

                Vector3 inside1 = Vector3.Cross(tangent1, Vector3.up);
                Vector3 inside2 = Vector3.Cross(tangent2, Vector3.up);

                Vector2 vec2Pos1    = new Vector2(pos1.x, pos1.z);
                Vector2 vec2Pos2    = new Vector2(pos2.x, pos2.z);
                Vector2 vec2Inside1 = new Vector2(inside1.x, inside1.z);
                Vector2 vec2Inside2 = new Vector2(inside2.x, inside2.z);

                Line line1 = new Line(vec2Pos1, vec2Pos1 + vec2Inside1);
                Line line2 = new Line(vec2Pos2, vec2Pos2 + vec2Inside2);

                Vector2 intersect = Vector2.zero;

                bool intersects = line1.Intersects(line2, out intersect);

                float curvative = 0f;

                if (intersect != Vector2.zero)
                {
                    float radius1 = Vector2.Distance(intersect, vec2Pos1);
                    float radius2 = Vector2.Distance(intersect, vec2Pos2);

                    float avgRadius = (radius1 + radius2) * 0.5f;

                    curvative = 1f / avgRadius;

                    Vector3 toRight      = (inside1 - pos1).normalized;
                    Vector3 intersectDir = ((new Vector3(intersect.x, pos1.y, intersect.y)) - pos1).normalized;

                    if (Vector3.Angle(toRight, intersectDir) >= 90)
                    {
                        curvative *= -1f;
                    }

                    if (debugInfo)
                    {
                        Debug.DrawLine(pos1, new Vector3(intersect.x, pos1.y, intersect.y), Color.yellow);
                        Debug.DrawLine(pos2, new Vector3(intersect.x, pos2.y, intersect.y), Color.yellow);
                    }
                }

                if (debugInfo)
                {
                    //Debug.Log("Curvative: " + curvative);
                }

                if (curvativeBins != null && curvativeBins.Length > 0)
                {
                    bool found = false;
                    for (int j = 0; j < curvativeBins.Length; j++)
                    {
                        if (curvative < curvativeBins[j])
                        {
                            curvativeProfile[j]++;
                            found = true;
                            break;
                        }
                    }

                    if (!found)
                    {
                        curvativeProfile[curvativeProfile.Length - 1]++;
                    }
                }
            }

            if (visualizerProfile != null)
            {
                visualizerProfile.SetTrackName(trackname);

                for (int i = 0; i < curvativeProfile.Length; i++)
                {
                    visualizerProfile.SetBarValue(i, curvativeProfile[i] / ((float)sampleRate));
                }
            }
        }
    }
Exemple #8
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);
    }
    public override void CPChanged(int index, IntCpRole role, Vector3 newPosition, float newNextDistance, float newPrevDistance, float newDirection)
    {
        newPosition = new Vector3(newPosition.x, 0f, newPosition.z);

        int i  = index - 1 < 0 ? copy.Elements.Length - 1 : index - 1;
        int i2 = index;

        if (role == IntCpRole.MIDPOINT)
        {
            if (copy.Elements[i].GetType() == typeof(GeneratedBezSpline) && copy.Elements[i2].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline old1 = (GeneratedBezSpline)copy.Elements[i];
                GeneratedBezSpline old2 = (GeneratedBezSpline)copy.Elements[i2];

                GeneratedBezSpline new1 = new GeneratedBezSpline(old1.Position, old1.Direction, newPosition, old1.EndDirection, old1.WidthStart, old1.WidthEnd, old1.FirstTwoCpsDistance, old1.LastTwoCpsDistance);
                GeneratedBezSpline new2 = new GeneratedBezSpline(newPosition, old2.Direction, old2.EndPosition, old2.EndDirection, old2.WidthStart, old2.WidthEnd, old2.FirstTwoCpsDistance, old2.LastTwoCpsDistance);

                copy.ReplaceElement(i, new1);
                copy.ReplaceElement(i2, new2);

                //Debug.Log("Updated 2 BezSplines: " + newPosition.ToString());
            }
            else if (copy.Elements[i].GetType() == typeof(GeneratedBezSpline) && copy.Elements[i2].GetType() == typeof(GeneratedStraight))
            {
                GeneratedBezSpline spline      = (GeneratedBezSpline)copy.Elements[i];
                GeneratedStraight  straight    = (GeneratedStraight)copy.Elements[i2];
                GeneratedBezSpline afterSpline = (GeneratedBezSpline)copy.Elements[(i2 + 1) % copy.Elements.Length];

                float newStraightDirectinon = Vector2.Angle(new Vector2(0f, 1f), new Vector2(straight.EndPosition.x, straight.EndPosition.z) - new Vector2(newPosition.x, newPosition.z));
                if (Vector2.Angle(new Vector2(1f, 0f), new Vector2(straight.EndPosition.x, straight.EndPosition.z) - new Vector2(newPosition.x, newPosition.z)) > 90f)
                {
                    newStraightDirectinon = 360 - newStraightDirectinon;
                }
                newStraightDirectinon = newStraightDirectinon * Mathf.PI / 180f;

                instObjects[i2].GetComponent <InteractiveCheckpoint>().ParamDirection = newStraightDirectinon;
                instObjects[i2].GetComponent <InteractiveCheckpoint>().DirectionChanged();
                instObjects[(i2 + 1) % copy.Elements.Length].GetComponent <InteractiveCheckpoint>().ParamDirection = newStraightDirectinon;
                instObjects[(i2 + 1) % copy.Elements.Length].GetComponent <InteractiveCheckpoint>().DirectionChanged();

                GeneratedBezSpline new1        = new GeneratedBezSpline(spline.Position, spline.Direction, newPosition, newStraightDirectinon, spline.WidthStart, spline.WidthEnd, spline.FirstTwoCpsDistance, spline.LastTwoCpsDistance);
                GeneratedBezSpline new2        = new GeneratedBezSpline(afterSpline.Position, newStraightDirectinon, afterSpline.EndPosition, afterSpline.EndDirection, afterSpline.WidthStart, afterSpline.WidthEnd, afterSpline.FirstTwoCpsDistance, afterSpline.LastTwoCpsDistance);
                GeneratedStraight  newStraight = new GeneratedStraight(newPosition, newStraightDirectinon, Vector2.Distance(new Vector2(newPosition.x, newPosition.z), new Vector2(afterSpline.Position.x, afterSpline.Position.z)), straight.WidthStart, straight.WidthEnd);

                copy.ReplaceElement(i, new1);
                copy.ReplaceElement(i2, newStraight);
                copy.ReplaceElement((i2 + 1) % copy.Elements.Length, new2);
                //Debug.Log("Updated Straight - Spline: " + newPosition.ToString());
            }
            else if (copy.Elements[i].GetType() == typeof(GeneratedStraight) && copy.Elements[i2].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline spline      = (GeneratedBezSpline)copy.Elements[i2];
                GeneratedStraight  straight    = (GeneratedStraight)copy.Elements[i];
                GeneratedBezSpline afterSpline = (GeneratedBezSpline)copy.Elements[i - 1 >= 0 ? i - 1 : copy.Elements.Length - 1];

                float newStraightDirectinon = Vector2.Angle(new Vector2(0f, 1f), new Vector2(newPosition.x, newPosition.z) - new Vector2(straight.Position.x, straight.Position.z));
                if (Vector2.Angle(new Vector2(1f, 0f), new Vector2(newPosition.x, newPosition.z) - new Vector2(straight.Position.x, straight.Position.z)) > 90f)
                {
                    newStraightDirectinon = 360 - newStraightDirectinon;
                }
                newStraightDirectinon = newStraightDirectinon * Mathf.PI / 180f;

                instObjects[i].GetComponent <InteractiveCheckpoint>().ParamDirection = newStraightDirectinon;
                instObjects[i].GetComponent <InteractiveCheckpoint>().DirectionChanged();
                instObjects[i2].GetComponent <InteractiveCheckpoint>().ParamDirection = newStraightDirectinon;
                instObjects[i2].GetComponent <InteractiveCheckpoint>().DirectionChanged();

                GeneratedBezSpline new1        = new GeneratedBezSpline(newPosition, newStraightDirectinon, spline.EndPosition, spline.EndDirection, spline.WidthStart, spline.WidthEnd, spline.FirstTwoCpsDistance, spline.LastTwoCpsDistance);
                GeneratedBezSpline new2        = new GeneratedBezSpline(afterSpline.Position, afterSpline.Direction, afterSpline.EndPosition, newStraightDirectinon, afterSpline.WidthStart, afterSpline.WidthEnd, afterSpline.FirstTwoCpsDistance, afterSpline.LastTwoCpsDistance);
                GeneratedStraight  newStraight = new GeneratedStraight(straight.Position, newStraightDirectinon, Vector2.Distance(new Vector2(newPosition.x, newPosition.z), new Vector2(straight.Position.x, straight.Position.z)), straight.WidthStart, straight.WidthEnd);

                copy.ReplaceElement(i, newStraight);
                copy.ReplaceElement(i2, new1);
                copy.ReplaceElement(i - 1 >= 0 ? i - 1 : copy.Elements.Length - 1, new2);
                //Debug.Log("Updated Spline - Straight: " + newPosition.ToString());
            }
        }
        else if (role == IntCpRole.NEXT_B1)
        {
            if (copy.Elements[i2].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline old  = (GeneratedBezSpline)copy.Elements[i2];
                GeneratedBezSpline new1 = new GeneratedBezSpline(old.Position, old.Direction, old.EndPosition, old.EndDirection, old.WidthStart, old.WidthEnd, newNextDistance, old.LastTwoCpsDistance);
                copy.ReplaceElement(i2, new1);
            }
        }
        else if (role == IntCpRole.PREV_B2)
        {
            if (copy.Elements[i].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline old  = (GeneratedBezSpline)copy.Elements[i];
                GeneratedBezSpline new1 = new GeneratedBezSpline(old.Position, old.Direction, old.EndPosition, old.EndDirection, old.WidthStart, old.WidthEnd, old.FirstTwoCpsDistance, newPrevDistance);
                copy.ReplaceElement(i, new1);
            }
        }
        else if (role == IntCpRole.DIRECTION)
        {
            if (copy.Elements[i].GetType() == typeof(GeneratedBezSpline) && copy.Elements[index].GetType() == typeof(GeneratedBezSpline))
            {
                GeneratedBezSpline old1 = (GeneratedBezSpline)copy.Elements[i];
                GeneratedBezSpline old2 = (GeneratedBezSpline)copy.Elements[index];

                GeneratedBezSpline new1 = new GeneratedBezSpline(old1.Position, old1.Direction, old1.EndPosition, newDirection, old1.WidthStart, old1.WidthEnd, old1.FirstTwoCpsDistance, old1.LastTwoCpsDistance);
                GeneratedBezSpline new2 = new GeneratedBezSpline(old2.Position, newDirection, old2.EndPosition, old2.EndDirection, old2.WidthStart, old2.WidthEnd, old2.FirstTwoCpsDistance, old2.LastTwoCpsDistance);

                copy.ReplaceElement(i, new1);
                copy.ReplaceElement(index, new2);
            }
        }

        linesRenderer.RefreshTrack(copy);
    }
Exemple #10
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();
    }
    public void Render(GeneratedTrack track, bool mlStuff)
    {
        for (int i = 0; i < instMLStuff.Count; i++)
        {
            Destroy(instMLStuff[i]);
        }

        instMLStuff = new List <GameObject>();

        //if (planeRenderer != null)
        //{
        //    planeRenderer.RefreshPlane(track.TerrainModifier);
        //}

        trackLength = track.TrackLength;

        vertices.Clear();
        triangles.Clear();
        uvs.Clear();

        int debugCounter = 0;

        for (int i = 0; i < instDebugObjects.Count; i++)
        {
            Destroy(instDebugObjects[i]);
        }
        instDebugObjects.Clear();

        for (int i = 0; i < instCurbs.Count; i++)
        {
            Destroy(instCurbs[i]);
        }
        instCurbs.Clear();


        /*if (track.Elements[0].GetType() == typeof(GeneratedStraight))
         * {
         *  GeneratedStraight straight = (GeneratedStraight)track.Elements[0];
         *
         *  Vector3 toRight = (Quaternion.Euler(0f, (straight.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(straight.WidthStart, 0f, 0f));
         *
         *  vertices.Add(straight.Position - toRight);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *  vertices.Add(straight.Position + toRight);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *
         * }
         * else if (track.Elements[0].GetType() == typeof(GeneratedTurn))
         * {
         *  GeneratedTurn turn = (GeneratedTurn)track.Elements[0];
         *
         *  Vector3 toRight = (Quaternion.Euler(0f, (turn.Direction * 180f) / Mathf.PI, 0f)) * (new Vector3(turn.WidthStart, 0f, 0f));
         *
         *  vertices.Add(turn.Position - toRight);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *  vertices.Add(turn.Position + toRight);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         * }
         * else if (track.Elements[0].GetType() == typeof(GeneratedBezSpline))
         * {
         *  GeneratedBezSpline bezSpline = (GeneratedBezSpline)track.Elements[0];
         *
         *  vertices.Add(bezSpline.RenderVertsLeft[0]);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *  vertices.Add(bezSpline.RenderVertsRight[0]);
         *  uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         * }
         *
         *
         * for (int i = 0; i < track.Elements.Length; i++)
         * {
         *
         *  int verticesCountBefore = vertices.Count;
         *
         *  //if (track.Elements[i].GetType() != typeof(GeneratedStraight))
         *  //{
         *      GameObject instDebugText = Instantiate(debugText);
         *      instDebugText.transform.position = track.Elements[i].Position;
         *      instDebugText.GetComponent<DebugPoint>().Text = debugCounter.ToString();
         *
         *      instDebugObjects.Add(instDebugText);
         *
         *      debugCounter++;
         *  //}
         *
         *  if (track.Elements[i].GetType() == typeof(GeneratedStraight))
         *  {
         *      GeneratedStraight straight = (GeneratedStraight)track.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 / 4f);
         *
         *      for (int j = 1; j <= segmentsAmount; j++)
         *      {
         *          float s = ((float)j) / segmentsAmount;
         *
         *
         *          vertices.Add(straight.Position + (toFront * s) - toRight);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *          vertices.Add(straight.Position + (toFront * s) + toRight);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *
         *
         *          triangles.Add(vertices.Count - 4);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 3);
         *
         *          triangles.Add(vertices.Count - 3);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 1);
         *      }
         *  }
         *  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) / 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;
         *
         *          vertices.Add(segmentPos + toRightTurned * currentWidth * -1f + turn.Position);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *          vertices.Add(segmentPos + toRightTurned * currentWidth + turn.Position);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *
         *
         *          triangles.Add(vertices.Count - 4);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 3);
         *
         *          triangles.Add(vertices.Count - 3);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 1);
         *      }
         *  }
         *  else if (track.Elements[i].GetType() == typeof(GeneratedBezSpline))
         *  {
         *      GeneratedBezSpline bezierSpline = (GeneratedBezSpline)track.Elements[i];
         *
         *      for (int j = 1; j < bezierSpline.RenderVertsLeft.Length; j++)
         *      {
         *          vertices.Add(bezierSpline.RenderVertsLeft[j]);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *          vertices.Add(bezierSpline.RenderVertsRight[j]);
         *          uvs.Add(new Vector2(vertices[vertices.Count - 1].x, vertices[vertices.Count - 1].z));
         *
         *
         *          triangles.Add(vertices.Count - 4);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 3);
         *
         *          triangles.Add(vertices.Count - 3);
         *          triangles.Add(vertices.Count - 2);
         *          triangles.Add(vertices.Count - 1);
         *      }
         *  }
         *
         *  if (curbsEnabled && track.Elements[i].Curbs.Length > 0)
         *  {
         *      for (int j = 0; j < track.Elements[i].Curbs.Length; j++)
         *      {
         *          GameObject instCurb = Instantiate(curbPrefab, transform);
         *          instCurb.GetComponent<CurbRenderer>().ApplyCurb(track.Elements[i].Curbs[j], track.Elements[i]);
         *          instCurb.transform.localPosition = Vector3.zero;
         *          instCurbs.Add(instCurb);
         *      }
         *  }
         *
         *
         *
         *  //List<Vector3> sectorVertices = new List<Vector3>();
         *  //for (int j = verticesCountBefore; j < vertices.Count; j++)
         *  //{
         *  //    sectorVertices.Add(vertices[j]);
         *  //}
         *
         *  //track.TerrainModifier.FillSectorsByElements(sectorVertices, i);
         * }
         */

        Debug.Log("Generate Mesh: " + Time.time);

        track.GenerateMesh();
        vertices  = new List <Vector3>(track.RenderVerticesTrack);
        triangles = new List <int>(track.RenderTrianglesTrack);
        uvs       = new List <Vector2>(track.RenderUVsTrack);

        if (mlStuff)
        {
            Vector3[] leftMLPoints  = new Vector3[vertices.Count / 2];
            Vector3[] rightMLPoints = new Vector3[vertices.Count / 2];
            for (int i = 0; i < leftMLPoints.Length; i++)
            {
                leftMLPoints[i]  = vertices[i * 2 + 0];
                rightMLPoints[i] = vertices[i * 2 + 1];

                GameObject cubeI = Instantiate(mlCheckpointCubePrefab);
                cubeI.transform.position   = (leftMLPoints[i] + rightMLPoints[i]) * 0.5f;
                cubeI.transform.right      = leftMLPoints[i] - rightMLPoints[i];
                cubeI.transform.localScale = new Vector3((leftMLPoints[i] - rightMLPoints[i]).magnitude, 6f, 0.1f);

                instMLStuff.Add(cubeI);
            }
            GameObject instWallLeftML = Instantiate(wallPrefab);
            instWallLeftML.transform.position = Vector3.zero;
            GameObject instWallRightML = Instantiate(wallPrefab);
            instWallRightML.transform.position = Vector3.zero;

            instWallLeftML.GetComponent <WallRenderer>().Points  = leftMLPoints;
            instWallRightML.GetComponent <WallRenderer>().Points = rightMLPoints;

            instWallLeftML.name = "ML_Wall_Left";
            instWallLeftML.name = "ML_Wall_Right";

            instMLStuff.Add(instWallLeftML);
            instMLStuff.Add(instWallRightML);
        }



        //3,751



        int     startFinishElementIndex = (int)track.AnalyzedTrack.startFinishLineIndex;
        float   sStartFinishElement     = track.AnalyzedTrack.startFinishLineIndex - startFinishElementIndex;
        Vector3 posStartFinish          = Vector3.zero;
        float   rotStartFinish          = 0f;

        if (track.Elements[startFinishElementIndex].GetType() == typeof(GeneratedStraight))
        {
            GeneratedStraight straight = (GeneratedStraight)track.Elements[startFinishElementIndex];
            posStartFinish = straight.Position + (straight.EndPosition - straight.Position) * sStartFinishElement;
            rotStartFinish = straight.Direction;
        }
        else
        {
            GeneratedBezSpline spline = (GeneratedBezSpline)track.Elements[startFinishElementIndex];
            int vertSplineIndex       = (int)(spline.RenderVertsLeft.Length * sStartFinishElement);
            posStartFinish = spline.RenderVertsLeft[vertSplineIndex] + 0.5f * (spline.RenderVertsRight[vertSplineIndex] - spline.RenderVertsLeft[vertSplineIndex]);
            rotStartFinish = Vector2.Angle(new Vector2((spline.RenderVertsRight[vertSplineIndex] - spline.RenderVertsLeft[vertSplineIndex]).x, (spline.RenderVertsRight[vertSplineIndex] - spline.RenderVertsLeft[vertSplineIndex]).z), new Vector2(0f, 1f));
            if (Vector2.Angle(new Vector2((spline.RenderVertsRight[vertSplineIndex] - spline.RenderVertsLeft[vertSplineIndex]).x, (spline.RenderVertsRight[vertSplineIndex] - spline.RenderVertsLeft[vertSplineIndex]).z), new Vector2(1f, 0f)) > 90f)
            {
                rotStartFinish = 360 - rotStartFinish;
            }

            rotStartFinish  = rotStartFinish * Mathf.PI / 180f;
            rotStartFinish -= (Mathf.PI * 0.5f);
        }

        posStartFinish = new Vector3(posStartFinish.x, track.GetTensorHeight(posStartFinish), posStartFinish.z);

        startFinishBow.transform.position = posStartFinish;
        startFinishBow.transform.rotation = Quaternion.Euler(0f, rotStartFinish * 180f / Mathf.PI, 0f);


        //3,924



        Debug.Log("Generate Grass planes: " + Time.time);

        for (int j = 0; j < track.GrassPlanes.Length; j++)
        {
            Vector3[] grassLeftVerts = track.GrassPlanes[j].vertices;
            for (int i = 0; i < grassLeftVerts.Length; i++)
            {
                grassLeftVerts[i] = grassLeftVerts[i] + new Vector3(0f, track.GetTensorHeight(grassLeftVerts[i]), 0f);
            }


            GameObject grassLeft = Instantiate(grassPlanePrefab);
            grassLeft.transform.position = transform.position;
            grassLeft.GetComponent <MeshFilter>().mesh.Clear();
            grassLeft.GetComponent <MeshFilter>().mesh.vertices     = grassLeftVerts;
            grassLeft.GetComponent <MeshFilter>().mesh.uv           = track.GrassPlanes[j].uvs;
            grassLeft.GetComponent <MeshFilter>().mesh.subMeshCount = 1;
            grassLeft.GetComponent <MeshFilter>().mesh.SetTriangles(track.GrassPlanes[j].triangles, 0);
            grassLeft.GetComponent <MeshFilter>().mesh.RecalculateNormals();
            grassLeft.GetComponent <MeshCollider>().sharedMesh = grassLeft.GetComponent <MeshFilter>().mesh;

            instDebugObjects.Add(grassLeft);


            if (track.GrassPlanes[j].AllowBordercross)
            {
                List <Vector3> borderVerts = new List <Vector3>();
                List <Vector3> borderDirs  = new List <Vector3>();
                for (int k = 0; k < track.GrassPlanes[j].verticesOutside.Length; k++)
                {
                    int k0 = (k - 1) < 0 ? track.GrassPlanes[j].verticesOutside.Length - 1 : (k - 1);
                    int k2 = (k + 1) % track.GrassPlanes[j].verticesOutside.Length;

                    if (Vector3.Distance(track.GrassPlanes[j].verticesOutside[k], track.GrassPlanes[j].verticesOutside[k2]) >= 0.01f)
                    {
                        borderVerts.Add(track.GrassPlanes[j].verticesOutside[k] + new Vector3(0f, track.GetTensorHeight(track.GrassPlanes[j].verticesOutside[k]), 0f));
                        borderDirs.Add(track.GrassPlanes[j].directionsOutside[k]);
                    }
                }



                GameObject instLeftCrossover = Instantiate(crossoverRegionPrefab, transform);
                instLeftCrossover.transform.localPosition = Vector3.zero;
                instLeftCrossover.GetComponent <CrossoverRegion>().GeneratedTrack = track;
                instLeftCrossover.GetComponent <CrossoverRegion>().Render(borderVerts.ToArray(), borderDirs.ToArray(), true);

                instDebugObjects.Add(instLeftCrossover);
            }
        }

        if (track.Circles != null)
        {
            for (int i = 0; i < track.Circles.Length; i++)
            {
                GameObject instDebugCircle = Instantiate(debugText);
                instDebugCircle.transform.position = new Vector3(track.Circles[i].Midpoint.x, 0f, track.Circles[i].Midpoint.y);

                instDebugObjects.Add(instDebugCircle);
            }
        }


        //5,544



        for (int i = 0; i < vertices.Count; i++)
        {
            //int currentElement = elementsVertices[i];
            vertices[i] = vertices[i] + new Vector3(0f, track.GetTensorHeight(vertices[i]), 0f);
        }



        //5,560



        //
        // Cross over region
        //


        Vector3[] leftVertices    = new Vector3[vertices.Count / 2];
        Vector3[] rightVertices   = new Vector3[vertices.Count / 2];
        Vector3[] leftDirections  = new Vector3[vertices.Count / 2];
        Vector3[] rightDirections = new Vector3[vertices.Count / 2];

        for (int i = 0; i < vertices.Count; i++)
        {
            if (i % 2 == 0)
            {
                leftVertices[i / 2]   = vertices[i];
                leftDirections[i / 2] = vertices[i] - vertices[i + 1];
            }
            else
            {
                rightVertices[(i - 1) / 2]   = vertices[vertices.Count - i];
                rightDirections[(i - 1) / 2] = vertices[vertices.Count - i] - vertices[vertices.Count - i - 1];
            }
        }


        Debug.Log("Generate Curbs: " + Time.time);

        for (int i = 0; i < track.Curbs.Length; i++)
        {
            GameObject instCurb = Instantiate(curbPrefab);
            instCurb.transform.position = new Vector3(0f, 0.5f, 0f);
            instCurb.GetComponent <CurbRenderer>().ApplyCurb(track.Curbs[i], track.TerrainModifier);
            instDebugObjects.Add(instCurb);
        }



        if (instWallLeft != null)
        {
            Destroy(instWallLeft);
            instWallLeft = null;
        }
        if (instWallRight != null)
        {
            Destroy(instWallRight);
            instWallRight = null;
        }

        instWallLeft = Instantiate(wallPrefab);
        instWallLeft.transform.position = Vector3.zero;
        instWallRight = Instantiate(wallPrefab);
        instWallRight.transform.position = Vector3.zero;

        instWallLeft.GetComponent <WallRenderer>().Points  = track.BorderGenerator.WallLeft;
        instWallRight.GetComponent <WallRenderer>().Points = track.BorderGenerator.WallRight;


        //5,730



        Debug.Log("Set track mesh: " + Time.time);



        meshFilter.mesh.Clear();
        meshFilter.mesh.vertices = vertices.ToArray();
        meshFilter.mesh.uv       = uvs.ToArray();

        meshFilter.mesh.subMeshCount = 1;

        meshFilter.mesh.SetTriangles(triangles.ToArray(), 0);

        meshFilter.mesh.RecalculateNormals();

        meshCollider.sharedMesh = meshFilter.mesh;


        //5,743


        Debug.Log("Apply grass: " + Time.time);

        terrainModifier.ApplyGrass(vertices.ToArray());

        //61,596



        Debug.Log("Adjust terrain to track: " + Time.time);

        terrainGenerator.AdjustTerrainToTrack(vertices.ToArray());


        currentRenderedTrack = track;



        tempRem = false;

        //Debug.Log("Finished: " + Time.time);
    }
Exemple #12
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));
            }
        }
    }
Exemple #13
0
    public void RefreshTrack(GeneratedTrack track)
    {
        int counterLeft  = 0;
        int counterRight = 0;

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

                for (int j = 0; j < spline.RenderVertsLeft.Length; j++)
                {
                    Vector3 endPos = j + 1 < spline.RenderVertsLeft.Length ? new Vector3(spline.RenderVertsLeft[j + 1].x, track.GetTensorHeight(spline.RenderVertsLeft[j + 1]) + 1f, spline.RenderVertsLeft[j + 1].z) : track.Elements[(i + 1) % track.Elements.Length].Position;

                    doLine(new Vector3(spline.RenderVertsLeft[j].x, track.GetTensorHeight(spline.RenderVertsLeft[j]) + 1f, spline.RenderVertsLeft[j].z), endPos, true, counterLeft, Color.white);
                    counterLeft++;
                }
                for (int j = 0; j < spline.RenderVertsRight.Length; j++)
                {
                    Vector3 endPos = j + 1 < spline.RenderVertsRight.Length ? new Vector3(spline.RenderVertsRight[j + 1].x, track.GetTensorHeight(spline.RenderVertsRight[j + 1]) + 1f, spline.RenderVertsRight[j + 1].z) : track.Elements[(i + 1) % track.Elements.Length].Position;

                    doLine(new Vector3(spline.RenderVertsRight[j].x, track.GetTensorHeight(spline.RenderVertsRight[j]) + 1f, spline.RenderVertsRight[j].z), endPos, false, counterRight, Color.white);
                    counterRight++;
                }
            }
            else if (track.Elements[i].GetType() == typeof(GeneratedStraight))
            {
                int iPrev = i - 1 < 0 ? track.Elements.Length - 1 : i - 1;
                int iNext = (i + 1) % track.Elements.Length;
                GeneratedBezSpline splinePrev = (GeneratedBezSpline)track.Elements[iPrev];
                GeneratedBezSpline splineNext = (GeneratedBezSpline)track.Elements[iNext];

                Vector3 leftStartPos  = splinePrev.RenderVertsLeft[splinePrev.RenderVertsLeft.Length - 1];
                Vector3 rightStartPos = splinePrev.RenderVertsRight[splinePrev.RenderVertsRight.Length - 1];
                Vector3 leftEndPos    = splineNext.RenderVertsLeft[0];
                Vector3 rightEndPos   = splineNext.RenderVertsRight[0];

                leftStartPos  = new Vector3(leftStartPos.x, track.GetTensorHeight(leftStartPos) + 1f, leftStartPos.z);
                rightStartPos = new Vector3(rightStartPos.x, track.GetTensorHeight(rightStartPos) + 1f, rightStartPos.z);
                leftEndPos    = new Vector3(leftEndPos.x, track.GetTensorHeight(leftEndPos) + 1f, leftEndPos.z);
                rightEndPos   = new Vector3(rightEndPos.x, track.GetTensorHeight(rightEndPos) + 1f, rightEndPos.z);

                doLine(leftStartPos, leftEndPos, true, counterLeft, Color.blue);
                counterLeft++;
                doLine(rightStartPos, rightEndPos, false, counterRight, Color.blue);
                counterRight++;
            }
        }


        for (int i = counterLeft; i < instLinesLeft.Count; i++)
        {
            Destroy(instLinesLeft[i]);
            instLinesLeft.RemoveAt(i);
            i--;
        }
        for (int i = counterRight; i < instLinesRight.Count; i++)
        {
            Destroy(instLinesRight[i]);
            instLinesRight.RemoveAt(i);
            i--;
        }
    }