Inheritance: MonoBehaviour
Beispiel #1
0
    public void OptimseMeshes()
    {
#if UNITY_EDITOR
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];

            for (int m = 0; m < curve.dynamicTrackMesh.meshCount; m++)
            {
                MeshUtility.Optimize(curve.dynamicTrackMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicOffroadMesh.meshCount; m++)
            {
                MeshUtility.Optimize(curve.dynamicOffroadMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBumperMesh.meshCount; m++)
            {
                MeshUtility.Optimize(curve.dynamicBumperMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBoundaryMesh.meshCount; m++)
            {
                MeshUtility.Optimize(curve.dynamicBoundaryMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBottomMesh.meshCount; m++)
            {
                MeshUtility.Optimize(curve.dynamicBottomMesh[m].mesh);
            }
        }
        _optimised = true;
#endif
    }
Beispiel #2
0
//    /// <summary>
//    /// Mark the pit lane as dirty so it will be recalculated/rebuilt
//    /// </summary>
//    public void SetPitDirty()
//    {
//        for (int i = 0; i < pitlane.numberOfPoints; i++)
//        {
//            pitlane[i].isDirty = true;
//        }
//    }
//
//    /// <summary>
//    /// Set pit lane point data to rerender
//    /// </summary>
//    public void ReRenderPit()
//    {
//        for (int i = 0; i < pitlane.numberOfPoints; i++)
//        {
//            pitlane[i].shouldReRender = true;
//        }
//    }

    public void GenerateSecondaryUVSet()
    {
#if UNITY_EDITOR
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];

            List <Mesh> unwrapList = new List <Mesh>();
            unwrapList.AddRange(curve.dynamicTrackMesh.meshes);
            unwrapList.AddRange(curve.dynamicOffroadMesh.meshes);
            unwrapList.AddRange(curve.dynamicBumperMesh.meshes);
            unwrapList.AddRange(curve.dynamicBoundaryMesh.meshes);
            unwrapList.AddRange(curve.dynamicBottomMesh.meshes);

            int count = unwrapList.Count;
            for (int m = 0; m < count; m++)
            {
                if (unwrapList[m].vertexCount == 0)
                {
                    continue;
                }
                Unwrapping.GenerateSecondaryUVSet(unwrapList[m]);
            }
        }
        _lightmapGenerated = true;
#endif
    }
Beispiel #3
0
    public void GenerateSecondaryUVSet()
    {
#if UNITY_EDITOR
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];

            for (int m = 0; m < curve.dynamicTrackMesh.meshCount; m++)
            {
                Unwrapping.GenerateSecondaryUVSet(curve.dynamicTrackMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicOffroadMesh.meshCount; m++)
            {
                Unwrapping.GenerateSecondaryUVSet(curve.dynamicOffroadMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBumperMesh.meshCount; m++)
            {
                Unwrapping.GenerateSecondaryUVSet(curve.dynamicBumperMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBoundaryMesh.meshCount; m++)
            {
                Unwrapping.GenerateSecondaryUVSet(curve.dynamicBoundaryMesh[m].mesh);
            }
            for (int m = 0; m < curve.dynamicBottomMesh.meshCount; m++)
            {
                Unwrapping.GenerateSecondaryUVSet(curve.dynamicBottomMesh[m].mesh);
            }
        }
        _lightmapGenerated = true;
#endif
    }
Beispiel #4
0
    public static void ConformTrack(TrackBuildRTrack track, Terrain terrain)
    {
        TerrainData terrainData       = terrain.terrainData;
        int         terrainWidth      = terrainData.heightmapWidth;
        int         terrainHeight     = terrainData.heightmapHeight;
        float       terrainHeightmapY = terrain.terrainData.heightmapScale.y;
        float       terrainY          = terrain.transform.position.y / terrainHeightmapY;
        float       conformAccuracy   = track.conformAccuracy;

        float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight);

        Bounds trackBounds    = new Bounds();
        int    numberOfCurves = track.numberOfCurves;

        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = track[i];
            if (curve.holder == null)
            {
                continue;
            }
            Renderer[] rends = curve.holder.GetComponentsInChildren <Renderer>();
            foreach (Renderer rend in rends)
            {
                trackBounds.Encapsulate(rend.bounds);
            }
        }

        Vector3 trackOffset = track.transform.position - terrain.transform.position;
        Vector3 trackScale  = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z);

        int realNumberOfPoints = track.realNumberOfPoints;

        for (int i = 0; i < realNumberOfPoints; i++)
        {
            TrackBuildRPoint point = track[i];
            Vector3          trackPointPosition = point.position;
            int pointX = Mathf.RoundToInt(((trackPointPosition.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
            int pointY = Mathf.RoundToInt(((trackPointPosition.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

            pointX = Mathf.Clamp(pointX, 0, terrainWidth - 1);
            pointY = Mathf.Clamp(pointY, 0, terrainHeight - 1);

            trackPointPosition.y = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy;
            point.position       = trackPointPosition;

            Vector3 controlPoint = point.forwardControlPoint;
            pointX = Mathf.RoundToInt(((controlPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
            pointY = Mathf.RoundToInt(((controlPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

            pointX = Mathf.Clamp(pointX, 0, terrainWidth - 1);
            pointY = Mathf.Clamp(pointY, 0, terrainHeight - 1);

            controlPoint.y            = originalData[pointY, pointX] * terrain.terrainData.size.y - terrainY + conformAccuracy;
            point.forwardControlPoint = controlPoint;

            point.isDirty = true;
        }
        track.RecalculateCurves();
    }
Beispiel #5
0
    public void Init()
    {
        track = gameObject.AddComponent <TrackBuildRTrack>();
        track.InitTextures();
        track.baseTransform = transform;

        TrackBuildRPoint p0 = gameObject.AddComponent <TrackBuildRPoint>(); // ScriptableObject.CreateInstance<TrackBuildRPoint>();
        TrackBuildRPoint p1 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>();
        TrackBuildRPoint p2 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>();
        TrackBuildRPoint p3 = gameObject.AddComponent <TrackBuildRPoint>(); //ScriptableObject.CreateInstance<TrackBuildRPoint>();

        p0.baseTransform = transform;
        p1.baseTransform = transform;
        p2.baseTransform = transform;
        p3.baseTransform = transform;

        p0.position = new Vector3(-20, 0, -20);
        p1.position = new Vector3(20, 0, -20);
        p2.position = new Vector3(20, 0, 20);
        p3.position = new Vector3(-20, 0, 20);

        p0.forwardControlPoint = new Vector3(0, 0, -20);
        p1.forwardControlPoint = new Vector3(40, 0, -20);
        p2.forwardControlPoint = new Vector3(0, 0, 20);
        p3.forwardControlPoint = new Vector3(-40, 0, 20);

        p0.leftForwardControlPoint = new Vector3(-15, 0, -20);
        p1.leftForwardControlPoint = new Vector3(25, 0, -20);
        p2.leftForwardControlPoint = new Vector3(5, 0, 20);
        p3.leftForwardControlPoint = new Vector3(-35, 0, 20);

        p0.rightForwardControlPoint = new Vector3(15, 0, -20);
        p1.rightForwardControlPoint = new Vector3(55, 0, -20);
        p2.rightForwardControlPoint = new Vector3(-5, 0, 20);
        p3.rightForwardControlPoint = new Vector3(-45, 0, 20);

        track.AddPoint(p0);
        track.AddPoint(p1);
        track.AddPoint(p2);
        track.AddPoint(p3);

        generator = gameObject.AddComponent <TrackBuildRGenerator>();

        ForceFullRecalculation();

        track.diagramMesh           = new Mesh();
        track.diagramMesh.vertices  = new [] { new Vector3(-1, 0, -1), new Vector3(1, 0, -1), new Vector3(-1, 0, 1), new Vector3(1, 0, 1) };
        track.diagramMesh.uv        = new [] { new Vector2(0, 0), new Vector2(1, 0), new Vector2(0, 1), new Vector2(1, 1) };
        track.diagramMesh.triangles = new [] { 1, 0, 2, 1, 2, 3 };

        track.diagramGO = new GameObject("Diagram");
        track.diagramGO.transform.parent                 = transform;
        track.diagramGO.transform.localPosition          = Vector3.zero;
        track.diagramGO.AddComponent <MeshFilter>().mesh = track.diagramMesh;
        track.diagramMaterial = new Material(Shader.Find("Unlit/Texture"));
        track.diagramGO.AddComponent <MeshRenderer>().material   = track.diagramMaterial;
        track.diagramGO.AddComponent <MeshCollider>().sharedMesh = track.diagramMesh;
    }
Beispiel #6
0
    //Sample nextNormIndex position on the entire curve based on time (0-1)
    public Vector3 GetRightBoundaryPosition(float t)
    {
        float            curveT = 1.0f / numberOfCurves;
        int              point  = Mathf.FloorToInt(t / curveT);
        float            ct     = Mathf.Clamp01((t - point * curveT) * numberOfCurves);
        TrackBuildRPoint pointA = GetPoint(point);
        TrackBuildRPoint pointB = GetPoint(point + 1);

        return(SplineMaths.CalculateBezierPoint(ct, pointA.rightTrackBoundary, pointA.rightForwardControlPoint, pointB.rightBackwardControlPoint, pointB.rightTrackBoundary));
    }
Beispiel #7
0
    public float GetTrackCrownAngle(float t)
    {
        float            curveT  = 1.0f / numberOfCurves;
        int              point   = Mathf.FloorToInt(t / curveT);
        float            ct      = Mathf.Clamp01((t - point * curveT) * numberOfCurves);
        float            hermite = SplineMaths.CalculateHermite(ct);
        TrackBuildRPoint pointA  = GetPoint(point);
        TrackBuildRPoint pointB  = GetPoint(point + 1);

        return(Mathf.LerpAngle(pointA.crownAngle, pointB.crownAngle, hermite));
    }
Beispiel #8
0
    public Vector3 GetTrackCross(float t)
    {
        float            curveT  = 1.0f / numberOfCurves;
        int              point   = Mathf.FloorToInt(t / curveT);
        float            ct      = Mathf.Clamp01((t - point * curveT) * numberOfCurves);
        float            hermite = SplineMaths.CalculateHermite(ct);
        TrackBuildRPoint pointA  = GetPoint(point);
        TrackBuildRPoint pointB  = GetPoint(point + 1);

        return(Vector3.Slerp(pointA.trackCross, pointB.trackCross, hermite));
    }
Beispiel #9
0
    /// <summary>
    /// unfinished!
    /// </summary>
    /// <param name="track"></param>
    /// <param name="selectedPoint"></param>
    public static void AddTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);

        float      twistDistance      = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength);
        Vector3    twistDirection     = atPoint.trackDirection;
        Vector3    twistMiddle        = atPoint.worldPosition;
        Vector3    twistUp            = atPoint.trackUp;
        Vector3    twistAxis          = Vector3.Cross(twistDirection, twistUp);
        float      twistRadius        = track.twistRadius;
        Vector3    twistStartPosition = -twistDirection * (twistDistance * 0.33f);
        Vector3    twistEndPosition   = twistDirection * (twistDistance * 0.33f);
        Vector3    twistCentreHeight  = twistUp * twistRadius;
        Quaternion twistAngle         = Quaternion.LookRotation(twistDirection, twistUp);
        Vector3    twistCenter        = atPoint.worldPosition + Vector3.up * twistRadius;
        float      controlPointLength = twistRadius / (Mathf.PI);

        int   numberOfPoints = track.twistPoints;
        float arcPercent     = 1.0f / numberOfPoints;

        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints + 1];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float   pointArcPercent   = arcPercent * i;
            float   radA              = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
            float   smoothI           = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent);
            Vector3 lateral           = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI));
            Vector3 pointPosition     = (pointLoopPosition) + lateral;
            Vector3 pointDirection    = Vector3.Cross(-pointLoopPosition, twistAxis).normalized;

            TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i);
            newTrackPoint.worldPosition       = twistCenter + pointPosition;
            newTrackPoint.trackUpQ            = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength);
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition      += twistStartPosition;
        atPoint.trackUpQ            = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack       = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength      = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
Beispiel #10
0
//    /// <summary>
//    /// Mark the pit lane as dirty so it will be recalculated/rebuilt
//    /// </summary>
//    public void SetPitDirty()
//    {
//        for (int i = 0; i < pitlane.numberOfPoints; i++)
//        {
//            pitlane[i].isDirty = true;
//        }
//    }
//
//    /// <summary>
//    /// Set pit lane point data to rerender
//    /// </summary>
//    public void ReRenderPit()
//    {
//        for (int i = 0; i < pitlane.numberOfPoints; i++)
//        {
//            pitlane[i].shouldReRender = true;
//        }
//    }


    public void SolveTangents()
    {
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];
            curve.dynamicTrackMesh.SolveTangents();
            curve.dynamicOffroadMesh.SolveTangents();
            curve.dynamicBumperMesh.SolveTangents();
            curve.dynamicBoundaryMesh.SolveTangents();
            curve.dynamicBottomMesh.SolveTangents();
        }
        _tangentsGenerated = true;
    }
Beispiel #11
0
    public Vector3 GetTrackDirection(float t)
    {
        float            curveT          = 1.0f / numberOfCurves;
        int              point           = Mathf.FloorToInt(t / curveT);
        float            ct              = Mathf.Clamp01((t - point * curveT) * numberOfCurves);
        float            hermite         = SplineMaths.CalculateHermite(ct);
        TrackBuildRPoint pointA          = GetPoint(point);
        TrackBuildRPoint pointB          = GetPoint(point + 1);
        Quaternion       trackDirectionA = Quaternion.LookRotation(pointA.trackDirection);
        Quaternion       trackDirectionB = Quaternion.LookRotation(pointB.trackDirection);
        Quaternion       trackDirectionQ = Quaternion.Slerp(trackDirectionA, trackDirectionB, hermite);

        return(trackDirectionQ * Vector3.forward);
    }
Beispiel #12
0
    public TrackBuildRPoint AddPoint(Vector3 position)
    {
#if UNITY_EDITOR
        TrackBuildRPoint point = Undo.AddComponent <TrackBuildRPoint>(gameObject); //ScriptableObject.CreateInstance<TrackBuildRPoint>();
#else
        TrackBuildRPoint point = gameObject.AddComponent <TrackBuildRPoint>();     //ScriptableObject.CreateInstance<TrackBuildRPoint>();
#endif
        point.baseTransform = baseTransform;
        point.position      = position;
        point.isDirty       = true;
        _points.Add(point);
        RecalculateCurves();
        return(point);
    }
Beispiel #13
0
    public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex)
    {
        TrackBuildRPoint atPoint = track[selectedPointIndex];
        int     atPointIndex     = selectedPointIndex;
        float   loopRadius       = track.loopRadius;
        float   trackWidth       = atPoint.width;
        Vector3 trackDirection   = atPoint.trackDirection.normalized;
        Vector3 trackUp          = atPoint.trackUpQ * Vector3.forward;
        Vector3 trackCross       = atPoint.trackCross;

        Vector3    entryPosition       = atPoint.worldPosition + (trackCross * trackWidth * 0.6f);
        Vector3    loopAxis            = Vector3.Cross(trackDirection, trackUp);
        Vector3    loopCenter          = atPoint.worldPosition + Vector3.up * loopRadius;
        Quaternion loopAngle           = Quaternion.FromToRotation(Vector3.right, trackDirection);
        float      controlPointLength  = loopRadius / (Mathf.PI);
        Vector3    controlPointLateral = -loopAxis;

        int   numberOfPoints = 6;
        float arcPercent     = 1.0f / numberOfPoints;

        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float            pointArcPercent   = arcPercent * i;
            TrackBuildRPoint newTrackPoint     = track.InsertPoint(atPointIndex + 1);
            float            rad               = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3          pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius);
            Vector3          lateral           = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent);
            Vector3          pointPosition     = (pointLoopPosition) + lateral;
            Vector3          pointDirection    = Vector3.Cross(-pointLoopPosition, loopAxis).normalized;
            newTrackPoint.worldPosition       = loopCenter + pointPosition;
            newTrackPoint.trackUpQ            = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral;
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition       = entryPosition;
        atPoint.trackUpQ            = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack       = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength      = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
