Exemple #1
0
    public static void create(long key, WayReference endPoint, string materialId)
    {
        bool isNode1 = endPoint.isNode1(NodeIndex.getPosById(key));
        bool isSmall = endPoint.SmallWay;

        Vector3 originalScale = endPoint.gameObject.transform.localScale;
        Vector3 nodeCameraPos = Game.getCameraPosition(isNode1 ? endPoint.node1 : endPoint.node2);

        Vector3 fromPos = nodeCameraPos - new Vector3(0f, originalScale.y / 2f, 0f);
        Vector3 toPos   = fromPos + new Vector3((isSmall ? originalScale.x / 2f : originalScale.y / 2f), originalScale.y, 0f);

        GameObject endPointObj = MapSurface.createPlaneMeshForPoints(fromPos, toPos, MapSurface.Anchor.LEFT_CENTER);

        endPointObj.name = "End of way (" + key + ")";
        Vector3 zOffset = new Vector3(0, 0, Game.WAYS_Z_POSITION);

        endPointObj.transform.position = endPointObj.transform.position + zOffset - (isNode1 ? Vector3.zero : endPoint.transform.rotation * new Vector3(isSmall ? originalScale.x / 2f : originalScale.y / 2f, 0f, 0f));
        endPointObj.transform.parent   = Game.instance.waysParent;
        endPointObj.transform.rotation = endPoint.transform.rotation;
        AutomaticMaterialObject endPointMaterialObject = endPointObj.AddComponent <AutomaticMaterialObject> () as AutomaticMaterialObject;

        endPointMaterialObject.requestMaterial(materialId, null);          // TODO - Default material

        // Add rigidbody and mesh collider, so that they will fall onto the underlying plane
        Misc.AddGravityToWay(endPointObj);
        Misc.AddWayObjectComponent(endPointObj);
    }
Exemple #2
0
    public static void CreateCurved(GameObject parent, long key, List <WayReference> wayReferences)
    {
        // Make sure to only make dashed lines if the number of fields are the same in the way direction
        WayReference firstWayReference  = wayReferences [0];
        WayReference secondWayReference = wayReferences [1];

        bool firstIsNode1  = firstWayReference.isNode1(NodeIndex.getPosById(key));
        bool secondIsNode1 = secondWayReference.isNode1(NodeIndex.getPosById(key));

        float firstFieldsTowardsPos = firstWayReference.getNumberOfFieldsInDirection(!firstIsNode1);
        float secondFieldsFromPos   = secondWayReference.getNumberOfFieldsInDirection(secondIsNode1);

        float secondFieldsTowardsPos = secondWayReference.getNumberOfFieldsInDirection(!secondIsNode1);
        float firstFieldsFromPos     = firstWayReference.getNumberOfFieldsInDirection(firstIsNode1);
        bool  makeDashedLines        = firstFieldsTowardsPos == secondFieldsFromPos && secondFieldsTowardsPos == firstFieldsFromPos;

        if (firstWayReference.way.WayWidthFactor >= WayHelper.LIMIT_WAYWIDTH && firstWayReference.way.CarWay)
        {
//			createOuterLines (reference);
            CreateCurvedMiddleLine(parent, key, wayReferences);
            if (makeDashedLines)
            {
                CreateCurvedDashedLines(parent, key, wayReferences);
            }
        }
    }