Beispiel #14
0
    //Sample nextNormIndex position on the entire curve based on time (0-1)
    public Vector3 GetTrackPosition(float t)
    {
        if (realNumberOfPoints < 2)
        {
            Debug.LogError("Not enough points to define a curve");
            return(Vector3.zero);
        }
        float            curveT = 1.0f / numberOfCurves;
        int              point  = Mathf.FloorToInt(t / curveT);
        float            ct     = Mathf.Clamp01((t - point * curveT) * numberOfCurves);
        TrackBuildRPoint pointA = GetPoint(point);
        TrackBuildRPoint pointB = GetPoint(point + 1);

        return(SplineMaths.CalculateBezierPoint(ct, pointA.position, pointA.forwardControlPoint, pointB.backwardControlPoint, pointB.position));
    }
    public static void AddLoop(TrackBuildRTrack track, int selectedPointIndex)
    {
        TrackBuildRPoint atPoint = track[selectedPointIndex];
        int atPointIndex = selectedPointIndex;
        float loopRadius = track.loopRadius;
        float trackWidth = atPoint.width;
        Vector3 trackDirection = atPoint.trackDirection.normalized;
        Vector3 trackUp = atPoint.trackUpQ * Vector3.forward;
        Vector3 trackCross = atPoint.trackCross;

        Vector3 entryPosition = atPoint.worldPosition + (trackCross * trackWidth * 0.6f);
        Vector3 loopAxis = Vector3.Cross(trackDirection, trackUp);
        Vector3 loopCenter = atPoint.worldPosition + Vector3.up * loopRadius;
        Quaternion loopAngle = Quaternion.FromToRotation(Vector3.right, trackDirection);
        float controlPointLength = loopRadius / (Mathf.PI);
        Vector3 controlPointLateral = -loopAxis;

        int numberOfPoints = 6;
        float arcPercent = 1.0f / numberOfPoints;
        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[7];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float pointArcPercent = arcPercent * i;
            TrackBuildRPoint newTrackPoint = track.InsertPoint(atPointIndex + 1);
            float rad = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = loopAngle * ((new Vector3(Mathf.Sin(rad), Mathf.Cos(rad), 0)) * loopRadius);
            Vector3 lateral = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), pointArcPercent);
            Vector3 pointPosition = (pointLoopPosition) + lateral;
            Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, loopAxis).normalized;
            newTrackPoint.worldPosition = loopCenter + pointPosition;
            newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength) - controlPointLateral;
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition = entryPosition;
        atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (trackDirection * controlPointLength) + controlPointLateral;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
Beispiel #16
0
    public static void AddJumpTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

        float      trackWidth      = atPoint.width * 0.5f;
        Vector3    startCross      = atPoint.trackCross;
        Vector3    jumpDirection   = atPoint.trackDirection;
        Vector3    jumpMiddle      = atPoint.worldPosition;
        Quaternion atPointUpQ      = atPoint.trackUpQ;
        Quaternion trackUpJump     = Quaternion.AngleAxis(track.twistAngle, -jumpDirection);
        Quaternion trackCrossExit  = trackUpJump * (atPointUpQ);
        Quaternion trackCrossEntry = Quaternion.Inverse(trackUpJump) * (atPointUpQ);
        Vector3    jumpLateral     = startCross * track.twistAngle / 33.3f;

        Vector3 jumpHeight        = atPointUpQ * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f) + jumpHeight - jumpLateral;
        Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f) + jumpHeight + jumpLateral;

        lastPoint.extrudeTrack       = true;
        lastPoint.extrudeLength      = track.jumpHeight;
        lastPoint.extrudeCurveEnd    = true;
        lastPoint.extrudeTrackBottom = true;

        atPoint.Reset();
        atPoint.worldPosition       = jumpStartPosition;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight;
        atPoint.trackUpQ            = trackCrossExit;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);

        jumpEnd.worldPosition       = jumpEndPosition;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition - jumpHeight;
        jumpEnd.trackUpQ            = trackCrossEntry;
        jumpEnd.extrudeTrack        = true;
        jumpEnd.extrudeLength       = track.jumpHeight;
        jumpEnd.extrudeCurveEnd     = true;
        jumpEnd.extrudeTrackBottom  = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
Beispiel #17
0
    public TrackBuildRPoint InsertPoint(int index)
    {
#if UNITY_EDITOR
        Undo.IncrementCurrentGroup();
        TrackBuildRPoint point = Undo.AddComponent <TrackBuildRPoint>(gameObject); //ScriptableObject.CreateInstance<TrackBuildRPoint>();
#else
        TrackBuildRPoint point = gameObject.AddComponent <TrackBuildRPoint>();     //ScriptableObject.CreateInstance<TrackBuildRPoint>();
#endif
        point.baseTransform = baseTransform;
#if UNITY_EDITOR
        Undo.RecordObject(this, "Remove Point");
#endif
        _points.Insert(index, point);
#if UNITY_EDITOR
        Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
#endif
        RecalculateCurves();
        return(point);
    }
Beispiel #18
0
    public void RemovePoint(TrackBuildRPoint point)
    {
        if (_points.Count < 3)
        {
            Debug.Log("We can't see any point in allowing you to delete any more points so we're not going to do it.");
            return;
        }

#if UNITY_EDITOR
        Undo.IncrementCurrentGroup();
        _points.Remove(point);
        Undo.DestroyObjectImmediate(point.holder);
        Undo.DestroyObjectImmediate(point);
        Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
#else
        _points.Remove(point);
#endif
        RecalculateCurves();
    }
Beispiel #19
0
    public void RemoveTexture(TrackBuildRTexture texture)
    {
        int textureIndex = _textures.IndexOf(texture);


#if UNITY_EDITOR
        Undo.IncrementCurrentGroup();
        Undo.RecordObject(this, "Remove Texture");
        _textures.Remove(texture);
        Undo.DestroyObjectImmediate(texture);
        Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
#else
        _textures.Remove(texture);
#endif

        //ensure that curves are not referenceing textures that no longer exist
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];

            if (curve.trackTextureStyleIndex > textureIndex)
            {
                curve.trackTextureStyleIndex--;
            }
            if (curve.offroadTextureStyleIndex > textureIndex)
            {
                curve.offroadTextureStyleIndex--;
            }
            if (curve.bumperTextureStyleIndex > textureIndex)
            {
                curve.bumperTextureStyleIndex--;
            }
            if (curve.boundaryTextureStyleIndex > textureIndex)
            {
                curve.boundaryTextureStyleIndex--;
            }
            if (curve.bottomTextureStyleIndex > textureIndex)
            {
                curve.bottomTextureStyleIndex--;
            }
        }
    }
Beispiel #20
0
    public static void AddJump(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint   = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);
        TrackBuildRPoint nextPoint = track.GetPoint(selectedPoint + 1);

        float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
        float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, track.maxJumpLength);

        Vector3    jumpDirection = atPoint.trackDirection;
        Vector3    jumpMiddle    = atPoint.worldPosition;
        Vector3    startCross    = atPoint.trackCross;
        float      trackWidth    = atPoint.width * 0.5f;
        Quaternion trackUp       = atPoint.trackUpQ;

        Vector3 jumpHeight        = trackUp * (Vector3.forward * track.jumpHeight);
        Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f);
        Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f);

        lastPoint.extrudeTrack    = true;
        lastPoint.extrudeLength   = track.jumpHeight;
        lastPoint.extrudeCurveEnd = true;

        atPoint.Reset();
        atPoint.worldPosition       = jumpStartPosition + jumpHeight;
        atPoint.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpStartPosition + jumpHeight * 2;
        atPoint.trackUpQ            = trackUp;
        atPoint.render = false;

        TrackBuildRPoint jumpEnd = track.InsertPoint(selectedPoint + 1);

        jumpEnd.worldPosition       = jumpEndPosition + jumpHeight;
        jumpEnd.forwardControlPoint = jumpDirection * (jumpDistance * 0.5f) + jumpEndPosition;
        jumpEnd.trackUpQ            = trackUp;
        jumpEnd.extrudeTrack        = true;
        jumpEnd.extrudeLength       = track.jumpHeight;
        jumpEnd.extrudeCurveEnd     = true;

        atPoint.RecalculateStoredValues();
        jumpEnd.RecalculateStoredValues();
    }
Beispiel #21
0
    private static void ExportModel(TrackBuildR track)
    {
        GameObject baseObject = new GameObject(track.exportFilename);

        baseObject.transform.position = CURRENT_TRANSFORM.position;
        baseObject.transform.rotation = CURRENT_TRANSFORM.rotation;
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.0f);
        track.ForceFullRecalculation();
        EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.1f);
        try
        {
            TrackBuildRTrack trackData = track.track;

            //check overwrites...
            string newDirectory = ROOT_FOLDER + track.exportFilename;
            if (!CreateFolder(newDirectory))
            {
                EditorUtility.ClearProgressBar();
                return;
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.15f);

            int              numberOfCurves    = trackData.numberOfCurves;
            int              numberOfDynMeshes = 9;
            float            exportProgress    = 0.75f / (numberOfCurves * numberOfDynMeshes);
            ExportMaterial[] exportMaterials   = new ExportMaterial[1];
            ExportMaterial   exportTexture     = new ExportMaterial();

            TrackBuildRTexture[] textures = trackData.GetTexturesArray();
            int        textureCount       = textures.Length;
            Material[] materials          = new Material[textureCount];
            for (int t = 0; t < textureCount; t++)
            {
                TrackBuildRTexture texture = textures[t];
                if (!texture.isSubstance && !texture.isUSer)
                {
                    string materialPath = string.Format("{0}{1}/{2}.mat", ROOT_FOLDER, track.exportFilename, texture.customName);
                    if (File.Exists(materialPath))
                    {
                        Material mat = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material));
                        EditorUtility.CopySerialized(texture.material, mat);
                        AssetDatabase.SaveAssets();
                        materials[t] = mat;
                        continue;
                    }
                    Material tempMat = Object.Instantiate(texture.material);
                    AssetDatabase.CreateAsset(tempMat, materialPath);
                    materials[t] = (Material)AssetDatabase.LoadAssetAtPath(materialPath, typeof(Material));
                }
                else
                {
                    materials[t] = texture.isUSer ? texture.userMaterial : texture.proceduralMaterial;
                }
            }

            string[] dynNames      = { "track", "bumper", "boundary", "bottom", "offroad", "trackCollider" };
            string[] colliderNames = { "track collider", "wall collider", "offroad collider", "bumper collider" };
            for (int c = 0; c < numberOfCurves; c++)
            {
                TrackBuildRPoint curve = trackData[c];

                DynamicMesh[] dynMeshes = new DynamicMesh[numberOfDynMeshes];
                dynMeshes[0] = curve.dynamicTrackMesh;
                dynMeshes[1] = curve.dynamicBumperMesh;
                dynMeshes[2] = curve.dynamicBoundaryMesh;
                dynMeshes[3] = curve.dynamicBottomMesh;
                dynMeshes[4] = curve.dynamicOffroadMesh;
                dynMeshes[5] = curve.dynamicColliderMesh1; //track surface
                dynMeshes[6] = curve.dynamicColliderMesh2; //walls and roof
                dynMeshes[7] = curve.dynamicColliderMesh3; //track bottom and offroad
                dynMeshes[8] = curve.dynamicColliderMesh4; //bumpers

                int[]            textureIndeices = { curve.trackTextureStyleIndex, curve.bumperTextureStyleIndex, curve.boundaryTextureStyleIndex, curve.bottomTextureStyleIndex, curve.offroadTextureStyleIndex, 0 };
                PhysicMaterial[] physicMaterials = { trackData.Texture(curve.trackTextureStyleIndex).physicMaterial, trackData.Texture(curve.boundaryTextureStyleIndex).physicMaterial, trackData.Texture(curve.offroadTextureStyleIndex).physicMaterial, trackData.Texture(curve.bumperTextureStyleIndex).physicMaterial };

                for (int d = 0; d < numberOfDynMeshes; d++)
                {
                    int textureIndex = Mathf.Clamp(d, 0, 5);
                    if (EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "Exporting Track Curve " + c + " " + dynNames[textureIndex], 0.15f + exportProgress * (c * numberOfDynMeshes + d)))
                    {
                        EditorUtility.ClearProgressBar();
                        return;
                    }

                    DynamicMesh exportDynMesh = dynMeshes[d];
//                    if(track.includeTangents || exportDynMesh.isEmpty)
//                        exportDynMesh.Build();//rebuild with tangents

                    TrackBuildRTexture texture = trackData.Texture(textureIndeices[textureIndex]);
                    exportTexture.name      = texture.customName;
                    exportTexture.material  = texture.material;
                    exportTexture.generated = false;
                    exportTexture.filepath  = texture.filePath;
                    exportMaterials[0]      = exportTexture;

                    Material mat = materials[textureIndeices[textureIndex]];

                    int    meshCount = exportDynMesh.meshCount;
                    Mesh[] meshes    = exportDynMesh.meshes;
                    for (int i = 0; i < meshCount; i++)
                    {
                        Mesh exportMesh = meshes[i];
                        MeshUtility.Optimize(exportMesh);
                        string filenameSuffix = trackModelName(dynNames[textureIndex], c, (meshCount > 1) ? i : -1); // "trackCurve" + c + ((meshCount > 1) ? "_" + i.ToString() : "");
                        if (d > 4)                                                                                   //colliders
                        {
                            filenameSuffix = string.Format("{0}_{1}", filenameSuffix, (d % 5));
                        }
                        string filename = track.exportFilename + filenameSuffix;
                        Export(filename, ROOT_FOLDER + track.exportFilename + "/", track, exportMesh, exportMaterials);

                        if (track.createPrefabOnExport)
                        {
                            AssetDatabase.Refresh();//ensure the database is up to date...

                            string modelFilePath = ROOT_FOLDER + track.exportFilename + "/" + filename + FILE_EXTENTION;
                            if (d < numberOfDynMeshes - 4)
                            {
                                GameObject newModel = (GameObject)PrefabUtility.InstantiatePrefab(AssetDatabase.LoadMainAssetAtPath(modelFilePath));
                                newModel.name                    = filename;
                                newModel.transform.parent        = baseObject.transform;
                                newModel.transform.localPosition = Vector3.zero;
                                newModel.transform.localRotation = Quaternion.identity;

                                MeshRenderer[] renders = newModel.GetComponentsInChildren <MeshRenderer>();
                                foreach (MeshRenderer rend in renders)
                                {
                                    rend.material = mat;
                                }
                            }
                            else
                            {
                                int          colliderIndex  = d - (numberOfDynMeshes - 4);
                                GameObject   colliderObject = new GameObject(colliderNames[colliderIndex]);
                                MeshCollider collider       = colliderObject.AddComponent <MeshCollider>();
                                collider.sharedMesh                    = (Mesh)AssetDatabase.LoadAssetAtPath(modelFilePath, typeof(Mesh));
                                collider.material                      = physicMaterials[colliderIndex];
                                colliderObject.transform.parent        = baseObject.transform;
                                colliderObject.transform.localPosition = Vector3.zero;
                                colliderObject.transform.localRotation = Quaternion.identity;
                            }
                        }
                    }
                }
            }
            if (track.createPrefabOnExport)
            {
                string prefabPath = ROOT_FOLDER + track.exportFilename + "/" + track.exportFilename + ".prefab";
                Object prefab     = AssetDatabase.LoadAssetAtPath(prefabPath, typeof(GameObject));
                if (prefab == null)
                {
                    prefab = PrefabUtility.CreateEmptyPrefab(prefabPath);
                }
                PrefabUtility.ReplacePrefab(baseObject, prefab, ReplacePrefabOptions.ConnectToPrefab);
            }

            EditorUtility.DisplayCancelableProgressBar(PROGRESSBAR_TEXT, "", 0.70f);

            AssetDatabase.Refresh();//ensure the database is up to date...
        }
        catch (System.Exception e)
        {
            Debug.LogError("Track BuildR Export Error: " + e);
            EditorUtility.ClearProgressBar();
            AssetDatabase.Refresh();//ensure the database is up to date...
        }
        Object.DestroyImmediate(baseObject);
        EditorUtility.ClearProgressBar();
        EditorUtility.UnloadUnusedAssetsImmediate();
        AssetDatabase.Refresh();
    }
Beispiel #22
0
    public float GetTrackPercentage(TrackBuildRPoint point)
    {
        int index = _points.IndexOf(point);

        return(index / (float)numberOfPoints);
    }
 public void AddPoint(TrackBuildRPoint point)
 {
     point.baseTransform = baseTransform;
     _points.Add(point);
     RecalculateCurves();
 }
Beispiel #24
0
 public void InsertPoint(TrackBuildRPoint point, int index)
 {
     point.baseTransform = baseTransform;
     _points.Insert(index, point);
     RecalculateCurves();
 }
Beispiel #25
0
 public void AddPoint(TrackBuildRPoint point)
 {
     point.baseTransform = baseTransform;
     _points.Add(point);
     RecalculateCurves();
 }
 public void InsertPoint(TrackBuildRPoint point, int index)
 {
     point.baseTransform = baseTransform;
     _points.Insert(index, point);
     RecalculateCurves();
 }