Exemple #3
0
    public static void Create(GameObject parent, long key, List <WayReference> wayReferences)
    {
        WayReference firstWayReference      = wayReferences[0];
        WayReference secondWayReference     = wayReferences[1];
        Quaternion   firstWayRotation       = firstWayReference.transform.rotation;
        float        crossingAngle          = (secondWayReference.transform.rotation.eulerAngles.z - firstWayRotation.eulerAngles.z) / 2f;
        Vector3      crossingRotationVector = new Vector3(0f, 0f, firstWayRotation.eulerAngles.z + crossingAngle);
        Quaternion   crossingRotation       = Quaternion.Euler(crossingRotationVector);
        Quaternion   orthoCrossingRotation  = Quaternion.Euler(crossingRotationVector + WayHelper.DEGREES_90_VECTOR);
        Pos          pos                   = NodeIndex.getPosById(key);
        GameObject   crossingLine          = Game.instance.wayCrossing;
        float        lineHeight            = crossingLine.transform.localScale.y;
        float        wayScale              = Game.instance.partOfWay.transform.localScale.y * Settings.wayWidthFactor;
        float        lineWidth             = crossingLine.transform.localScale.x * Settings.wayWidthFactor * firstWayReference.way.WayWidthFactor;
        float        wayHeight             = firstWayReference.way.WayWidthFactor * wayScale;
        Vector3      startPosition         = Game.getCameraPosition(pos) - orthoCrossingRotation * new Vector3(wayHeight / 2f, 0, 0) + crossingLine.transform.position;
        float        numberOfCrossingLines = Mathf.Floor((wayHeight - WayHelper.CROSSING_LINE_PERCENTAGE * lineHeight) / (lineHeight + WayHelper.CROSSING_LINE_PERCENTAGE * lineHeight));
        float        spaceHeight           = (wayHeight - numberOfCrossingLines * lineHeight) / (numberOfCrossingLines + 1);
        float        stepLength            = spaceHeight + lineHeight;

        for (int i = 1; i <= numberOfCrossingLines; i++)
        {
            Vector3    lineCenter = startPosition + orthoCrossingRotation * new Vector3(i * stepLength - lineHeight / 2f, 0, -0.01f);
            GameObject line       = MonoBehaviour.Instantiate(crossingLine, lineCenter, crossingRotation) as GameObject;
            line.transform.localScale = new Vector3(lineWidth, crossingLine.transform.localScale.y, crossingLine.transform.localScale.z);
            line.transform.SetParent(parent.transform);
        }
    }
Exemple #4
0
    private void spawnUnit(EMERGENCY_TYPE type, Vector3 targetPosition)
    {
        List <Pos> endPositions = getEndPosForVector(targetPosition);

        Pos startPos;

        do
        {
            startPos = NodeIndex.getPosById(Misc.pickRandomKey(NodeIndex.endPointDriveWayIndex));
        } while (startPos.Id == endPositions[0].Id || (endPositions.Count == 2 && startPos.Id == endPositions[1].Id));

        // Find out which is the closest of the two end points
        Pos endPos        = null;
        Pos secondLastPos = null;

        if (endPositions.Count == 1)
        {
            endPos = endPositions[0];
        }
        else
        {
            if (Game.isPathToFirstClosest(startPos, endPositions[0], endPositions[1]))
            {
                endPos        = endPositions[1];
                secondLastPos = endPositions[0];
            }
            else
            {
                endPos        = endPositions[0];
                secondLastPos = endPositions[1];
            }
        }

        // TODO - When having Ambulance or Fire Truck, change some of these
        // TODO - Which of these SHOULD be "Po-liz", and which shouldn't
        float       speedFactor  = Misc.randomRange(1.1f, 1.5f);
        float       acceleration = Misc.randomRange(3f, 3.5f);
        long        newId        = 0L;
        string      newName      = "Po-liz";
        float       newTime      = GameTimer.elapsedTime() + Misc.randomRange(5f, 15f);
        List <long> newWayPoints = secondLastPos != null ? new List <long>()
        {
            secondLastPos.Id
        } : new List <long>();
        string       newBrand        = "Po-liz";
        string       newType         = "Po-liz";
        List <long>  newPassengerIds = new List <long>();
        List <float> newMood         = new List <float>()
        {
            1f, 0f, 1.5f
        };

        Setup.VehicleSetup vehicleSetup = new Setup.VehicleSetup(newId, newName, newTime, startPos.Id, endPos.Id, null, false, false, newWayPoints, newBrand, null, newType, 0, 0F, 1F, 0L, newPassengerIds, speedFactor, acceleration, 0F, 0F, 0f, null, null, newMood, 0.1F, 0.05F, true, true);
        vehicleSetup.emergencyId = emergencyId;

        CustomObjectCreator.instance.addVehicle(vehicleSetup);
    }
Exemple #5
0
 private void setWaypointsInfo(Setup.PersonSetup personality)
 {
     if (personality != null && personality.wayPoints != null)
     {
         this.wayPoints     = NodeIndex.getPosById(personality.wayPoints);
         this.wayPointsLoop = personality.wayPointsLoop;
     }
     else
     {
         this.wayPoints = new List <Pos>();
     }
 }
Exemple #6
0
    private static void CreateTrafficLightColliders()
    {
        // For each pos in TrafficLightsForPos, register an entry in TrafficLightToggle, with position and radius
        foreach (KeyValuePair <long, List <TrafficLightLogic> > trafficLightGroup in TrafficLightsForPos)
        {
            long    posId                   = trafficLightGroup.Key;
            Pos     centerPos               = NodeIndex.getPosById(posId);
            float   maxDistance             = 0f;
            Vector3 centerPosCameraPosition = Game.getCameraPosition(centerPos);

            // Get max distance from crossing
            foreach (TrafficLightLogic trafficLight in trafficLightGroup.Value)
            {
                maxDistance = Mathf.Max(Vector2.Distance(trafficLight.transform.position, centerPosCameraPosition), maxDistance);
            }

            // Double the maxDistance to get a somewhat bigger touch area
            TrafficLightToggle.Add(posId, centerPosCameraPosition, maxDistance * 2f);
        }
        TrafficLightToggle.Start();
    }
Exemple #7
0
    private void grabOrSpawn(int numberOfUnits, EMERGENCY_TYPE type, Vector3 closestToPosition, Vehicle potentialVehicle)
    {
        // TODO - Based on "type"
        string         brand = "Po-liz";
        List <Vehicle> availableEmergencyUnits = Misc.GetVehicles(brand);

        // If position is not on map... pretend it's on of our endpoints
        if (closestToPosition == Misc.VECTOR3_NULL)
        {
            long endPointNode = Misc.pickRandomKey(NodeIndex.endPointDriveWayIndex);
            if (endPointNode != 0L)
            {
                closestToPosition = Game.getCameraPosition(NodeIndex.getPosById(endPointNode));
            }
        }
        else
        {
            // Make a collider, this will grow once emergency vehicles are standing still - when dispatching vehicle sees this, it has arrived
            BoxCollider collider = createCollider(closestToPosition, potentialVehicle);
            registerCollider(emergencyId, collider);
        }

        // Filter the units that are already on the way to other emergencies - and can re-route to given position
        availableEmergencyUnits = availableEmergencyUnits.FindAll(vehicle => !vehicle.areSirensOn() && vehicle.canReroute(closestToPosition));

        // If there are too many, pick out some, either by position, or randomly...
        if (availableEmergencyUnits.Count > numberOfUnits)
        {
            availableEmergencyUnits = pickUnits(numberOfUnits, closestToPosition, availableEmergencyUnits);
        }

        // Dispatch units on map
        dispatchUnits(availableEmergencyUnits, closestToPosition);

        // If there aren't units on the map, spawn "the rest"
        spawnUnits(numberOfUnits - availableEmergencyUnits.Count, type, closestToPosition);

//        Debug.Log(availableEmergencyUnits.Count);
    }
Exemple #8
0
    private List <Pos> getEndPosForVector(Vector3 vector)
    {
        // First check in the end-point register
        foreach (KeyValuePair <long, List <WayReference> > pair in NodeIndex.endPointDriveWayIndex)
        {
            if (Game.getCameraPosition(NodeIndex.getPosById(pair.Key)) == vector)
            {
                return(new List <Pos>()
                {
                    NodeIndex.getPosById(pair.Key)
                });
            }
        }

        // If not found as end-point, get closest WayReference
        WayReference closestWayReference = NodeIndex.getClosestWayReference(vector);

        return(new List <Pos>()
        {
            closestWayReference.node1,
            closestWayReference.node2
        });
    }