Beispiel #27
0
    public void FromKML(string coordinates)
    {
        Clear();
        string[]       coorArray      = coordinates.Split(new [] { " " }, StringSplitOptions.RemoveEmptyEntries);
        List <Vector3> kmlpoints      = new List <Vector3>();
        Vector3        xyCenter       = new Vector3();
        Vector3        lastCoord      = Vector3.zero;
        int            numberOfCoords = coorArray.Length;

        for (int i = 0; i < numberOfCoords; i++)
        {
            string coord = coorArray[i];
            if (coord == "")
            {
                continue;
            }

            string[] coordEntry = coord.Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries);

            if (coordEntry.Length < 3)
            {
                continue;
            }

            float   KMLPointX   = float.Parse(coordEntry[0]);
            float   KMLPointY   = float.Parse(coordEntry[2]);
            float   KMLPointZ   = float.Parse(coordEntry[1]);
            Vector3 newKMLPoint = new Vector3(KMLPointX, KMLPointY, KMLPointZ);

            if (Vector3.Distance(newKMLPoint, lastCoord) < 1.0f && lastCoord != Vector3.zero)
            {
                continue;//skip duplicate point
            }
            kmlpoints.Add(newKMLPoint);
            xyCenter.x += newKMLPoint.x;
            xyCenter.z += newKMLPoint.z;

            lastCoord = newKMLPoint;
        }

        int numberOfPoints = kmlpoints.Count;

        xyCenter.x *= 1.0f / numberOfPoints;
        xyCenter.z *= 1.0f / numberOfPoints;

        if (Vector3.Distance(kmlpoints[numberOfPoints - 1], kmlpoints[0]) < 1.0f)
        {
            kmlpoints.RemoveAt(numberOfPoints - 1);
        }
        numberOfPoints = kmlpoints.Count;

        List <Vector3> eulerpoints     = new List <Vector3>();
        float          dataTrackLength = 0;
        Vector3        lastPoint       = Vector3.zero;

        for (int i = 0; i < numberOfPoints; i++)
        {
            Vector3 KMLPoint = kmlpoints[i];

            Vector3 newEulerPoint = GPSMaths.Simple(xyCenter, KMLPoint);
            newEulerPoint.y = KMLPoint.y;
            eulerpoints.Add(newEulerPoint);

            if (i > 0)
            {
                dataTrackLength += Vector3.Distance(lastPoint, newEulerPoint);
            }
            lastPoint = newEulerPoint;
        }


        if (dataTrackLength > 20000)
        {
            if (!EditorUtility.DisplayDialog("Really Long Track!", "The Data is creating a track length around " + (dataTrackLength / 1000).ToString("F1") + "km long", "Continue", "Cancel"))
            {
                return;
            }
        }

        if (dataTrackLength < 1)
        {
            if (EditorUtility.DisplayDialog("No Track!", "The Data not producing a viable track", "Ok"))
            {
                return;
            }
        }

        for (int i = 0; i < numberOfPoints; i++)
        {
            TrackBuildRPoint point = gameObject.AddComponent <TrackBuildRPoint>();
            point.baseTransform = baseTransform;
            point.position      = eulerpoints[i];
            point.isDirty       = true;
            _points.Add(point);
        }

        for (int i = 0; i < numberOfPoints; i++)
        {
            TrackBuildRPoint point            = _points[i];
            Vector3          thisPosition     = point.worldPosition;
            Vector3          lastPosition     = GetPoint(i - 1).worldPosition;
            Vector3          nextPosition     = GetPoint(i + 1).worldPosition;
            Vector3          backwardTrack    = thisPosition - lastPosition;
            Vector3          forwardTrack     = nextPosition - thisPosition;
            Vector3          controlDirection = (backwardTrack + forwardTrack).normalized;
            float            forwardMag       = forwardTrack.magnitude;
            float            backwardMag      = backwardTrack.magnitude;
            if (forwardMag == 0)
            {
                forwardMag = backwardMag;
            }
            if (backwardMag == 0)
            {
                backwardMag = forwardMag;
            }
            float controlMagnitude = Mathf.Min(forwardMag, backwardMag) * 0.1666f;
            point.forwardControlPoint = (controlDirection * controlMagnitude) + thisPosition;
        }
        InitTextures();
        RecalculateCurves();
    }
    /// <summary>
    /// unfinished!
    /// </summary>
    /// <param name="track"></param>
    /// <param name="selectedPoint"></param>
    public static void AddTwist(TrackBuildRTrack track, int selectedPoint)
    {
        TrackBuildRPoint atPoint = track[selectedPoint];
        TrackBuildRPoint lastPoint = track.GetPoint(selectedPoint - 1);

        float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, track.maxJumpLength);
        Vector3 twistDirection = atPoint.trackDirection;
//        Vector3 twistMiddle = atPoint.worldPosition;
        Vector3 twistUp = atPoint.trackUp;
        Vector3 twistAxis = Vector3.Cross(twistDirection, twistUp);
        float twistRadius = track.twistRadius;
        Vector3 twistStartPosition = -twistDirection * (twistDistance * 0.33f);
        Vector3 twistEndPosition = twistDirection * (twistDistance * 0.33f);
//        Vector3 twistCentreHeight = twistUp * twistRadius;
        Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp);
        Vector3 twistCenter = atPoint.worldPosition + Vector3.up * twistRadius;
        float controlPointLength = twistRadius / (Mathf.PI);

        int numberOfPoints = track.twistPoints;
        float arcPercent = 1.0f / numberOfPoints;
        TrackBuildRPoint[] loopPoints = new TrackBuildRPoint[numberOfPoints+1];
        for (int i = 0; i < numberOfPoints; i++)
        {
            float pointArcPercent = arcPercent * i;
            float radA = Mathf.PI * 2 * (pointArcPercent + 0.5f);
            Vector3 pointLoopPosition = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
            float smoothI = pointArcPercent * pointArcPercent * (3.0f - 2.0f * pointArcPercent);
            Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, pointArcPercent + (pointArcPercent - smoothI));
            Vector3 pointPosition = (pointLoopPosition) + lateral;
            Vector3 pointDirection = Vector3.Cross(-pointLoopPosition, twistAxis).normalized;

            TrackBuildRPoint newTrackPoint = track.InsertPoint(selectedPoint + 1 + i);
            newTrackPoint.worldPosition = twistCenter + pointPosition;
            newTrackPoint.trackUpQ = Quaternion.LookRotation(-pointLoopPosition, pointDirection);
            newTrackPoint.forwardControlPoint = newTrackPoint.worldPosition + (pointDirection * controlPointLength);
            loopPoints[i] = newTrackPoint;
        }
        atPoint.worldPosition += twistStartPosition;
        atPoint.trackUpQ = Quaternion.LookRotation(Vector3.up, atPoint.trackDirection);
        atPoint.forwardControlPoint = atPoint.worldPosition + (twistDirection * controlPointLength) - twistAxis;
        loopPoints[6] = atPoint;
        //                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;

        for (int i = 0; i < numberOfPoints + 1; i++)
        {
            loopPoints[i].extrudeTrack = true;
            loopPoints[i].extrudeTrackBottom = true;
            loopPoints[i].extrudeLength = 0.5f;
            loopPoints[i].RecalculateStoredValues();
        }
    }
    /// <summary>
    /// Warning - not working correctly - yet...
    /// </summary>
    /// <param name="track"></param>
    /// <param name="terrain"></param>
    /// <param name="curve"></param>
    public static void MergeTerrain(TrackBuildRTrack track, Terrain terrain, TrackBuildRPoint curve)
    {
        //        ResetTerrain(track, terrain);

        TerrainData terrainData = terrain.terrainData;
        int terrainWidth = terrainData.heightmapWidth;
        int terrainHeight = terrainData.heightmapHeight;
        float terrainHeightmapY = terrain.terrainData.heightmapScale.y;
        float terrainY = terrain.transform.position.y / terrainHeightmapY;
        Vector3 meshScale = terrainData.heightmapScale;
        float terrainAccuracy = track.terrainAccuracy;
        float terrainMergeMargin = track.terrainMergeMargin;

        float[,] originalData = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight);
        float[,] mergeData = new float[terrainWidth,terrainHeight];
        float[,] modifiedData = new float[terrainWidth,terrainHeight];
        int[,] modifiedPointLock = new int[terrainWidth,terrainHeight];

        Bounds trackBounds = new Bounds();
        if(curve.holder != null)
        {
            Renderer[] rends = curve.holder.GetComponentsInChildren<Renderer>();
            foreach(Renderer rend in rends)
                trackBounds.Encapsulate(rend.bounds);
        }

        Vector3 trackOffset = track.transform.position - terrain.transform.position;
        Vector3 trackScale = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z);

        float mergeWidth = track.terrainMergeWidth;
        AnimationCurve mergeCurve = track.mergeCurve;
        float minScaleUnit = Mathf.Min(meshScale.x, meshScale.z);
        int storedPointSize = curve.storedPointSize;
        for(int p = 0; p < storedPointSize - 1; p++)
        {
            Vector3 pointA = curve.sampledPoints[p];
            Vector3 pointB = curve.sampledPoints[p + 1];
            Vector3 crossA = curve.sampledTrackCrosses[p];
            Vector3 crossB = curve.sampledTrackCrosses[p + 1];
            float widthA = curve.sampledWidths[p] * terrainMergeMargin;
            float widthB = curve.sampledWidths[p + 1] * terrainMergeMargin;
            //                float heightA = (pointA.y - terrainAccuracy) * trackScale.y - terrainY;
            //                float heightB = (pointB.y - terrainAccuracy) * trackScale.y - terrainY;

            Vector3 lpointA = (pointA - crossA * (widthA + mergeWidth));
            Vector3 rpointA = (pointA + crossA * (widthA + mergeWidth));
            Vector3 lpointB = (pointB - crossB * (widthB + mergeWidth));
            Vector3 rpointB = (pointB + crossB * (widthB + mergeWidth));

            float crownA = curve.sampledCrowns[p] - terrainAccuracy;
            float crownB = curve.sampledCrowns[p + 1] - terrainAccuracy;

            float pointDistanceLeft = Vector3.Distance(lpointA, lpointB) * 1.8f;
            float pointDistanceRight = Vector3.Distance(rpointA, rpointB) * 1.8f;
            float pointDistance = Mathf.Max(pointDistanceLeft, pointDistanceRight);
            float pointFillResolution = minScaleUnit / pointDistance * 0.125f;

            float heightLA = (lpointA.y + track.transform.position.y - terrainAccuracy) * trackScale.y - terrainY;
            float heightRA = (rpointA.y + track.transform.position.y - terrainAccuracy) * trackScale.y - terrainY;
            float heightLB = (lpointB.y + track.transform.position.y
                - terrainAccuracy) * trackScale.y - terrainY;
            float heightRB = (rpointB.y + track.transform.position.y - terrainAccuracy) * trackScale.y - terrainY;

            for(float pf = 0; pf < 1; pf += pointFillResolution)//point a to point b
            {
                //Track Filler
                Vector3 fillPoint = Vector3.Lerp(pointA, pointB, pf);
                Vector3 fillCross = Vector3.Lerp(crossA, crossB, pf);
                float fillWidth = Mathf.Lerp(widthA, widthB, pf);// *1.2f;
                float fillCrown = Mathf.Lerp(crownA, crownB, pf);// *1.2f;
                float fillTrackHeightL = Mathf.Lerp(heightLA, heightLB, pf);
                float fillTrackHeightR = Mathf.Lerp(heightRA, heightRB, pf);

                Vector3 leftTrackPoint = fillPoint - fillCross * fillWidth;
                Vector3 rightTrackPoint = fillPoint + fillCross * fillWidth;

                int leftX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int leftY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                int rightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int rightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

                int diffX = leftX - rightX;
                int diffY = leftY - rightY;
                int trackCrossFillAmount = Mathf.Max(Mathf.Abs(diffX), 1) * Mathf.Max(Mathf.Abs(diffY), 1);
                for(int f = 0; f < trackCrossFillAmount; f++)//left to right
                {
                    float move = f / (float)trackCrossFillAmount;
                    int fillX = Mathf.RoundToInt(Mathf.Lerp(leftX, rightX, move));
                    int fillY = Mathf.RoundToInt(Mathf.Lerp(leftY, rightY, move));
                    if(fillX < 0 || fillY < 0 || fillX > terrainWidth || fillY > terrainHeight)
                        continue;
                    float crownHeight = Mathf.Sin(move * Mathf.PI) * fillCrown / terrainHeightmapY;
                    float fillTrackHeight = Mathf.Lerp(fillTrackHeightL, fillTrackHeightR, move) + crownHeight;
                    int currentPointLock = modifiedPointLock[fillY, fillX];
                    if(currentPointLock == 0 || mergeData[fillY, fillX] > fillTrackHeight)
                        mergeData[fillY, fillX] = fillTrackHeight;
                    modifiedPointLock[fillY, fillX] = 1;//point lock
                }

                //Merge
                Vector3 leftMergePoint = leftTrackPoint - fillCross * mergeWidth;

                int leftMergeLeftX = Mathf.RoundToInt(((leftMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int leftMergeLeftY = Mathf.RoundToInt(((leftMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                int leftMergeRightX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int leftMergeRightY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                //                  
                int leftMergeDiffX = leftMergeLeftX - leftMergeRightX;
                int leftMergeDiffY = leftMergeLeftY - leftMergeRightY;
                int leftMergeFillAmount = Mathf.Max(Mathf.Abs(leftMergeDiffX), 1) * Mathf.Max(Mathf.Abs(leftMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY));
                for(int f = 0; f < leftMergeFillAmount; f++)
                {
                    float move = f / (float)leftMergeFillAmount;
                    int fillX = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftX, leftMergeRightX, move));
                    int fillY = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftY, leftMergeRightY, move));
                    if(fillX < 0 || fillY < 0 || fillX > terrainWidth || fillY > terrainHeight)
                        continue;
                    float curveStrength = mergeCurve.Evaluate(move);
                    float fillTrackHeight = fillTrackHeightL;
                    float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength);
                    int pointLock = modifiedPointLock[fillY, fillX];
                    float currentMergeHeight = mergeData[fillY, fillX];
                    float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight);
                    float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight);
                    if(newDifference < currentDifference && pointLock == 0)
                    {
                        mergeData[fillY, fillX] = mergeHeight;
                    }
                }

                Vector3 rightMergePoint = rightTrackPoint + fillCross * mergeWidth;
                int rightMergeLeftX = Mathf.RoundToInt(((rightMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int rightMergeLeftY = Mathf.RoundToInt(((rightMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                int rightMergeRightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                int rightMergeRightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

                //                  
                int rightMergeDiffX = rightMergeLeftX - rightMergeRightX;
                int rightMergeDiffY = rightMergeLeftY - rightMergeRightY;
                int rightMergeFillAmount = Mathf.Max(Mathf.Abs(rightMergeDiffX), 1) * Mathf.Max(Mathf.Abs(rightMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY));
                for(int f = 0; f < rightMergeFillAmount; f++)
                {
                    float move = f / (float)rightMergeFillAmount;
                    int fillX = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftX, rightMergeRightX, move));
                    int fillY = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftY, rightMergeRightY, move));
                    if(fillX < 0 || fillY < 0 || fillX > terrainWidth || fillY > terrainHeight)
                        continue;
                    float curveStrength = mergeCurve.Evaluate(move);
                    float fillTrackHeight = fillTrackHeightR;
                    float mergeHeight = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength);
                    int pointLock = modifiedPointLock[fillY, fillX];
                    float currentMergeHeight = mergeData[fillY, fillX];
                    float currentDifference = Mathf.Abs(currentMergeHeight - fillTrackHeight);
                    float newDifference = Mathf.Abs(mergeHeight - fillTrackHeight);
                    if(newDifference < currentDifference && pointLock == 0)
                    {
                        mergeData[fillY, fillX] = mergeHeight;
                    }
                }
            }
        }

        for(int x = 0; x < terrainWidth; x++)
        {
            for(int y = 0; y < terrainHeight; y++)
            {
                bool isNotEdge = x > 0 && x < terrainWidth - 1 && y > 0 && y < terrainHeight - 1;
                if(mergeData[x, y] == 0)
                {
                    int mergeNeighbours = 0;
                    if(isNotEdge)
                    {
                        mergeNeighbours += (mergeData[x + 1, y] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x - 1, y] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x, y + 1] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x, y - 1] != 0) ? 1 : 0;
                    }
                    if(mergeNeighbours > 1)//if a hole is surounded by rasied terrain in two or more neighbouring places
                    {
                        float mergeHeight = 0;
                        mergeHeight += (mergeData[x + 1, y] != 0) ? mergeData[x + 1, y] : 0;
                        mergeHeight += (mergeData[x - 1, y] != 0) ? mergeData[x - 1, y] : 0;
                        mergeHeight += (mergeData[x, y + 1] != 0) ? mergeData[x, y + 1] : 0;
                        mergeHeight += (mergeData[x, y - 1] != 0) ? mergeData[x, y - 1] : 0;
                        modifiedData[x, y] = mergeHeight / mergeNeighbours;//clean up holes
                    }
                    else
                    {
                        modifiedData[x, y] = originalData[x, y];//use original
                    }
                }
                else
                {
                    modifiedData[x, y] = mergeData[x, y];
                }

                terrainData.SetHeights(0, 0, modifiedData);
                terrain.terrainData = terrainData;
            }
        }
    }
    public void RemovePoint(TrackBuildRPoint point)
    {
        if(_points.Count < 3)
        {
            Debug.Log("We can't see any point in allowing you to delete any more points so we're not going to do it.");
            return;
        }

#if UNITY_EDITOR
        Undo.IncrementCurrentGroup();
        _points.Remove(point);
        Undo.DestroyObjectImmediate(point.holder);
        Undo.DestroyObjectImmediate(point);
        Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
#else
        _points.Remove(point);
#endif
        RecalculateCurves();
    }
 public float GetTrackPercentage(TrackBuildRPoint point)
 {
     int index = _points.IndexOf(point);
     return index / (float)numberOfPoints;
 }