Exemple #9
0
    public static void create(long key, List <WayReference> wayReferences, string materialId)
    {
        if (off)
        {
            return;
        }
        Pos pos = NodeIndex.getPosById(key);

        // Sort based on rotation in the point closest to the intersection
        wayReferences.Sort(delegate(WayReference x, WayReference y) {
            float angleDiff = AngleAroundNode(pos, x) - AngleAroundNode(pos, y);
            // Ignoring float to int issues (if there are any)
            int angleDiffInt = (int)angleDiff;
            return(angleDiffInt);
        });

        // Gather our way bounds (used for checking if ways intersects each other)
        List <Bounds> wayBounds = getWayBounds(wayReferences);

        // List of positions where to draw the mesh
        List <Vector3> meshPoints;

        List <WayReference> intersectionList = Misc.CloneBaseNodeList(wayReferences);
        bool isComplex = false;

        if (intersectionList.Count == 2 && wayBounds [0].Intersects(wayBounds [1]))
        {
            // Only two ways and they intersect, special logic
            meshPoints = getMeshPointsForComplexTwoWay(intersectionList, wayBounds, pos);
            isComplex  = true;
        }
        else
        {
            meshPoints = getMeshPointsForNonComplex(intersectionList, wayBounds, pos);
        }

//		Debug.Log ("Intersection");
        GameObject intersectionObj = MapSurface.createPlaneMeshForPoints(meshPoints);

        intersectionObj.name = "Intersection " + (isComplex ? "complex " : "") + (intersectionList.Count - 1) + "-way (" + key + ")";
        Vector3 zOffset = new Vector3(0, 0, Game.WAYS_Z_POSITION);

        intersectionObj.transform.position = intersectionObj.transform.position + zOffset;
        intersectionObj.transform.parent   = Game.instance.waysParent;
        AutomaticMaterialObject intersectionMaterialObject = intersectionObj.AddComponent <AutomaticMaterialObject> () as AutomaticMaterialObject;

        intersectionMaterialObject.requestMaterial(materialId, null);          // TODO - Should have same material as connecting way(s)
        Misc.AddGravityToWay(intersectionObj);
        Misc.AddWayObjectComponent(intersectionObj);

        // Need waylines for all straight ways
        if (wayReferences.Count == 2)
        {
            bool wayQualifiedForCrossing = wayReferences[0].way.WayWidthFactor >= WayHelper.LIMIT_WAYWIDTH && wayReferences[0].way.CarWay;
            if (pos.getTagValue("highway") == "crossing" && wayQualifiedForCrossing)
            {
                WayCrossing.Create(intersectionObj, key, wayReferences);
            }
            else
            {
                WayLine.CreateCurved(intersectionObj, key, wayReferences);
            }
        }
    }
Exemple #10
0
    private static void CreateCurvedDashedLines(GameObject parent, long key, List <WayReference> wayReferences)
    {
        GameObject curveDashedLines = new GameObject();

        curveDashedLines.name = "Curved dashed lines";
        curveDashedLines.transform.SetParent(parent.transform);
        curveDashedLines.transform.localPosition = Vector3.zero;

        Pos     centerPos   = NodeIndex.getPosById(key);
        Vector3 posPosition = Game.getCameraPosition(centerPos);

        WayReference firstReference  = wayReferences [0];
        WayReference secondReference = wayReferences [1];

        bool firstIsNode1  = firstReference.isNode1(centerPos);
        bool secondIsNode1 = secondReference.isNode1(centerPos);

        GameObject wayFirst  = firstReference.gameObject;
        GameObject waySecond = secondReference.gameObject;

        // Number of fields in opposite direction
        float fieldsFromPos2 = firstReference.getNumberOfFieldsInDirection(false);

        // Number of fields in own direction
        float fieldsFromPos1 = firstReference.getNumberOfFieldsInDirection(true);

        // Number of fields in total
        float numberOfFields = firstReference.getNumberOfFields();

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

        for (float field = 1; field < fieldsFromPos2; field++)
        {
            dashedLineFields.Add(field);
        }

        for (float field = 1; field < fieldsFromPos1; field++)
        {
            dashedLineFields.Add(fieldsFromPos2 + field);
        }

        // If ways have same "isNode1", invert y-axis for second way
        bool isSameNode1 = firstIsNode1 == secondIsNode1;

        // Way width
        float wayHeight            = wayFirst.transform.localScale.y;
        float wayHeightCompensated = wayHeight - GetLineHeight() * 2f;

        foreach (float field in dashedLineFields)
        {
            GameObject curveDashes = new GameObject();
            curveDashes.name = "Curved dashes";
            curveDashes.transform.SetParent(curveDashedLines.transform);
            curveDashes.transform.localPosition = Vector3.zero;

            // Percentual position of way width, where to put middle line
            float percentualPositionY = field / numberOfFields;

            // Get our points (center in y-axis)
            float yPositionInWay       = percentualPositionY * wayHeightCompensated;
            float dashYMiddle          = -wayHeightCompensated / 2f + GetLineHeight() + yPositionInWay - GetDashedLineHeight() / 2f;
            float dashYMiddleSameNode1 = wayHeightCompensated / 2f - yPositionInWay + GetDashedLineHeight() / 2f;

            Vector3 firstPosMiddle  = posPosition + wayFirst.transform.rotation * new Vector3((firstIsNode1 ? 1 : -1) * wayHeight / 2f, dashYMiddle, 0);
            Vector3 secondPosMiddle = posPosition + waySecond.transform.rotation * new Vector3((secondIsNode1 ? 1 : -1) * wayHeight / 2f, isSameNode1 ? dashYMiddleSameNode1 : dashYMiddle, 0);

            Vector3 halfDashedLineHeight = new Vector3(0, GetDashedLineHeight() / 2f, 0);

            // Get our points (top in y-axis)
            Vector3 wayFirstHalfDashedHeight  = wayFirst.transform.rotation * halfDashedLineHeight;
            Vector3 waySecondHalfDashedHeight = waySecond.transform.rotation * halfDashedLineHeight;
            Vector3 firstPosTop  = firstPosMiddle - wayFirstHalfDashedHeight;
            Vector3 secondPosTop = secondPosMiddle + (isSameNode1 ? 1 : -1) * waySecondHalfDashedHeight;

            // Get our points (bottom in y-axis)
            Vector3 firstPosBottom  = firstPosMiddle + wayFirstHalfDashedHeight;
            Vector3 secondPosBottom = secondPosMiddle + (isSameNode1 ? -1 : 1) * waySecondHalfDashedHeight;

            Quaternion firstRotation   = firstIsNode1 ? WayHelper.ONEEIGHTY_DEGREES * wayFirst.transform.rotation : wayFirst.transform.rotation;
            Quaternion secondRotation  = secondIsNode1 ? WayHelper.ONEEIGHTY_DEGREES * waySecond.transform.rotation : waySecond.transform.rotation;
            Vector3    firstDirection  = firstRotation * Vector3.right;
            Vector3    secondDirection = secondRotation * Vector3.right;

            Vector3 intersectionPoint;
            Vector3 intersectionPointTop;
            Vector3 intersectionPointBottom;
            bool    intersectionFound = Math3d.LineLineIntersection(out intersectionPoint, firstPosMiddle, firstDirection, secondPosMiddle, secondDirection);
            if (!intersectionFound && firstRotation.eulerAngles.z == secondRotation.eulerAngles.z)
            {
                intersectionFound       = true;
                intersectionPoint       = firstPosMiddle + ((secondPosMiddle - firstPosMiddle) / 2);
                intersectionPointTop    = firstPosTop + ((secondPosTop - firstPosTop) / 2);
                intersectionPointBottom = firstPosBottom + ((secondPosBottom - firstPosBottom) / 2);
            }
            else
            {
                Math3d.LineLineIntersection(out intersectionPointTop, firstPosTop, firstDirection, secondPosTop, secondDirection);
                Math3d.LineLineIntersection(out intersectionPointBottom, firstPosBottom, firstDirection, secondPosBottom, secondDirection);
            }

            // TODO - Shouldn't be needed - debug only
            if (!intersectionFound)
            {
                Debug.Log("ERR: " + key);
                return;
            }

            // 1. Get bezier length for curve
            float bezierLength = Math3d.GetBezierLength(firstPosMiddle, intersectionPoint, secondPosMiddle);

            // 2. Decide how many dashes to fit, with gaps (also calculate each dash and gap length)
            // If only one line
            float numberOfLines   = 1f;
            float dashedLineWidth = bezierLength;
            float dashedLineGap   = 0f;
            // If more lines
            if (bezierLength > DASHED_LINE_WIDTH + CITY_DASHED_LINE_GAP)
            {
                float totalWidth = 0f;
                for (numberOfLines = 2f;  ; numberOfLines++)
                {
                    totalWidth = DASHED_LINE_WIDTH + (DASHED_LINE_WIDTH + CITY_DASHED_LINE_GAP) * (numberOfLines - 1);
                    if (totalWidth >= bezierLength)
                    {
                        break;
                    }
                }
                dashedLineWidth = DASHED_LINE_WIDTH * bezierLength / totalWidth;
                dashedLineGap   = CITY_DASHED_LINE_GAP * bezierLength / totalWidth;
            }


            // 3. Calculate each dash along the line t (time) on bezier curve
            List <KeyValuePair <float, float> > dashTimes = new List <KeyValuePair <float, float> > ();
            if (numberOfLines == 1f)
            {
                dashTimes.Add(new KeyValuePair <float, float>(0f, 1f));
            }
            else
            {
                dashTimes.Add(new KeyValuePair <float, float>(0f, dashedLineWidth / bezierLength));
                for (float lineStart = dashedLineWidth + dashedLineGap; lineStart < bezierLength; lineStart += dashedLineWidth + dashedLineGap)
                {
                    float lineStartTime = lineStart / bezierLength;
                    dashTimes.Add(new KeyValuePair <float, float>(lineStartTime, lineStartTime + dashedLineWidth / bezierLength));
                }
            }

            foreach (KeyValuePair <float, float> dashTime in dashTimes)
            {
                float startTime         = dashTime.Key;
                float endTime           = dashTime.Value;
                float dashLengthPercent = endTime - startTime;
                float numberOfPoints    = Mathf.Max(bezierLength / dashLengthPercent * WayHelper.BEZIER_RESOLUTION, 4f);
                float eachPointTime     = dashLengthPercent / numberOfPoints;

                List <Vector3> dashPoints = new List <Vector3>();

                // Top line
                for (float t = startTime; t <= endTime; t += eachPointTime)
                {
                    dashPoints.Add(Math3d.GetVectorInBezierAtTime(t, firstPosTop, intersectionPointTop, secondPosTop));
                }

                // Bottom line
                for (float t = endTime; t >= startTime; t -= eachPointTime)
                {
                    dashPoints.Add(Math3d.GetVectorInBezierAtTime(t, firstPosBottom, intersectionPointBottom, secondPosBottom));
                }

                GameObject lineMiddle = MapSurface.createPlaneMeshForPoints(dashPoints);
                lineMiddle.name = "Curved dash";
                WayLine.SetWhiteMaterial(lineMiddle);
                lineMiddle.transform.SetParent(curveDashes.transform);
                lineMiddle.transform.localPosition = new Vector3(0, 0, -0.01f);
            }
        }
    }