Beispiel #32
0
    public void RecalculateCurves()
    {
        if (_points.Count < 2)//there is no track with only one point :o)
        {
            return;
        }

        if (isDirty)
        {
            _tangentsGenerated = false;
            _lightmapGenerated = false;
            _optimised         = false;
        }

        //calculate approx bezier arc length per curve
        for (int i = 0; i < realNumberOfPoints; i++)
        {
            TrackBuildRPoint pointA        = GetPoint(i);
            TrackBuildRPoint pointB        = GetPoint(i + 1);
            float            thisArcLength = 0;
            thisArcLength       += Vector3.Distance(pointA.position, pointA.forwardControlPoint);
            thisArcLength       += Vector3.Distance(pointA.forwardControlPoint, pointB.backwardControlPoint);
            thisArcLength       += Vector3.Distance(pointB.backwardControlPoint, pointB.position);
            _points[i].arcLength = thisArcLength;
            if (thisArcLength == 0)
            {
                DestroyImmediate(pointA);
                i--;
            }
        }

        for (int i = 0; i < realNumberOfPoints; i++)
        {
            TrackBuildRPoint pointA = GetPoint(i);
            TrackBuildRPoint pointB = GetPoint(i + 1);
            TrackBuildRPoint pointC = GetPoint(i - 1);
            pointA.nextPoint = pointB;
            pointA.lastPoint = pointC;
            pointA.pointName = "point " + i;
        }

        foreach (TrackBuildRPoint curve in _points)
        {
            if (!curve.curveIsDirty)//only recalculate modified points
            {
                continue;
            }

            if (curve.arcLength > 0)
            {
                TrackBuildRPoint pointA = curve;
                TrackBuildRPoint pointB = curve.nextPoint;

                //Build accurate arc length data into curve
                curve.center = Vector3.zero;
                int   arcLengthResolution = Mathf.Max(Mathf.RoundToInt(curve.arcLength * 10), 1);
                float alTime = 1.0f / arcLengthResolution;
                float calculatedTotalArcLength = 0;
                curve.storedArcLengthsFull    = new float[arcLengthResolution];
                curve.storedArcLengthsFull[0] = 0.0f;
                Vector3 pA = curve.position;
                for (int i = 0; i < arcLengthResolution - 1; i++)
                {
                    curve.center += pA;
                    float   altB      = alTime * (i + 1) + alTime;
                    Vector3 pB        = SplineMaths.CalculateBezierPoint(altB, curve.position, curve.forwardControlPoint, pointB.backwardControlPoint, pointB.position);
                    float   arcLength = Vector3.Distance(pA, pB);
                    calculatedTotalArcLength         += arcLength;
                    curve.storedArcLengthsFull[i + 1] = calculatedTotalArcLength;
                    pA = pB;//switch over values so we only calculate the bezier once
                }
                curve.arcLength = calculatedTotalArcLength;
                curve.center   /= arcLengthResolution;

                int storedPointSize = Mathf.RoundToInt(calculatedTotalArcLength / meshResolution);
                curve.storedPointSize = storedPointSize;
                curve.normalisedT     = new float[storedPointSize];
                curve.targetSize      = new float[storedPointSize];
                curve.midPointPerc    = new float[storedPointSize];
                curve.prevNormIndex   = new int[storedPointSize];
                curve.nextNormIndex   = new int[storedPointSize];
                curve.clipArrayLeft   = new bool[storedPointSize];
                curve.clipArrayRight  = new bool[storedPointSize];

                //calculate normalised spline data
                int normalisedIndex = 0;
                curve.normalisedT[0] = 0;
                for (int p = 1; p < storedPointSize; p++)
                {
                    float t            = p / (float)(storedPointSize - 1);
                    float targetLength = t * calculatedTotalArcLength;
                    curve.targetSize[p] = targetLength;
                    int it = 1000;
                    while (targetLength > curve.storedArcLengthsFull[normalisedIndex])
                    {
                        normalisedIndex++;
                        it--;
                        if (it < 0)
                        {
                            curve.normalisedT[p] = 0;
                            break;
                        }
                    }

                    normalisedIndex = Mathf.Min(normalisedIndex, arcLengthResolution);//ensure we've not exceeded the length

                    int prevNormIndex = Mathf.Max((normalisedIndex - 1), 0);
                    int nextNormIndex = normalisedIndex;

                    float lengthBefore       = curve.storedArcLengthsFull[prevNormIndex];
                    float lengthAfter        = curve.storedArcLengthsFull[nextNormIndex];
                    float midPointPercentage = (targetLength - lengthBefore) / (lengthAfter - lengthBefore);
                    curve.midPointPerc[p]  = midPointPercentage;
                    curve.prevNormIndex[p] = prevNormIndex;
                    curve.nextNormIndex[p] = nextNormIndex;
                    float normalisedT = (normalisedIndex + midPointPercentage) / arcLengthResolution;//lerp between the values to get the exact normal T
                    curve.normalisedT[p] = normalisedT;
                }

                curve.sampledPoints              = new Vector3[storedPointSize];
                curve.sampledLeftBoundaryPoints  = new Vector3[storedPointSize];
                curve.sampledRightBoundaryPoints = new Vector3[storedPointSize];
                curve.sampledWidths              = new float[storedPointSize];
                curve.sampledCrowns              = new float[storedPointSize];
                curve.sampledTrackDirections     = new Vector3[storedPointSize];
                curve.sampledTrackUps            = new Vector3[storedPointSize];
                curve.sampledTrackCrosses        = new Vector3[storedPointSize];
                curve.sampledAngles              = new float[storedPointSize];
                for (int p = 0; p < storedPointSize; p++)
                {
                    float tN = curve.normalisedT[p];
                    float tH = SplineMaths.CalculateHermite(tN);
                    curve.sampledPoints[p]              = SplineMaths.CalculateBezierPoint(tN, pointA.position, pointA.forwardControlPoint, pointB.backwardControlPoint, pointB.position);
                    curve.sampledLeftBoundaryPoints[p]  = SplineMaths.CalculateBezierPoint(tN, pointA.leftTrackBoundary, pointA.leftForwardControlPoint, pointB.leftBackwardControlPoint, pointB.leftTrackBoundary);
                    curve.sampledRightBoundaryPoints[p] = SplineMaths.CalculateBezierPoint(tN, pointA.rightTrackBoundary, pointA.rightForwardControlPoint, pointB.rightBackwardControlPoint, pointB.rightTrackBoundary);
                    curve.sampledWidths[p]              = Mathf.LerpAngle(pointA.width, pointB.width, tH);
                    curve.sampledCrowns[p]              = Mathf.LerpAngle(pointA.crownAngle, pointB.crownAngle, tH);
                    curve.sampledTrackUps[p]            = Quaternion.Slerp(pointA.trackUpQ, pointB.trackUpQ, tH) * Vector3.forward;
                    curve.clipArrayLeft[p]              = true;
                    curve.clipArrayRight[p]             = true;
                }
            }
        }
        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = _points[i];
            if (!curve.curveIsDirty)//only recalculate modified points
            {
                continue;
            }
            if (curve.arcLength > 0)
            {
                int lastCurveIndex         = (i > 0) ? i - 1 : (_looped) ? numberOfCurves - 1 : 0;
                int nextCurveIndex         = (i < numberOfCurves - 1) ? i + 1 : (_looped) ? 0 : numberOfCurves - 1;
                TrackBuildRPoint lastcurve = _points[lastCurveIndex];
                TrackBuildRPoint nextcurve = _points[nextCurveIndex];

                int storedPointSize = curve.storedPointSize;
                for (int p = 0; p < storedPointSize; p++)
                {
                    int pA = p - 1;
                    int pB = p;
                    int pC = p + 1;
                    if (pA < 0)
                    {
                        pA = 0;
                    }
                    if (pC >= storedPointSize)
                    {
                        pC = storedPointSize - 1;
                    }

                    Vector3 sampledPointA = curve.sampledPoints[pA];
                    Vector3 sampledPointB = curve.sampledPoints[pB];
                    Vector3 sampledPointC = curve.sampledPoints[pC];

                    if (p == 0 && lastcurve != null && lastcurve.sampledPoints.Length > 1)
                    {
                        sampledPointA = lastcurve.sampledPoints[lastcurve.storedPointSize - 2];//retrieve the penultimate point from the last curve
                    }
                    if (p == storedPointSize - 1 && nextcurve != null && nextcurve.sampledPoints.Length > 1)
                    {
                        sampledPointC = nextcurve.sampledPoints[1];//retrieve the second point from the next curve
                    }
                    Vector3 sampledTrackDirectionA = (sampledPointB - sampledPointA);
                    Vector3 sampledTrackDirectionB = (sampledPointC - sampledPointB);
                    Vector3 sampledTrackDirection  = (sampledTrackDirectionA + sampledTrackDirectionB).normalized;
                    curve.sampledTrackDirections[pB] = sampledTrackDirection;
                    curve.sampledTrackCrosses[pB]    = Vector3.Cross(curve.sampledTrackUps[pB], sampledTrackDirection);
                    curve.sampledAngles[pB]          = Vector3.Angle(sampledTrackDirectionA, sampledTrackDirectionB) * -Mathf.Sign(Vector3.Dot((sampledTrackDirectionB - sampledTrackDirectionA), curve.sampledTrackCrosses[pB]));

                    curve.clipArrayLeft[pB]  = true;
                    curve.clipArrayRight[pB] = true;
                }
            }
        }

        bool dirtyTextures = false;

        foreach (TrackBuildRTexture texture in _textures)
        {
            if (texture.isDirty)
            {
                dirtyTextures = true;//if nextNormIndex point was dirty, ensure it's rerendered
            }
            texture.isDirty = false;
        }

        foreach (TrackBuildRPoint point in _points)
        {
            if (point.curveIsDirty || dirtyTextures)
            {
                point.shouldReRender = true;//if nextNormIndex point was dirty, ensure it's rerendered
            }
        }
        //clean points
        foreach (TrackBuildRPoint point in _points)
        {
            point.isDirty = false;//reset all points - data is no longer considered dirty
        }
        //recalculate track length
        _trackLength = 0;
        foreach (TrackBuildRPoint curve in _points)
        {
            _trackLength += curve.arcLength;
        }
    }
    void OnSceneGUI()
    {
        if (_track.drawMode)
        {
            DrawTrack();
            return;
        }

        if (SceneView.focusedWindow != null)
        {
            SceneView.focusedWindow.wantsMouseMove = false;
        }
        Vector3 position    = _trackBuildR.transform.position;
        Camera  sceneCamera = Camera.current;

        _handleSize = HandleUtility.GetHandleSize(_trackBuildR.transform.position) * 0.1f;

        int realNumberOfPoints = _track.realNumberOfPoints;

        Ray        mouseRay           = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
        Quaternion mouseLookDirection = Quaternion.LookRotation(-mouseRay.direction);
        int        numberOfCurves     = _track.numberOfCurves;

        switch (_trackBuildR.mode)
        {
        case TrackBuildR.modes.track:
            Handles.color = TrackBuildRColours.GREEN;
            switch (_trackBuildR.pointMode)
            {
            case TrackBuildR.pointModes.add:

                if (SceneView.focusedWindow != null)
                {
                    SceneView.focusedWindow.wantsMouseMove = true;
                }

                if (Event.current.type == EventType.MouseMove)
                {
                    Repaint();
                }

                Handles.color = TrackBuildRColours.GREY;
                for (int i = 0; i < _track.realNumberOfPoints; i++)
                {
                    Vector3 pointPos   = _track[i].worldPosition;
                    float   handleSize = HandleUtility.GetHandleSize(pointPos);
                    Handles.DotCap(0, pointPos, Quaternion.identity, handleSize * 0.05f);
                }

                Handles.color = TrackBuildRColours.GREEN;
                float   mousePercentage = NearestmMousePercentage();      // _track.GetNearestPoint(mousePlanePoint);
                Vector3 mouseTrackPoint = _track.GetTrackPosition(mousePercentage) + position;
                Handles.Label(mouseTrackPoint, "Add New Track Point");
                float newPointHandleSize = HandleUtility.GetHandleSize(mouseTrackPoint) * HANDLE_SCALE;
                if (Handles.Button(mouseTrackPoint, mouseLookDirection, newPointHandleSize, newPointHandleSize, Handles.DotCap))
                {
                    int newPointIndex         = _track.GetLastPointIndex(mousePercentage);
                    TrackBuildRPoint newPoint = _track.InsertPoint(newPointIndex + 1);
                    newPoint.worldPosition = mouseTrackPoint;
                    newPoint.width         = _track.GetTrackWidth(mousePercentage);
                    newPoint.crownAngle    = _track.GetTrackCrownAngle(mousePercentage);
                    selectedPoint          = newPointIndex + 1;
                    GUI.changed            = true;
                    _trackBuildR.pointMode = TrackBuildR.pointModes.transform;
                }
                break;

            case TrackBuildR.pointModes.remove:

                if (SceneView.focusedWindow != null)
                {
                    SceneView.focusedWindow.wantsMouseMove = true;
                }

                Handles.color = TrackBuildRColours.RED;
                for (int i = 0; i < realNumberOfPoints; i++)
                {
                    TrackBuildRPoint point = _track[i];

                    float pointHandleSize = HandleUtility.GetHandleSize(point.worldPosition) * HANDLE_SCALE;
                    Handles.Label(point.worldPosition, "Remove Track Point");
                    if (Handles.Button(point.worldPosition, mouseLookDirection, pointHandleSize, pointHandleSize, Handles.DotCap))
                    {
                        _track.RemovePoint(point);
                        GUI.changed            = true;
                        _trackBuildR.pointMode = TrackBuildR.pointModes.transform;
                    }
                }

                break;

            default:

                SceneGUIPointBased();
                break;
            }

            //draw track outline
            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint curve = _track[i];
                if (curve == null)
                {
                    continue;
                }
                int curvePoints = curve.storedPointSize;

                float dotPA = Vector3.Dot(sceneCamera.transform.forward, curve.worldPosition - sceneCamera.transform.position);
                float dotPB = Vector3.Dot(sceneCamera.transform.forward, curve.nextPoint.worldPosition - sceneCamera.transform.position);

                if (dotPA < 0 && dotPB < 0)
                {
                    continue;
                }

                float curveDistance = Vector3.Distance(sceneCamera.transform.position, curve.center);
                int   pointJump     = Mathf.Max((int)(curveDistance / 20.0f), 1);
                Color trackOutline  = curve.render ? TrackBuildRColours.GREEN : TrackBuildRColours.RED;
                Color trackOutlineA = trackOutline;
                trackOutlineA.a = 0.5f;
                for (int p = pointJump; p < curvePoints; p += pointJump)
                {
                    int indexA = p - pointJump;
                    int indexB = p;

                    if (p + pointJump > curvePoints - 1)
                    {
                        indexB = curvePoints - 1;
                    }

                    Handles.color = trackOutlineA;
                    Handles.DrawLine(curve.sampledPoints[indexA] + position, curve.sampledPoints[indexB] + position);
                    Handles.color = trackOutline;
                    Vector3 trackCrossWidth = curve.sampledTrackCrosses[indexA] * (curve.sampledWidths[indexA] * 0.5f);
                    Handles.DrawLine(curve.sampledPoints[indexA] + trackCrossWidth + position, curve.sampledPoints[indexB] + trackCrossWidth + position);
                    Handles.DrawLine(curve.sampledPoints[indexA] - trackCrossWidth + position, curve.sampledPoints[indexB] - trackCrossWidth + position);
                }
            }
            break;

        case TrackBuildR.modes.boundary:

            //draw boundary outline
            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint curve = _track[i];
                int curvePoints        = curve.storedPointSize;

                float dotPA = Vector3.Dot(sceneCamera.transform.forward, curve.worldPosition - sceneCamera.transform.position);
                float dotPB = Vector3.Dot(sceneCamera.transform.forward, curve.nextPoint.worldPosition - sceneCamera.transform.position);

                if (dotPA < 0 && dotPB < 0)
                {
                    continue;
                }

                float curveDistance = Vector3.Distance(sceneCamera.transform.position, curve.center);
                int   pointJump     = Mathf.Max((int)(curveDistance / 20.0f), 1);
                for (int p = pointJump; p < curvePoints; p += pointJump)
                {
                    int indexA = p - pointJump;
                    int indexB = p;

                    if (p + pointJump > curvePoints - 1)
                    {
                        indexB = curvePoints - 1;
                    }

                    if (_track.disconnectBoundary)
                    {
                        Handles.color = TrackBuildRColours.BLUE;
                        Handles.DrawLine(curve.sampledLeftBoundaryPoints[indexA] + position, curve.sampledLeftBoundaryPoints[indexB] + position);
                        Handles.color = TrackBuildRColours.RED;
                        Handles.DrawLine(curve.sampledRightBoundaryPoints[indexA] + position, curve.sampledRightBoundaryPoints[indexB] + position);
                    }
                    else
                    {
                        Vector3 trackCrossWidth = curve.sampledTrackCrosses[indexA] * (curve.sampledWidths[indexA] * 0.5f);
                        Handles.color = TrackBuildRColours.BLUE;
                        Handles.DrawLine(curve.sampledPoints[indexA] + trackCrossWidth + position, curve.sampledPoints[indexB] + trackCrossWidth + position);
                        Handles.color = TrackBuildRColours.RED;
                        Handles.DrawLine(curve.sampledPoints[indexA] - trackCrossWidth + position, curve.sampledPoints[indexB] - trackCrossWidth + position);
                    }
                }
            }
            SceneGUIPointBased();
            break;

        case TrackBuildR.modes.textures:

            for (int i = 0; i < numberOfCurves; i++)
            {
                TrackBuildRPoint thisCurve = _track[i];

                float pointHandleSize = HandleUtility.GetHandleSize(thisCurve.center) * HANDLE_SCALE;
                Handles.color = (i == selectedCurveIndex) ? TrackBuildRColours.RED : TrackBuildRColours.BLUE;
                if (Handles.Button(thisCurve.center, Quaternion.identity, pointHandleSize, pointHandleSize, Handles.DotCap))
                {
                    selectedCurveIndex         = i;
                    GUIUtility.hotControl      = 0;
                    GUIUtility.keyboardControl = 0;
                    GUI.changed = true;
                }
            }


            Handles.color = TrackBuildRColours.RED;
            TrackBuildRPoint selectedCurve  = _track[selectedCurveIndex];
            int numberOfSelectedCurvePoints = selectedCurve.storedPointSize;
            for (int i = 0; i < numberOfSelectedCurvePoints - 1; i++)
            {
                Vector3 leftPointA  = selectedCurve.sampledLeftBoundaryPoints[i];
                Vector3 leftPointB  = selectedCurve.sampledLeftBoundaryPoints[i + 1];
                Vector3 rightPointA = selectedCurve.sampledRightBoundaryPoints[i];
                Vector3 rightPointB = selectedCurve.sampledRightBoundaryPoints[i + 1];

                Handles.DrawLine(leftPointA, leftPointB);
                Handles.DrawLine(rightPointA, rightPointB);

                if (i == 0)
                {
                    Handles.DrawLine(leftPointA, rightPointA);
                }
                if (i == numberOfSelectedCurvePoints - 2)
                {
                    Handles.DrawLine(leftPointB, rightPointB);
                }
            }

            break;

        case TrackBuildR.modes.terrain:

            //nothing

            break;

        case TrackBuildR.modes.stunt:

            SceneGUIPointBased();

            TrackBuildRPoint atPoint   = _track[selectedPoint];
            TrackBuildRPoint lastPoint = _track.GetPoint(selectedPoint - 1);
            TrackBuildRPoint nextPoint = _track.GetPoint(selectedPoint + 1);
            float            trackWidth;
            Vector3          startCross;
            Vector3          p0, p1, p2, p3, p4, p5, p6, p7;
            switch (_trackBuildR.stuntMode)
            {
            case TrackBuildR.stuntModes.loop:

                atPoint    = _track[selectedPoint];
                trackWidth = atPoint.width;

                float      loopRadius       = _track.loopRadius;
                Vector3    loopPosition     = atPoint.worldPosition;
                Vector3    trackDirection   = atPoint.trackDirection.normalized;
                Vector3    trackup          = atPoint.trackUpQ * Vector3.forward;
                Vector3    trackCross       = atPoint.trackCross;
                Vector3    loopCentreHeight = loopRadius * trackup;
                Quaternion loopAngle        = Quaternion.FromToRotation(Vector3.right, trackDirection);
                for (float i = 0; i < 0.99f; i += 0.01f)
                {
                    float   radA = Mathf.PI * 2 * (i + 0.5f);
                    float   radB = Mathf.PI * 2 * (i + 0.51f);
                    Vector3 pointLoopPositionA = loopAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * loopRadius);
                    Vector3 pointLoopPositionB = loopAngle * ((new Vector3(Mathf.Sin(radB), Mathf.Cos(radB), 0)) * loopRadius);
                    Vector3 lateral            = Vector3.Lerp((trackCross * trackWidth * -0.6f), (trackCross * trackWidth * 0.6f), i);
                    Vector3 pointPositionA     = (pointLoopPositionA) + lateral + loopPosition + loopCentreHeight;
                    Vector3 pointPositionB     = (pointLoopPositionB) + lateral + loopPosition + loopCentreHeight;
                    Handles.DrawLine(pointPositionA, pointPositionB);
                }
                break;

            case TrackBuildR.stuntModes.jump:

                atPoint   = _track[selectedPoint];
                lastPoint = _track.GetPoint(selectedPoint - 1);
                nextPoint = _track.GetPoint(selectedPoint + 1);

                float trackPartDistance = lastPoint.arcLength + atPoint.arcLength;
                float jumpDistance      = Mathf.Min(trackPartDistance * 0.333f, _track.maxJumpLength);

                Vector3 jumpDirection = atPoint.trackDirection;
                Vector3 jumpMiddle    = atPoint.worldPosition;
                startCross = atPoint.trackCross;
                trackWidth = atPoint.width * 0.5f;
                Quaternion trackUp = atPoint.trackUpQ;

                Vector3 jumpHeight        = trackUp * (Vector3.forward * _track.jumpHeight);
                Vector3 jumpStartPosition = jumpMiddle - jumpDirection * (jumpDistance * 0.33f);
                Vector3 jumpEndPosition   = jumpMiddle + jumpDirection * (jumpDistance * 0.33f);

                p0 = lastPoint.worldPosition + trackWidth * startCross;
                p1 = lastPoint.worldPosition - trackWidth * startCross;
                p2 = jumpStartPosition + trackWidth * startCross + jumpHeight;
                p3 = jumpStartPosition - trackWidth * startCross + jumpHeight;

                p4 = jumpEndPosition + trackWidth * startCross + jumpHeight;
                p5 = jumpEndPosition - trackWidth * startCross + jumpHeight;
                p6 = nextPoint.worldPosition + trackWidth * startCross;
                p7 = nextPoint.worldPosition - trackWidth * startCross;

                Handles.DrawLine(p0, p2);
                Handles.DrawLine(p1, p3);
                Handles.DrawLine(p0, p1);
                Handles.DrawLine(p2, p3);
                Handles.DrawLine(p2, p2 - jumpHeight);
                Handles.DrawLine(p3, p3 - jumpHeight);
                Handles.DrawLine(p0, p2 - jumpHeight);
                Handles.DrawLine(p1, p3 - jumpHeight);

                Handles.DrawLine(p4, p6);
                Handles.DrawLine(p5, p7);
                Handles.DrawLine(p4, p5);
                Handles.DrawLine(p6, p7);
                Handles.DrawLine(p4, p4 - jumpHeight);
                Handles.DrawLine(p5, p5 - jumpHeight);
                Handles.DrawLine(p6, p4 - jumpHeight);
                Handles.DrawLine(p7, p5 - jumpHeight);

                break;