Exemple #11
0
    private static void CreateCurvedMiddleLine(GameObject parent, long key, List <WayReference> wayReferences)
    {
        Pos     centerPos   = NodeIndex.getPosById(key);
        Vector3 posPosition = Game.getCameraPosition(centerPos);

        WayReference firstReference  = wayReferences [0];
        WayReference secondReference = wayReferences [1];

        bool firstIsNode1  = firstReference.isNode1(centerPos);
        bool secondIsNode1 = secondReference.isNode1(centerPos);

        GameObject wayFirst  = firstReference.gameObject;
        GameObject waySecond = secondReference.gameObject;

        // Number of fields in opposite direction
        float fieldsFromPos2 = firstReference.getNumberOfFieldsInDirection(false);

        // Number of fields in total
        float numberOfFields = firstReference.getNumberOfFields();

        // Percentual position of way width, where to put middle line
        float percentualPositionY = fieldsFromPos2 / numberOfFields;

        // Way width
        float wayHeight = wayFirst.transform.localScale.y - GetLineHeight() * 2f;

        // TODO - What if the wayReference is REALLY short
        Vector3    wayFirstSize                = wayFirst.transform.localScale;
        Quaternion wayFirstRotation            = wayFirst.transform.rotation;
        float      wayFirstWayWidth            = (firstIsNode1 ? 1 : -1) * wayFirstSize.y;
        float      lineFirstPositionAdjustment = percentualPositionY * wayHeight;
        Vector3    wayFirstMiddleLineTopPos    = posPosition + wayFirstRotation * new Vector3(wayFirstWayWidth / 2f, -wayHeight / 2f + lineFirstPositionAdjustment, 0f);
        Vector3    wayFirstMiddleLineBottomPos = posPosition + wayFirstRotation * new Vector3(wayFirstWayWidth / 2f, -wayHeight / 2f + GetLineHeight() + lineFirstPositionAdjustment, 0f);

        Vector3    waySecondSize                = waySecond.transform.localScale;
        Quaternion waySecondRotation            = waySecond.transform.rotation;
        float      waySecondWayWidth            = (secondIsNode1 ? 1 : -1) * waySecondSize.y;
        float      lineSecondPositionAdjustment = percentualPositionY * wayHeight;
        Vector3    waySecondMiddleLineTopPos    = posPosition + waySecondRotation * new Vector3(waySecondWayWidth / 2f, -wayHeight / 2f + lineSecondPositionAdjustment, 0f);
        Vector3    waySecondMiddleLineBottomPos = posPosition + waySecondRotation * new Vector3(waySecondWayWidth / 2f, -wayHeight / 2f + GetLineHeight() + lineSecondPositionAdjustment, 0f);

        if (IsTopAndBottomCrossing(wayFirstMiddleLineTopPos, waySecondMiddleLineTopPos, wayFirstMiddleLineBottomPos, waySecondMiddleLineBottomPos))
        {
            Vector3 tmp = wayFirstMiddleLineBottomPos;
            wayFirstMiddleLineBottomPos = wayFirstMiddleLineTopPos;
            wayFirstMiddleLineTopPos    = tmp;
        }

//		DebugFn.square (wayFirstMiddleLineTopPos);
//		DebugFn.square (wayFirstMiddleLineBottomPos);
//		DebugFn.square (waySecondMiddleLineTopPos);
//		DebugFn.square (waySecondMiddleLineBottomPos);

        List <Vector3> linePoints = new List <Vector3> ();

        linePoints.Add(wayFirstMiddleLineTopPos);
        AddBezierPoints(linePoints, wayFirstMiddleLineTopPos, wayFirstRotation, waySecondMiddleLineTopPos, waySecondRotation);
        linePoints.Add(waySecondMiddleLineBottomPos);
        AddBezierPoints(linePoints, waySecondMiddleLineBottomPos, waySecondRotation, wayFirstMiddleLineBottomPos, wayFirstRotation);

        GameObject lineMiddle = MapSurface.createPlaneMeshForPoints(linePoints);

        lineMiddle.name = "Curved middle line";
        WayLine.SetWhiteMaterial(lineMiddle);
        lineMiddle.transform.SetParent(parent.transform);
        lineMiddle.transform.localPosition = new Vector3(0, 0, -0.01f);
    }