//                        case TrackBuildR.stuntModes.twist:
//
//                        atPoint = _track[selectedPoint];
//                        lastPoint = _track.GetPoint(selectedPoint - 1);
//
//                        float twistDistance = Mathf.Min((lastPoint.arcLength + atPoint.arcLength) * 0.333f, _track.maxJumpLength);
//
//                        Vector3 twistDirection = atPoint.trackDirection;
//                        Vector3 twistMiddle = atPoint.worldPosition;
//                        Vector3 twistUp = atPoint.trackUp;
//                        float twistRadius = _track.twistRadius;
//                        Vector3 twistStartPosition = twistMiddle - twistDirection * (twistDistance * 0.33f);
//                        Vector3 twistEndPosition = twistMiddle + twistDirection * (twistDistance * 0.33f);
//                        Vector3 twistCentreHeight = twistUp * twistRadius;
//                        Quaternion twistAngle = Quaternion.LookRotation(twistDirection, twistUp);
//                        for(float i = 0; i < 0.99f; i += 0.01f )
//                        {
//                            float radA = Mathf.PI * 2 * (i+0.5f);
//                            float radB = Mathf.PI * 2 * (i+0.51f);
//                            Vector3 pointLoopPositionA = twistAngle * ((new Vector3(Mathf.Sin(radA), Mathf.Cos(radA), 0)) * twistRadius);
//                            Vector3 pointLoopPositionB = twistAngle * ((new Vector3(Mathf.Sin(radB), Mathf.Cos(radB), 0)) * twistRadius);
//                            float smoothI = i * i * (3.0f - 2.0f * i);
//                            Vector3 lateral = Vector3.Lerp(twistStartPosition, twistEndPosition, i + (i-smoothI));
//                            Vector3 pointPositionA = (pointLoopPositionA) + lateral + twistCentreHeight;
//                            Vector3 pointPositionB = (pointLoopPositionB) + lateral + twistCentreHeight;
//                            Handles.DrawLine(pointPositionA, pointPositionB);
//                        }
//
//                        break;

            case TrackBuildR.stuntModes.jumptwist:

                atPoint   = _track[selectedPoint];
                lastPoint = _track.GetPoint(selectedPoint - 1);
                nextPoint = _track.GetPoint(selectedPoint + 1);

                float trackTPartDistance = lastPoint.arcLength + atPoint.arcLength;
                float jumpTDistance      = Mathf.Min(trackTPartDistance * 0.333f, _track.maxJumpLength);

                trackWidth = atPoint.width * 0.5f;
                startCross = atPoint.trackCross;
                Vector3    jumpTDirection  = atPoint.trackDirection;
                Vector3    jumpTMiddle     = atPoint.worldPosition;
                Quaternion atPointUpQ      = atPoint.trackUpQ;
                Quaternion trackUpJump     = Quaternion.AngleAxis(_track.twistAngle, -jumpTDirection);
                Vector3    trackCrossExit  = trackUpJump * startCross;
                Vector3    trackCrossEntry = Quaternion.Inverse(trackUpJump) * startCross;
                Vector3    jumpLateral     = startCross * _track.twistAngle / 33.3f;

                Vector3 jumpTHeight        = atPointUpQ * (Vector3.forward * _track.jumpHeight);
                Vector3 jumpTStartPosition = jumpTMiddle - jumpTDirection * (jumpTDistance * 0.33f) + jumpTHeight - jumpLateral;
                Vector3 jumpTEndPosition   = jumpTMiddle + jumpTDirection * (jumpTDistance * 0.33f) + jumpTHeight + jumpLateral;

                p0 = lastPoint.worldPosition + trackWidth * startCross;
                p1 = lastPoint.worldPosition - trackWidth * startCross;
                p2 = jumpTStartPosition + trackWidth * trackCrossExit;
                p3 = jumpTStartPosition - trackWidth * trackCrossExit;

                p4 = jumpTEndPosition + trackWidth * trackCrossEntry;
                p5 = jumpTEndPosition - trackWidth * trackCrossEntry;
                p6 = nextPoint.worldPosition + trackWidth * startCross;
                p7 = nextPoint.worldPosition - trackWidth * startCross;

                Handles.DrawLine(p0, p2);
                Handles.DrawLine(p1, p3);
                Handles.DrawLine(p0, p1);
                Handles.DrawLine(p2, p3);
//                        Handles.DrawLine(p2, p2 - jumpTHeight);
//                        Handles.DrawLine(p3, p3 - jumpTHeight);
//                        Handles.DrawLine(p0, p2 - jumpTHeight);
//                        Handles.DrawLine(p1, p3 - jumpTHeight);

                Handles.DrawLine(p4, p6);
                Handles.DrawLine(p5, p7);
                Handles.DrawLine(p4, p5);
                Handles.DrawLine(p6, p7);
//                        Handles.DrawLine(p4, p4 - jumpTHeight);
//                        Handles.DrawLine(p5, p5 - jumpTHeight);
//                        Handles.DrawLine(p6, p4 - jumpTHeight);
//                        Handles.DrawLine(p7, p5 - jumpTHeight);

                break;
            }

            break;

        case TrackBuildR.modes.diagram:
            if (SceneView.focusedWindow != null)
            {
                SceneView.focusedWindow.wantsMouseMove = true;
            }
            if (!_track.showDiagram)
            {
                break;
            }
            Plane diagramPlane = new Plane(Vector3.up, position);
            float diagramDistance;
            float crossSize = _handleSize * 10;

            switch (_trackBuildR.track.assignedPoints)
            {
            case 0:        //display the diagram scale points

                Vector3 diagramPointA = _track.scalePointA;
                Vector3 diagramPointB = _track.scalePointB;

                if (diagramPointA != Vector3.zero || diagramPointB != Vector3.zero)
                {
                    Handles.color = TrackBuildRColours.BLUE;
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPointA, diagramPointA + Vector3.back * crossSize);

                    Handles.color = TrackBuildRColours.GREEN;
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPointB, diagramPointB + Vector3.back * crossSize);

                    Handles.color = TrackBuildRColours.RED;
                    Handles.DrawLine(diagramPointA, diagramPointB);
                }
                break;

            case 1:        //place the first of two scale points to define the diagram scale size

                Ray diagramRay = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (diagramPlane.Raycast(diagramRay, out diagramDistance))
                {
                    Vector3 diagramPlanePoint = diagramRay.GetPoint(diagramDistance);

                    Handles.color = TrackBuildRColours.BLUE;
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.back * crossSize);

                    Handles.color = new Color(0, 0, 0, 0);
                    if (Handles.Button(diagramPlanePoint, Quaternion.identity, crossSize, crossSize, Handles.DotCap))
                    {
                        _track.scalePointA    = diagramPlanePoint;
                        _track.assignedPoints = 2;
                    }
                }

                break;

            case 2:        //place the second of two scale points to define the diagram scale

                Vector3 diagramPoint1 = _track.scalePointA;
                Handles.color = TrackBuildRColours.BLUE;
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.left * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.right * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.forward * crossSize);
                Handles.DrawLine(diagramPoint1, diagramPoint1 + Vector3.back * crossSize);

                Ray diagramRayB = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));
                if (diagramPlane.Raycast(diagramRayB, out diagramDistance))
                {
                    Vector3 diagramPlanePoint = diagramRayB.GetPoint(diagramDistance);

                    Handles.color = TrackBuildRColours.RED;
                    Handles.DrawLine(diagramPlanePoint, diagramPoint1);

                    Handles.color = TrackBuildRColours.GREEN;
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.left * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.right * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.forward * crossSize);
                    Handles.DrawLine(diagramPlanePoint, diagramPlanePoint + Vector3.back * crossSize);

                    Handles.color = new Color(0, 0, 0, 0);
                    if (Handles.Button(diagramPlanePoint, Quaternion.identity, crossSize, crossSize, Handles.DotCap))
                    {
                        _track.scalePointB    = diagramPlanePoint;
                        _track.assignedPoints = 0;
                        //wUpdateDiagram();
                    }
                }
                break;
            }
            break;
        }


        if (Event.current.type == EventType.ValidateCommand)
        {
            switch (Event.current.commandName)
            {
            case "UndoRedoPerformed":
                //                    Debug.Log("UndoRedoPerformed");
                _trackBuildR.ForceFullRecalculation();
                GUI.changed = true;
                return;
            }
        }

        if (GUI.changed)
        {
            UpdateGui();
        }
    }
Beispiel #34
0
    public void UpdateRender()
    {
        if (track.numberOfCurves == 0)
        {
            return;
        }

        track.RecalculateCurves();
        float trackMeshRes = track.meshResolution;

        float bumperDistanceA = 0;
        float bumperDistanceB = 0;


        int   numberOfCurves = track.numberOfCurves;
        bool  renderTrack    = track.render;
        float UVOffset       = 0;
        int   polyCount      = 0;

        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = track[i];

            DynamicMeshGenericMultiMaterialMesh dynamicTrackMesh    = curve.dynamicTrackMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBoundaryMesh = curve.dynamicBoundaryMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicOffroadMesh  = curve.dynamicOffroadMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBumperMesh   = curve.dynamicBumperMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicColliderMesh = curve.dynamicColliderMesh;
            DynamicMeshGenericMultiMaterialMesh dynamicBottomMesh   = curve.dynamicBottomMesh;

            if (!curve.render || !renderTrack)
            {
                dynamicTrackMesh.Clear();
                dynamicBoundaryMesh.Clear();
                dynamicColliderMesh.Clear();
                dynamicOffroadMesh.Clear();
                dynamicBumperMesh.Clear();
                dynamicBottomMesh.Clear();
            }

            if (curve.shouldReRender && curve.render && renderTrack)
            {
                dynamicTrackMesh.Clear();
                dynamicTrackMesh.subMeshCount = 1;
                dynamicBoundaryMesh.Clear();
                dynamicBoundaryMesh.subMeshCount = 1;
                dynamicColliderMesh.Clear();
                dynamicColliderMesh.subMeshCount = 1;
                dynamicOffroadMesh.Clear();
                dynamicOffroadMesh.subMeshCount = 1;
                dynamicBumperMesh.Clear();
                dynamicBumperMesh.subMeshCount = 1;
                dynamicBottomMesh.Clear();
                dynamicBottomMesh.subMeshCount = 1;

                dynamicTrackMesh.name    = "curve " + i + " track mesh";
                dynamicBoundaryMesh.name = "curve " + i + " boundary mesh";
                dynamicColliderMesh.name = "curve " + i + " trackCollider mesh";
                dynamicOffroadMesh.name  = "curve " + i + " offroad mesh";
                dynamicBumperMesh.name   = "curve " + i + " bumper mesh";
                dynamicBottomMesh.name   = "curve " + i + " bottom mesh";

                bool trackTextureFlip    = (track.numberOfTextures > 0) ? track.Texture(curve.trackTextureStyleIndex).flipped : false;
                bool boundaryTextureFlip = (track.numberOfTextures > 0) ? track.Texture(curve.boundaryTextureStyleIndex).flipped : false;
                bool bumperTextureFlip   = (track.numberOfTextures > 0) ? track.Texture(curve.bumperTextureStyleIndex).flipped : false;
                bool bottomTextureFlip   = (track.numberOfTextures > 0) ? track.Texture(curve.bottomTextureStyleIndex).flipped : false;

                int   storedPointSize = curve.storedPointSize;
                float curveLength     = curve.arcLength;
                //Store these points so we can use previous values when Bezier clips itself
                Vector3 leftPointA  = curve.sampledLeftBoundaryPoints[0];
                Vector3 rightPointA = curve.sampledRightBoundaryPoints[0];
                Vector3 leftPointB  = curve.sampledLeftBoundaryPoints[0];
                Vector3 rightPointB = curve.sampledRightBoundaryPoints[0];
                for (int p = 0; p < storedPointSize - 1; p++)
                {
                    float   tA           = curve.normalisedT[p];
                    float   tB           = curve.normalisedT[p + 1];
                    int     sampleIndexA = p;
                    int     sampleIndexB = sampleIndexA + 1;
                    Vector3 pointA       = curve.sampledPoints[sampleIndexA];
                    Vector3 pointB       = curve.sampledPoints[sampleIndexB];
                    float   trackWidthA  = curve.sampledWidths[sampleIndexA] * 0.5f;
                    float   trackWidthB  = curve.sampledWidths[sampleIndexB] * 0.5f;
                    float   trackCrownA  = curve.sampledCrowns[sampleIndexA];
                    float   trackCrownB  = curve.sampledCrowns[sampleIndexB];
                    Vector3 trackUpA     = curve.sampledTrackUps[sampleIndexA];
                    Vector3 trackUpB     = curve.sampledTrackUps[sampleIndexB];
                    Vector3 trackCrossA  = curve.sampledTrackCrosses[sampleIndexA];
                    Vector3 trackCrossB  = curve.sampledTrackCrosses[sampleIndexB];
                    float   trackAngle   = curve.sampledAngles[sampleIndexA];

                    if (trackUpA == Vector3.zero || trackUpB == Vector3.zero)
                    {
                        return;
                    }

                    //TrackBuildRTexture texture = track.Texture(curve.trackTextureStyleIndex) ;// track.trackTexture;
                    int       pointANumber     = Mathf.Max(Mathf.CeilToInt(trackWidthA / trackMeshRes / 2) * 2, 2); //number of verts along line A
                    int       pointBNumber     = Mathf.Max(Mathf.CeilToInt(trackWidthB / trackMeshRes / 2) * 2, 2); //number of verts along line B
                    int       numberOfNewVerts = pointANumber + pointBNumber;
                    Vector3[] uncrownedVerts   = new Vector3[numberOfNewVerts];
                    if (curve.clipArrayLeft[sampleIndexA])
                    {
                        leftPointA = (pointA + (trackCrossA * -trackWidthA));
                    }
                    if (curve.clipArrayRight[sampleIndexA])
                    {
                        rightPointA = (pointA + (trackCrossA * trackWidthA));
                    }
                    float curveLengthA = (curveLength * tA) / trackWidthA + UVOffset;
                    float curveLengthB = (curveLength * tB) / trackWidthB + UVOffset;
                    float lerpASize    = 1.0f / (pointANumber - 1);

                    //track vertex/uv data for point nextNormIndex
                    Vector3[] newAPoints     = new Vector3[pointANumber];
                    Vector3[] newTrackPoints = new Vector3[pointANumber + pointBNumber];
                    Vector2[] newTrackUVs    = new Vector2[pointANumber + pointBNumber];
                    for (int pa = 0; pa < pointANumber; pa++)
                    {
                        float   lerpValue     = lerpASize * pa;
                        Vector3 crownVector   = Quaternion.LookRotation(trackUpA) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownA);
                        Vector3 uncrownedVert = Vector3.Lerp(leftPointA, rightPointA, lerpValue);
                        uncrownedVerts[pa] = uncrownedVert;
                        Vector3 newVert = uncrownedVert + crownVector;
                        newAPoints[pa]     = newVert;
                        newTrackPoints[pa] = newVert;
                        Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthA) : new Vector2(curveLengthA, lerpValue);
                        newTrackUVs[pa] = newUV;
                    }

                    //track vertex/uv data for point prevNormIndex
                    if (curve.clipArrayLeft[sampleIndexB])
                    {
                        leftPointB = (pointB + (trackCrossB * -trackWidthB));
                    }
                    if (curve.clipArrayRight[sampleIndexB])
                    {
                        rightPointB = (pointB + (trackCrossB * trackWidthB));
                    }
                    float     lerpBSize  = 1.0f / (pointBNumber - 1);
                    Vector3[] newBPoints = new Vector3[pointBNumber];
                    for (int pb = 0; pb < pointBNumber; pb++)
                    {
                        float   lerpValue     = lerpBSize * pb;
                        Vector3 crownVector   = Quaternion.LookRotation(trackUpB) * new Vector3(0, 0, Mathf.Sin(lerpValue * Mathf.PI) * trackCrownB);
                        Vector3 uncrownedVert = Vector3.Lerp(leftPointB, rightPointB, lerpValue);
                        uncrownedVerts[pb + pointANumber] = uncrownedVert;
                        Vector3 newVert = uncrownedVert + crownVector;
                        newBPoints[pb] = newVert;
                        newTrackPoints[pb + pointANumber] = newVert;
                        Vector2 newUV = (!trackTextureFlip) ? new Vector2(lerpValue, curveLengthB) : new Vector2(curveLengthB, lerpValue);
                        newTrackUVs[pb + pointANumber] = newUV;
                    }
                    int   baseTriPointA     = 0;
                    int   baseTriPointB     = pointANumber;
                    int   triPointA         = baseTriPointA;
                    int   triPointB         = baseTriPointB;
                    int   newTriPointCountA = 1;
                    int   newTriPointCountB = 1;
                    int[] newTrackTris      = new int[(numberOfNewVerts - 2) * 3];
                    for (int v = 0; v < numberOfNewVerts - 2; v++)
                    {
                        int newTriPointA = baseTriPointA + newTriPointCountA;
                        int newTriPointB = baseTriPointB + newTriPointCountB;

                        float newTriPointADist, newTriPointBDist;
                        if (newTriPointA >= baseTriPointA + pointANumber)
                        {
                            newTriPointADist = float.PositiveInfinity;
                        }
                        else
                        {
                            newTriPointADist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointA] - uncrownedVerts[baseTriPointA]);
                        }

                        if (newTriPointB >= baseTriPointB + pointBNumber)
                        {
                            newTriPointBDist = float.PositiveInfinity;
                        }
                        else
                        {
                            newTriPointBDist = Vector3.SqrMagnitude(uncrownedVerts[newTriPointB] - uncrownedVerts[baseTriPointB]);
                        }

                        if (newTriPointADist < newTriPointBDist)
                        {
                            newTrackTris[v * 3]     = triPointA;
                            newTrackTris[v * 3 + 1] = triPointB;
                            newTrackTris[v * 3 + 2] = newTriPointA;
                            triPointA = newTriPointA;
                            newTriPointCountA++;
                        }
                        else
                        {
                            newTrackTris[v * 3]     = triPointA;
                            newTrackTris[v * 3 + 1] = triPointB;
                            newTrackTris[v * 3 + 2] = newTriPointB;
                            triPointB = newTriPointB;
                            newTriPointCountB++;
                        }
                    }
                    dynamicTrackMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0);
                    dynamicColliderMesh.AddData(newTrackPoints, newTrackUVs, newTrackTris, 0);

                    //Boundary
                    float trackBoundaryWallHeight = curve.boundaryHeight;// track.boundaryHeight;

                    Vector3 leftBoundaryPointA, leftBoundaryPointB, rightBoundaryPointA, rightBoundaryPointB;
                    if (track.disconnectBoundary)
                    {
                        leftBoundaryPointA  = curve.sampledLeftBoundaryPoints[sampleIndexA];
                        leftBoundaryPointB  = curve.sampledLeftBoundaryPoints[sampleIndexB];
                        rightBoundaryPointA = curve.sampledRightBoundaryPoints[sampleIndexA];
                        rightBoundaryPointB = curve.sampledRightBoundaryPoints[sampleIndexB];
                    }
                    else
                    {
                        leftBoundaryPointA  = leftPointA;
                        leftBoundaryPointB  = leftPointB;
                        rightBoundaryPointA = rightPointA;
                        rightBoundaryPointB = rightPointB;
                    }

                    Vector3[] newWallVerts;
                    Vector2[] newWallUVs;
                    int[]     newWallTris;

                    //Boundary Render Mesh
                    if (curve.renderBounds)
                    {
                        //LEFT
                        newWallVerts = new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackBoundaryWallHeight, leftBoundaryPointB + trackUpB * trackBoundaryWallHeight };

                        if (!boundaryTextureFlip)
                        {
                            newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                        }
                        ;
                        else
                        {
                            newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                        };
                        newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                        //                    newWallTris = (boundaryTextureFlip) ? (new[] { 1, 0, 2, 1, 2, 3 }) : (new[] { 0,2,1,2,3,1 });
                        //                    newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 1, 0, 2, 1, 2, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 };
                        dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        if (track.renderBoundaryWallReverse)
                        {
                            newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                            //                        newWallTris = (boundaryTextureFlip) ? (new[] { 0, 1, 2, 2, 1, 3 }) : (new[] { 0, 2, 1, 2, 3, 1 });
                            dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //RIGHT
                        newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackBoundaryWallHeight, rightBoundaryPointB + trackUpB * trackBoundaryWallHeight });
                        //newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), };
                        if (!boundaryTextureFlip)
                        {
                            newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                        }
                        ;
                        else
                        {
                            newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                        };

                        newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                        //newWallTris = (!track.renderBoundaryWallReverse) ? new[] { 0, 1, 2, 2, 1, 3 } : new[] { 1, 0, 2, 1, 2, 3, 0, 1, 2, 2, 1, 3 };
                        dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        if (track.renderBoundaryWallReverse)
                        {
                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBoundaryMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }
                    }

                    if (curve.trackCollider)
                    {
                        //COLLIDER walls for on track border
                        float trackColliderWallHeight = track.trackColliderWallHeight;
                        if (curve.colliderSides)
                        {
                            newWallVerts = (new[] { leftBoundaryPointA, leftBoundaryPointB, leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            newWallVerts = (new[] { rightBoundaryPointA, rightBoundaryPointB, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //offroad bits
                        if (track.disconnectBoundary)
                        {
                            Vector2 offroadTextureSize = Vector2.one;
                            if (track.numberOfTextures > 0)
                            {
                                offroadTextureSize = track.Texture(curve.offroadTextureStyleIndex).textureUnitSize;// track.offroadTexture.textureUnitSize;
                            }
                            newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB });
                            newWallUVs   = (new[] { new Vector2(leftPointA.x / offroadTextureSize.x, leftPointA.z / offroadTextureSize.y), new Vector2(leftPointB.x / offroadTextureSize.x, leftPointB.z / offroadTextureSize.y), new Vector2(leftBoundaryPointA.x / offroadTextureSize.x, leftBoundaryPointA.z / offroadTextureSize.y), new Vector2(leftBoundaryPointB.x / offroadTextureSize.x, leftBoundaryPointB.z / offroadTextureSize.y) });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);

                            newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB });
                            newWallUVs   = (new[] { new Vector2(rightPointA.x / offroadTextureSize.x, rightPointA.z / offroadTextureSize.y), new Vector2(rightPointB.x / offroadTextureSize.x, rightPointB.z / offroadTextureSize.y), new Vector2(rightBoundaryPointA.x / offroadTextureSize.x, rightBoundaryPointA.z / offroadTextureSize.y), new Vector2(rightBoundaryPointB.x / offroadTextureSize.x, rightBoundaryPointB.z / offroadTextureSize.y) });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicOffroadMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);

                            newWallVerts = (new[] { leftPointA, leftPointB, leftBoundaryPointA, leftBoundaryPointB });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            newWallVerts = (new[] { rightPointA, rightPointB, rightBoundaryPointA, rightBoundaryPointB });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 0, 1, 2, 2, 1, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        if (track.includeColliderRoof)
                        {
                            newWallVerts = (new[] { leftBoundaryPointA + trackUpA * trackColliderWallHeight, leftBoundaryPointB + trackUpB * trackColliderWallHeight, rightBoundaryPointA + trackUpA * trackColliderWallHeight, rightBoundaryPointB + trackUpB * trackColliderWallHeight });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }
                    }

                    if ((track.trackBumpers && curve.generateBumpers) || curve.generateBumpers)
                    {
                        float   bumperWidth          = track.bumperWidth;
                        float   bumperHeight         = track.bumperHeight;
                        Vector3 bumperRaisedA        = trackUpA * bumperHeight;
                        Vector3 bumperRaisedB        = trackUpB * bumperHeight;
                        float   trackAngleThreashold = track.bumperAngleThresold;

                        //left bumpers
                        if (trackAngle >= trackAngleThreashold)
                        {
                            Vector3 offroadEdgeDirectionA = (leftBoundaryPointA - leftPointA).normalized;
                            Vector3 trackEdgeDirectionA   = (newAPoints[1] - newAPoints[0]).normalized;
                            Vector3 bumperDirectionA      = (Vector3.Project(offroadEdgeDirectionA, trackUpA) - trackEdgeDirectionA).normalized;
                            Vector3 offroadEdgeDirectionB = (leftBoundaryPointB - leftPointB).normalized;
                            Vector3 trackEdgeDirectionB   = (newBPoints[1] - newBPoints[0]).normalized;
                            Vector3 bumperDirectionB      = (Vector3.Project(offroadEdgeDirectionB, trackUpB) - trackEdgeDirectionB).normalized;
                            float   trackEdgeA            = Vector3.Distance(pointA, leftPointA);
                            float   offroadEdgeA          = Vector3.Distance(pointA, leftBoundaryPointA);
                            bool    offroadBumper         = (trackEdgeA < (offroadEdgeA - bumperWidth));
                            Vector3 bumperLeft0           = (offroadBumper ? leftPointA + bumperDirectionA * bumperWidth : leftBoundaryPointA) + bumperRaisedA;
                            Vector3 bumperLeft1           = (offroadBumper ? leftPointA : bumperLeft0 - (bumperDirectionA * bumperWidth) - bumperRaisedB);//bumperLeft0 + (trackEdgeDirectionA * bumperWidth)) - bumperRaisedB;

                            Vector3 bumperLeft2 = (offroadBumper ? leftPointB + bumperDirectionB * bumperWidth : leftBoundaryPointB) + bumperRaisedB;
                            Vector3 bumperLeft3 = (offroadBumper ? leftPointB : bumperLeft2 - (bumperDirectionB * bumperWidth) - bumperRaisedB);

                            float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2);
                            float uvStartA, uvEndA;
                            if (track.numberOfTextures > 0)
                            {
                                uvStartA = bumperDistanceA / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndA   = (bumperDistanceA + bumperSegmentDistanceA) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y;
                            }
                            else
                            {
                                uvStartA = bumperDistanceA;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndA   = (bumperDistanceA + bumperSegmentDistanceA); // track.bumperTexture.textureUnitSize.y;
                            }
                            newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 });
                            if (!bumperTextureFlip)
                            {
                                newWallUVs = (new[] { new Vector2(uvStartA, 1), new Vector2(uvStartA, 0), new Vector2(uvEndA, 1), new Vector2(uvEndA, 0) });
                            }
                            else
                            {
                                newWallUVs = (new[] { new Vector2(1, uvStartA), new Vector2(0, uvStartA), new Vector2(1, uvEndA), new Vector2(0, uvEndA) });
                            }
                            newWallTris = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            bumperDistanceA += bumperSegmentDistanceA;

                            newWallVerts = (new[] { bumperLeft0, bumperLeft1, bumperLeft2, bumperLeft3 });
                            newWallUVs   = (new[] { Vector2.zero, Vector2.zero, Vector2.zero, Vector2.zero });
                            newWallTris  = (new[] { 1, 0, 2, 1, 2, 3 });
                            dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                        }

                        //Right bumpers
                        if (trackAngle < -trackAngleThreashold)
                        {
                            Vector3 trackEdgeDirectionA = (newAPoints[pointANumber - 2] - newAPoints[pointANumber - 1]).normalized;
                            Vector3 trackEdgeDirectionB = (newBPoints[pointBNumber - 2] - newBPoints[pointBNumber - 1]).normalized;

                            Vector3 bumperRight0 = ((Vector3.Distance(pointA, rightPointA) < (Vector3.Distance(pointA, rightBoundaryPointA) - bumperWidth)) ? rightPointA : rightBoundaryPointA) + bumperRaisedA;
                            Vector3 bumperRight1 = bumperRight0 + (trackEdgeDirectionA * bumperWidth);

                            Vector3 bumperRight2 = ((Vector3.Distance(pointB, rightPointB) < (Vector3.Distance(pointB, rightBoundaryPointB) - bumperWidth)) ? rightPointB : rightBoundaryPointB) + bumperRaisedB;
                            Vector3 bumperRight3 = bumperRight2 + (trackEdgeDirectionB * bumperWidth);

                            float bumperSegmentDistanceB = Vector3.Distance(bumperRight0, bumperRight2);
                            //float bumperSegmentDistanceA = Vector3.Distance(bumperLeft0, bumperLeft2);

                            float uvStartB, uvEndB;
                            if (track.numberOfTextures > 0)
                            {
                                uvStartB = bumperDistanceB / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y;                            // track.bumperTexture.textureUnitSize.y;
                                uvEndB   = (bumperDistanceB + bumperSegmentDistanceB) / track.Texture(curve.bumperTextureStyleIndex).textureUnitSize.y; // track.bumperTexture.textureUnitSize.y;
                            }
                            else
                            {
                                uvStartB = bumperDistanceB;
                                uvEndB   = (bumperDistanceB + bumperSegmentDistanceB);
                            }
                            newWallVerts = (new[] { bumperRight0, bumperRight1, bumperRight2, bumperRight3 });
                            if (!bumperTextureFlip)
                            {
                                newWallUVs = (new[] { new Vector2(uvStartB, 1), new Vector2(uvStartB, 0), new Vector2(uvEndB, 1), new Vector2(uvEndB, 0) });
                            }
                            else
                            {
                                newWallUVs = (new[] { new Vector2(1, uvStartB), new Vector2(0, uvStartB), new Vector2(1, uvEndB), new Vector2(0, uvEndB) });
                            }
//                            newWallTris = (new[] { 1, 0, 2, 1, 2, 3 });
                            newWallTris = (new[] { 0, 1, 2, 1, 3, 2 });
                            dynamicBumperMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            bumperDistanceB += bumperSegmentDistanceB;
                        }
                    }


                    //Track Bottom Mesh
                    if (curve.extrudeTrack || curve.extrudeTrackBottom)
                    {
                        float   extrusionLength = curve.extrudeLength;
                        Vector3 extrusionA      = -trackUpA * extrusionLength;
                        Vector3 extrusionB      = -trackUpB * extrusionLength;
                        Vector3 pl0             = leftBoundaryPointA;
                        Vector3 pl1             = leftBoundaryPointB;
                        Vector3 pl2             = leftBoundaryPointA + extrusionA;
                        Vector3 pl3             = leftBoundaryPointB + extrusionB;
                        Vector3 pr0             = rightBoundaryPointA;
                        Vector3 pr1             = rightBoundaryPointB;
                        Vector3 pr2             = rightBoundaryPointA + extrusionA;
                        Vector3 pr3             = rightBoundaryPointB + extrusionB;

                        float   bevelLerp = 0.5f - curve.extrudeBevel * 0.3333f;
                        Vector3 bevelOutA = trackCrossA.normalized * (trackWidthA * 0.5f);
                        Vector3 bevelOutB = trackCrossB.normalized * (trackWidthB * 0.5f);
                        Vector3 pl2b      = Vector3.Lerp(pl2 - bevelOutA, pr2 + bevelOutA, bevelLerp);
                        Vector3 pl3b      = Vector3.Lerp(pl3 - bevelOutB, pr3 + bevelOutB, bevelLerp);
                        Vector3 pr2b      = Vector3.Lerp(pr2 + bevelOutA, pl2 - bevelOutA, bevelLerp);
                        Vector3 pr3b      = Vector3.Lerp(pr3 + bevelOutB, pl3 - bevelOutB, bevelLerp);

                        if (curve.extrudeTrack)
                        {
                            //LEFT

                            newWallVerts = new[] { pl0, pl1, pl2b, pl3b };

                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };
                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }

                            //RIGHT
                            newWallVerts = (new[] { pr0, pr1, pr2b, pr3b });
                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };

                            newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }

                            if (curve.extrudeCurveEnd)
                            {
                                //Ends
                                if (p == 0)
                                {
                                    newWallVerts = (new[] { pl0, pl2b, pr0, pr2b });
                                    if (!bottomTextureFlip)
                                    {
                                        newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                                    }
                                    ;
                                    else
                                    {
                                        newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                                    };
                                    newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                                    dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    if (curve.trackCollider)
                                    {
                                        dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    }
                                }
                                if (p == storedPointSize - 2)
                                {
                                    newWallVerts = (new[] { pl1, pl3b, pr1, pr3b });
                                    if (!bottomTextureFlip)
                                    {
                                        newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                                    }
                                    ;
                                    else
                                    {
                                        newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                                    };
                                    newWallTris = new[] { 0, 1, 2, 2, 1, 3 };
                                    dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    if (curve.trackCollider)
                                    {
                                        dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                                    }
                                }
                            }
                        }

                        if (curve.extrudeTrackBottom)
                        {
                            if (!curve.extrudeTrack)
                            {
                                newWallVerts = new[] { pl0, pl1, pr0, pr1 }
                            }
                            ;
                            else
                            {
                                newWallVerts = new[] { pl2b, pl3b, pr2b, pr3b }
                            };

                            if (!bottomTextureFlip)
                            {
                                newWallUVs = new[] { new Vector2(curveLengthA, 0), new Vector2(curveLengthB, 0), new Vector2(curveLengthA, 1), new Vector2(curveLengthB, 1), }
                            }
                            ;
                            else
                            {
                                newWallUVs = new[] { new Vector2(1, curveLengthA), new Vector2(1, curveLengthB), new Vector2(0, curveLengthA), new Vector2(0, curveLengthB), }
                            };

                            newWallTris = new[] { 1, 0, 2, 1, 2, 3 };
                            dynamicBottomMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            if (curve.trackCollider)
                            {
                                dynamicColliderMesh.AddData(newWallVerts, newWallUVs, newWallTris, 0);
                            }
                        }
                    }

                    if (p == storedPointSize - 2)
                    {
                        UVOffset = curveLengthB;
                    }
                }

                if (curve.holder != null)
                {
                    DestroyImmediate(curve.holder);
                }

                GameObject newCurveMeshHolder = new GameObject("curve " + (i + 1));
                newCurveMeshHolder.transform.parent        = transform;
                newCurveMeshHolder.transform.localPosition = Vector3.zero;
                curve.holder = newCurveMeshHolder;
                int numberOfMeshes;
                if (!dynamicTrackMesh.isEmpty)
                {
                    dynamicTrackMesh.name = "Curve " + i + " Track Mesh";
                    dynamicTrackMesh.Build();
                    numberOfMeshes = dynamicTrackMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("model " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicTrackMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.trackTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }


                if (!dynamicBoundaryMesh.isEmpty)
                {
                    dynamicBoundaryMesh.Build();
                    numberOfMeshes = dynamicBoundaryMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("boundary " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBoundaryMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.boundaryTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (track.disconnectBoundary && !dynamicOffroadMesh.isEmpty)
                {
                    dynamicOffroadMesh.Build();
                    numberOfMeshes = dynamicOffroadMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("offroad " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicOffroadMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.offroadTextureStyleIndex).GetMaterial();// track.offroadTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (track.includeCollider && curve.trackCollider && !dynamicColliderMesh.isEmpty)
                {
                    dynamicColliderMesh.Build();
                    int numberOfColliderMeshes = dynamicColliderMesh.meshCount;
                    for (int m = 0; m < numberOfColliderMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("trackCollider " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshCollider>().sharedMesh = dynamicColliderMesh[m].mesh;
                    }
                }

                if (track.trackBumpers && !dynamicBumperMesh.isEmpty)
                {
                    dynamicBumperMesh.Build();
                    numberOfMeshes = dynamicBumperMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("bumper " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBumperMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bumperTextureStyleIndex).GetMaterial();// track.bumperTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }

                if (!dynamicBottomMesh.isEmpty)
                {
                    dynamicBottomMesh.Build();
                    numberOfMeshes = dynamicBottomMesh.meshCount;
                    for (int m = 0; m < numberOfMeshes; m++)
                    {
                        GameObject newMeshHolder = new GameObject("bottom " + (m + 1));
                        newMeshHolder.transform.parent        = curve.holder.transform;
                        newMeshHolder.transform.localPosition = Vector3.zero;
                        newMeshHolder.AddComponent <MeshFilter>().sharedMesh = dynamicBottomMesh[m].mesh;
                        if (track.numberOfTextures > 0)
                        {
                            newMeshHolder.AddComponent <MeshRenderer>().material = track.Texture(curve.bottomTextureStyleIndex).GetMaterial();// track.trackTexture.material;
                        }
#if UNITY_EDITOR
                        EditorUtility.SetSelectedWireframeHidden(newMeshHolder.renderer, !track.showWireframe);
#endif
                    }
                }
            }
            else
            {
                if (curve.holder != null && (!curve.render || !renderTrack))
                {
                    DestroyImmediate(curve.holder);
                }
            }

            polyCount += dynamicBottomMesh.triangleCount / 3;
            polyCount += dynamicBoundaryMesh.triangleCount / 3;
            polyCount += dynamicBumperMesh.triangleCount / 3;
            polyCount += dynamicOffroadMesh.triangleCount / 3;
            polyCount += dynamicTrackMesh.triangleCount / 3;
        }

        track.TrackRendered();

        track.lastPolycount = polyCount;

#if UNITY_EDITOR
        EditorUtility.UnloadUnusedAssets();
#endif
    }
    private void SceneGUIPointBased()
    {
        Vector3 position    = _trackBuildR.transform.position;
        Camera  sceneCamera = Camera.current;

        _handleSize = HandleUtility.GetHandleSize(_trackBuildR.transform.position) * 0.1f;
        int realNumberOfPoints = _track.realNumberOfPoints;
        Ray mouseRay           = Camera.current.ScreenPointToRay(new Vector3(Event.current.mousePosition.x, Screen.height - Event.current.mousePosition.y - 30, 0));

        for (int i = 0; i < realNumberOfPoints; i++)
        {
            TrackBuildRPoint point = _track[i];
            if (Vector3.Dot(sceneCamera.transform.forward, point.worldPosition - sceneCamera.transform.position) < 0)
            {
                continue;
            }

            Handles.Label(point.worldPosition, "point " + (i + 1));
            float pointHandleSize = HandleUtility.GetHandleSize(point.worldPosition) * HANDLE_SCALE;
            Handles.color = (i == selectedPoint) ? TrackBuildRColours.RED : TrackBuildRColours.GREEN;
            if (Handles.Button(point.worldPosition, Quaternion.identity, pointHandleSize, pointHandleSize, Handles.DotCap))
            {
                selectedPoint              = i;
                GUIUtility.hotControl      = 0;
                GUIUtility.keyboardControl = 0;
                GUI.changed   = true;
                point.isDirty = true;
            }

            if (i == selectedPoint)
            {
                switch (_trackBuildR.mode)
                {
                case TrackBuildR.modes.track:

                    switch (_trackBuildR.pointMode)
                    {
                    case TrackBuildR.pointModes.transform:
                        Vector3 currentPosition = point.worldPosition;
                        currentPosition = Handles.DoPositionHandle(currentPosition, Quaternion.identity);
                        if (currentPosition != point.worldPosition)
                        {
                            Undo.RecordObject(point, "Point Changed");
                            point.isDirty       = true;
                            point.worldPosition = currentPosition;
                        }

                        //greyed out control points for user ease
                        Handles.color = TrackBuildRColours.DARK_GREY;
                        Handles.DrawLine(point.worldPosition, point.forwardControlPoint + position);
                        Handles.DrawLine(point.worldPosition, point.backwardControlPoint + position);
                        if (Handles.Button(point.backwardControlPoint + position, Quaternion.identity, pointHandleSize, pointHandleSize, Handles.DotCap))
                        {
                            _trackBuildR.pointMode = TrackBuildR.pointModes.controlpoint;
                        }
                        if (Handles.Button(point.forwardControlPoint + position, Quaternion.identity, pointHandleSize, pointHandleSize, Handles.DotCap))
                        {
                            _trackBuildR.pointMode = TrackBuildR.pointModes.controlpoint;
                        }
                        break;

                    case TrackBuildR.pointModes.controlpoint:
                        //render reverse first so forward renders on top
                        Handles.DrawLine(point.worldPosition, point.backwardControlPoint + position);
                        point.backwardControlPoint = Handles.DoPositionHandle(point.backwardControlPoint + position, Quaternion.identity) - position;
                        if (Vector3.Dot(mouseRay.direction, point.worldPosition - mouseRay.origin) > 0)
                        {
                            Handles.Label(point.backwardControlPoint, "point " + (i + 1) + " reverse control point");
                        }

                        if (Vector3.Dot(mouseRay.direction, point.worldPosition - mouseRay.origin) > 0)
                        {
                            Handles.Label(point.forwardControlPoint, "point " + (i + 1) + " control point");
                        }
                        Handles.color = TrackBuildRColours.RED;
                        Handles.DrawLine(point.worldPosition, point.forwardControlPoint + position);
                        point.forwardControlPoint = Handles.DoPositionHandle(point.forwardControlPoint + position, Quaternion.identity) - position;

                        break;

                    case TrackBuildR.pointModes.trackup:

                        Undo.RecordObject(point, "Point Changed");
                        point.trackUpQ = Handles.RotationHandle(point.trackUpQ, point.worldPosition);

                        Handles.color = TrackBuildRColours.BLUE;
                        Handles.ArrowCap(0, point.worldPosition, point.trackUpQ, pointHandleSize * 10);
                        Handles.Label(point.worldPosition + point.trackUpQ * Vector3.forward * pointHandleSize * 15, "Up Vector");
                        Handles.color = TrackBuildRColours.GREEN;
                        Handles.ArrowCap(0, point.worldPosition, Quaternion.LookRotation(point.trackDirection), pointHandleSize * 10);
                        Handles.Label(point.worldPosition + point.trackDirection * pointHandleSize * 15, "Direction Vector");

                        Handles.color = TrackBuildRColours.RED;
                        Quaternion quatForward = Quaternion.LookRotation(point.trackUpQ * Vector3.up);
                        Handles.ArrowCap(0, point.worldPosition, quatForward, pointHandleSize * 10);
                        Handles.Label(point.worldPosition + Quaternion.LookRotation(point.trackUpQ * Vector3.up) * Vector3.forward * pointHandleSize * 15, "Up Forward Vector");

                        Handles.color = TrackBuildRColours.PURPLE;
                        Quaternion quatCross = Quaternion.LookRotation(point.trackCross);
                        Handles.ArrowCap(0, point.worldPosition, quatCross, pointHandleSize * 10);
                        Handles.Label(point.worldPosition + point.trackCross * pointHandleSize * 15, "Cross Vector");
                        break;

                    case TrackBuildR.pointModes.trackpoint:

                        //Track Width
                        Handles.color = TrackBuildRColours.RED;
                        float   pointWidth = point.width / 2;
                        Vector3 sliderPos  = Handles.Slider(point.worldPosition + point.trackCross * pointWidth, point.trackCross);
                        float   pointwidth = Vector3.Distance(sliderPos, point.worldPosition) * 2;
                        if (pointwidth != point.width)
                        {
                            Undo.RecordObject(point, "Point Changed");
                            point.isDirty = true;
                            point.width   = pointwidth;
                        }

                        //Crown
                        Handles.color = TrackBuildRColours.GREEN;
                        Vector3 crownPosition    = point.worldPosition + point.trackUp * point.crownAngle;
                        Vector3 newCrownPosition = Handles.Slider(crownPosition, point.trackUp);
                        Vector3 crownDifference  = newCrownPosition - point.worldPosition;
                        if (crownDifference.sqrMagnitude != 0)        //Crown Modified
                        {
                            Undo.RecordObject(point, "Point Changed");
                            point.isDirty    = true;
                            point.crownAngle = Vector3.Project(crownDifference, point.trackUp).magnitude *Mathf.Sign(Vector3.Dot(crownDifference, point.trackUp));
                        }

                        break;
                    }
                    break;


                case TrackBuildR.modes.boundary:

                    if (_track.disconnectBoundary)
                    {
                        if (Vector3.Dot(mouseRay.direction, point.worldPosition - mouseRay.origin) > 0)
                        {
                            Handles.color = TrackBuildRColours.RED;
                            Handles.Label(point.leftTrackBoundaryWorld, "point " + (i + 1) + " left track boundary");
                            Handles.Label(point.rightTrackBoundaryWorld, "point " + (i + 1) + " right track boundary");
                            Handles.DrawLine(point.worldPosition, point.leftTrackBoundaryWorld);
                            Handles.DrawLine(point.worldPosition, point.rightTrackBoundaryWorld);
                        }
                        switch (_trackBuildR.boundaryMode)
                        {
                        case TrackBuildR.boundaryModes.transform:
                            Undo.RecordObject(point, "Point Changed");
                            point.leftTrackBoundaryWorld  = Handles.DoPositionHandle(point.leftTrackBoundaryWorld, Quaternion.identity);
                            point.rightTrackBoundaryWorld = Handles.DoPositionHandle(point.rightTrackBoundaryWorld, Quaternion.identity);
                            break;

                        case TrackBuildR.boundaryModes.controlpoint:
                            Undo.RecordObject(point, "Point Changed");
                            Handles.color = TrackBuildRColours.RED;
                            Handles.DrawLine(point.leftTrackBoundaryWorld, point.leftForwardControlPoint + position);
                            point.leftForwardControlPoint = Handles.DoPositionHandle(point.leftForwardControlPoint + position, Quaternion.identity) - position;

                            Handles.DrawLine(point.leftTrackBoundaryWorld, point.leftBackwardControlPoint + position);
                            point.leftBackwardControlPoint = Handles.DoPositionHandle(point.leftBackwardControlPoint + position, Quaternion.identity) - position;

                            Handles.DrawLine(point.rightTrackBoundaryWorld, point.rightForwardControlPoint + position);
                            point.rightForwardControlPoint = Handles.DoPositionHandle(point.rightForwardControlPoint + position, Quaternion.identity) - position;

                            Handles.DrawLine(point.rightTrackBoundaryWorld, point.rightBackwardControlPoint + position);
                            point.rightBackwardControlPoint = Handles.DoPositionHandle(point.rightBackwardControlPoint + position, Quaternion.identity) - position;
                            break;
                        }
                    }
                    break;

                case TrackBuildR.modes.stunt:

                    break;
                }
            }
        }
    }
Beispiel #36
0
    public static void MergeTerrain(TrackBuildRTrack track, Terrain terrain)
    {
        TerrainData terrainData        = terrain.terrainData;
        int         terrainWidth       = terrainData.heightmapWidth;
        int         terrainHeight      = terrainData.heightmapHeight;
        float       terrainHeightmapY  = terrain.terrainData.heightmapScale.y;
        float       terrainY           = terrain.transform.position.y / terrainHeightmapY;
        Vector3     meshScale          = terrainData.heightmapScale;
        float       terrainAccuracy    = track.terrainAccuracy;
        float       terrainMergeMargin = track.terrainMergeMargin;

        float[,] originalData    = terrainData.GetHeights(0, 0, terrainWidth, terrainHeight);
        float[,] mergeData       = new float[terrainWidth, terrainHeight];
        float[,] modifiedData    = new float[terrainWidth, terrainHeight];
        int[,] modifiedPointLock = new int[terrainWidth, terrainHeight];

        Bounds trackBounds    = new Bounds();
        int    numberOfCurves = track.numberOfCurves;

        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = track[i];
            if (curve.holder == null)
            {
                continue;
            }
            Renderer[] rends = curve.holder.GetComponentsInChildren <Renderer>();
            foreach (Renderer rend in rends)
            {
                trackBounds.Encapsulate(rend.bounds);
            }
        }

        Vector3 trackOffset = track.transform.position - terrain.transform.position;
        Vector3 trackScale  = new Vector3(trackBounds.size.x / terrainData.size.x, 1.0f / terrain.terrainData.size.y, trackBounds.size.z / terrainData.size.z);

        float          mergeWidth   = track.terrainMergeWidth;
        AnimationCurve mergeCurve   = track.mergeCurve;
        float          minScaleUnit = Mathf.Min(meshScale.x, meshScale.z);

        for (int i = 0; i < numberOfCurves; i++)
        {
            TrackBuildRPoint curve = track[i];
            int storedPointSize    = curve.storedPointSize;
            for (int p = 0; p < storedPointSize - 1; p++)
            {
                Vector3 pointA = curve.sampledPoints[p];
                Vector3 pointB = curve.sampledPoints[p + 1];
                Vector3 crossA = curve.sampledTrackCrosses[p];
                Vector3 crossB = curve.sampledTrackCrosses[p + 1];
                float   widthA = curve.sampledWidths[p] * terrainMergeMargin;
                float   widthB = curve.sampledWidths[p + 1] * terrainMergeMargin;
//                float heightA = (pointA.y - terrainAccuracy) * trackScale.y - terrainY;
//                float heightB = (pointB.y - terrainAccuracy) * trackScale.y - terrainY;

                Vector3 lpointA = (pointA - crossA * (widthA + mergeWidth));
                Vector3 rpointA = (pointA + crossA * (widthA + mergeWidth));
                Vector3 lpointB = (pointB - crossB * (widthB + mergeWidth));
                Vector3 rpointB = (pointB + crossB * (widthB + mergeWidth));

                float crownA = curve.sampledCrowns[p] - terrainAccuracy;
                float crownB = curve.sampledCrowns[p + 1] - terrainAccuracy;

                float pointDistanceLeft   = Vector3.Distance(lpointA, lpointB) * 1.8f;
                float pointDistanceRight  = Vector3.Distance(rpointA, rpointB) * 1.8f;
                float pointDistance       = Mathf.Max(pointDistanceLeft, pointDistanceRight);
                float pointFillResolution = minScaleUnit / pointDistance * 0.125f;

                float heightLA = (lpointA.y - terrainAccuracy) * trackScale.y - terrainY;
                float heightRA = (rpointA.y - terrainAccuracy) * trackScale.y - terrainY;
                float heightLB = (lpointB.y - terrainAccuracy) * trackScale.y - terrainY;
                float heightRB = (rpointB.y - terrainAccuracy) * trackScale.y - terrainY;

                for (float pf = 0; pf < 1; pf += pointFillResolution)//point a to point b
                {
                    //Track Filler
                    Vector3 fillPoint        = Vector3.Lerp(pointA, pointB, pf);
                    Vector3 fillCross        = Vector3.Lerp(crossA, crossB, pf);
                    float   fillWidth        = Mathf.Lerp(widthA, widthB, pf); // *1.2f;
                    float   fillCrown        = Mathf.Lerp(crownA, crownB, pf); // *1.2f;
                    float   fillTrackHeightL = Mathf.Lerp(heightLA, heightLB, pf);
                    float   fillTrackHeightR = Mathf.Lerp(heightRA, heightRB, pf);

                    Vector3 leftTrackPoint  = fillPoint - fillCross * fillWidth;
                    Vector3 rightTrackPoint = fillPoint + fillCross * fillWidth;

                    int leftX  = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int leftY  = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                    int rightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int rightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

                    int diffX = leftX - rightX;
                    int diffY = leftY - rightY;
                    int trackCrossFillAmount = Mathf.Max(Mathf.Abs(diffX), 1) * Mathf.Max(Mathf.Abs(diffY), 1);
                    for (int f = 0; f < trackCrossFillAmount; f++)//left to right
                    {
                        float move  = f / (float)trackCrossFillAmount;
                        int   fillX = Mathf.RoundToInt(Mathf.Lerp(leftX, rightX, move));
                        int   fillY = Mathf.RoundToInt(Mathf.Lerp(leftY, rightY, move));
                        if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight)
                        {
                            continue;
                        }
                        float crownHeight      = Mathf.Sin(move * Mathf.PI) * fillCrown / terrainHeightmapY;
                        float fillTrackHeight  = Mathf.Lerp(fillTrackHeightL, fillTrackHeightR, move) + crownHeight;
                        int   currentPointLock = modifiedPointLock[fillY, fillX];
                        if (currentPointLock == 0 || mergeData[fillY, fillX] > fillTrackHeight)
                        {
                            mergeData[fillY, fillX] = fillTrackHeight;
                        }
                        modifiedPointLock[fillY, fillX] = 1;//point lock
                    }

                    //Merge
                    Vector3 leftMergePoint = leftTrackPoint - fillCross * mergeWidth;

                    int leftMergeLeftX  = Mathf.RoundToInt(((leftMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int leftMergeLeftY  = Mathf.RoundToInt(((leftMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                    int leftMergeRightX = Mathf.RoundToInt(((leftTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int leftMergeRightY = Mathf.RoundToInt(((leftTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
//
                    int leftMergeDiffX      = leftMergeLeftX - leftMergeRightX;
                    int leftMergeDiffY      = leftMergeLeftY - leftMergeRightY;
                    int leftMergeFillAmount = Mathf.Max(Mathf.Abs(leftMergeDiffX), 1) * Mathf.Max(Mathf.Abs(leftMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY));
                    for (int f = 0; f < leftMergeFillAmount; f++)
                    {
                        float move  = f / (float)leftMergeFillAmount;
                        int   fillX = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftX, leftMergeRightX, move));
                        int   fillY = Mathf.RoundToInt(Mathf.Lerp(leftMergeLeftY, leftMergeRightY, move));
                        if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight)
                        {
                            continue;
                        }
                        float curveStrength      = mergeCurve.Evaluate(move);
                        float fillTrackHeight    = fillTrackHeightL;
                        float mergeHeight        = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength);
                        int   pointLock          = modifiedPointLock[fillY, fillX];
                        float currentMergeHeight = mergeData[fillY, fillX];
                        float currentDifference  = Mathf.Abs(currentMergeHeight - fillTrackHeight);
                        float newDifference      = Mathf.Abs(mergeHeight - fillTrackHeight);
                        if (newDifference < currentDifference && pointLock == 0)
                        {
                            mergeData[fillY, fillX] = mergeHeight;
                        }
                    }

                    Vector3 rightMergePoint  = rightTrackPoint + fillCross * mergeWidth;
                    int     rightMergeLeftX  = Mathf.RoundToInt(((rightMergePoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int     rightMergeLeftY  = Mathf.RoundToInt(((rightMergePoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);
                    int     rightMergeRightX = Mathf.RoundToInt(((rightTrackPoint.x + trackOffset.x) / trackBounds.size.x * trackScale.x) * terrainData.heightmapWidth);
                    int     rightMergeRightY = Mathf.RoundToInt(((rightTrackPoint.z + trackOffset.z) / trackBounds.size.z * trackScale.z) * terrainData.heightmapHeight);

                    //
                    int rightMergeDiffX      = rightMergeLeftX - rightMergeRightX;
                    int rightMergeDiffY      = rightMergeLeftY - rightMergeRightY;
                    int rightMergeFillAmount = Mathf.Max(Mathf.Abs(rightMergeDiffX), 1) * Mathf.Max(Mathf.Abs(rightMergeDiffY), 1);// Mathf.Max(Mathf.Abs(leftMergeDiffX), Mathf.Abs(leftMergeDiffY));
                    for (int f = 0; f < rightMergeFillAmount; f++)
                    {
                        float move  = f / (float)rightMergeFillAmount;
                        int   fillX = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftX, rightMergeRightX, move));
                        int   fillY = Mathf.RoundToInt(Mathf.Lerp(rightMergeLeftY, rightMergeRightY, move));
                        if (fillX < 0 || fillY < 0 || fillX >= terrainWidth || fillY >= terrainHeight)
                        {
                            continue;
                        }
                        float curveStrength      = mergeCurve.Evaluate(move);
                        float fillTrackHeight    = fillTrackHeightR;
                        float mergeHeight        = Mathf.Lerp(originalData[fillY, fillX], fillTrackHeight, curveStrength);
                        int   pointLock          = modifiedPointLock[fillY, fillX];
                        float currentMergeHeight = mergeData[fillY, fillX];
                        float currentDifference  = Mathf.Abs(currentMergeHeight - fillTrackHeight);
                        float newDifference      = Mathf.Abs(mergeHeight - fillTrackHeight);
                        if (newDifference < currentDifference && pointLock == 0)
                        {
                            mergeData[fillY, fillX] = mergeHeight;
                        }
                    }
                }
            }
        }

        for (int x = 0; x < terrainWidth; x++)
        {
            for (int y = 0; y < terrainHeight; y++)
            {
                bool isNotEdge = x > 0 && x < terrainWidth - 1 && y > 0 && y < terrainHeight - 1;
                if (mergeData[x, y] == 0)
                {
                    int mergeNeighbours = 0;
                    if (isNotEdge)
                    {
                        mergeNeighbours += (mergeData[x + 1, y] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x - 1, y] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x, y + 1] != 0) ? 1 : 0;
                        mergeNeighbours += (mergeData[x, y - 1] != 0) ? 1 : 0;
                    }
                    if (mergeNeighbours > 1)//if a hole is surounded by rasied terrain in two or more neighbouring places
                    {
                        float mergeHeight = 0;
                        mergeHeight       += (mergeData[x + 1, y] != 0) ? mergeData[x + 1, y] : 0;
                        mergeHeight       += (mergeData[x - 1, y] != 0) ? mergeData[x - 1, y] : 0;
                        mergeHeight       += (mergeData[x, y + 1] != 0) ? mergeData[x, y + 1] : 0;
                        mergeHeight       += (mergeData[x, y - 1] != 0) ? mergeData[x, y - 1] : 0;
                        modifiedData[x, y] = mergeHeight / mergeNeighbours;//clean up holes
                    }
                    else
                    {
                        modifiedData[x, y] = originalData[x, y];//use original
                    }
                }
                else
                {
                    modifiedData[x, y] = mergeData[x, y];
                }
            }
        }

        terrainData.SetHeights(0, 0, modifiedData);
        terrain.terrainData = terrainData;
    }
Beispiel #37
0
    public virtual void FromXML(XmlNode node)
    {
        XmlNodeList textureNodes = node.SelectNodes("textures/texture");

        foreach (XmlNode textureNode in textureNodes)
        {
            TrackBuildRTexture newTexture = gameObject.AddComponent <TrackBuildRTexture>();
            newTexture.FromXML(textureNode);
            _textures.Add(newTexture);
        }

        XmlNodeList trackPointNodes = node.SelectNodes("trackpoints/trackpoint");

        foreach (XmlNode trackPointNode in trackPointNodes)
        {
            TrackBuildRPoint point = gameObject.AddComponent <TrackBuildRPoint>();
            point.FromXML(trackPointNode);
            point.baseTransform = baseTransform;
            point.isDirty       = true;
            _points.Add(point);
        }

        if (node["meshResolution"] != null)
        {
            _meshResolution = float.Parse(node["meshResolution"].FirstChild.Value);
        }
        if (node["includeCollider"] != null)
        {
            includeCollider = bool.Parse(node["includeCollider"].FirstChild.Value);
        }
        if (node["includeColliderRoof"] != null)
        {
            includeColliderRoof = bool.Parse(node["includeColliderRoof"].FirstChild.Value);
        }
        if (node["trackColliderWallHeight"] != null)
        {
            trackColliderWallHeight = float.Parse(node["trackColliderWallHeight"].FirstChild.Value);
        }
        if (node["trackBumpers"] != null)
        {
            trackBumpers = bool.Parse(node["trackBumpers"].FirstChild.Value);
        }
        if (node["bumperHeight"] != null)
        {
            bumperHeight = float.Parse(node["bumperHeight"].FirstChild.Value);
        }
        if (node["bumperWidth"] != null)
        {
            bumperWidth = float.Parse(node["bumperWidth"].FirstChild.Value);
        }
        if (node["bumperAngleThresold"] != null)
        {
            bumperAngleThresold = float.Parse(node["bumperAngleThresold"].FirstChild.Value);
        }
        if (node["disconnectBoundary"] != null)
        {
            _disconnectBoundary = bool.Parse(node["disconnectBoundary"].FirstChild.Value);
        }
        if (node["renderBoundaryWallReverse"] != null)
        {
            _renderBoundaryWallReverse = bool.Parse(node["renderBoundaryWallReverse"].FirstChild.Value);
        }


        RecalculateCurves();
    }