Пример #1
0
    //Setup all the papi lights.
    private void SetupPapiLights(ref List <SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness)
    {
        for (int side = 0; side < 2; side++)
        {
            if (runwayData.papiType[side] != PapiType.NONE)
            {
                //Calculate the offset direction.
                Vector3 lengthOffsetDir     = Math3d.GetForwardVector(runwayData.rotation[side]);
                Vector3 sideOffsetDir       = Math3d.GetRightVector(runwayData.rotation[side]);
                Vector3 lengthEdgeOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, 337f);

                if ((runwayData.papiType[side] == PapiType.PAPIRIGHT) || (runwayData.papiType[side] == PapiType.PAPIBOTH))
                {
                    Vector3 startOffsetVec  = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f);
                    Vector3 startPosition   = runwayData.thresholdPosition[side] + startOffsetVec;
                    Vector3 currentPosition = startPosition;

                    Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f);

                    for (int i = 0; i < 4; i++)
                    {
                        SpriteLights.LightData data = new SpriteLights.LightData();

                        float angle = GetPapiAngle(i);

                        data.position = currentPosition;
                        data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle);
                        lightData.Add(data);

                        currentPosition += sideOffsetVec;
                    }
                }

                if ((runwayData.papiType[side] == PapiType.PAPILEFT) || (runwayData.papiType[side] == PapiType.PAPIBOTH))
                {
                    sideOffsetDir *= -1;

                    Vector3 startOffsetVec  = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f);
                    Vector3 startPosition   = runwayData.thresholdPosition[side] + startOffsetVec;
                    Vector3 currentPosition = startPosition;

                    Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f);

                    for (int i = 0; i < 4; i++)
                    {
                        SpriteLights.LightData data = new SpriteLights.LightData();

                        float angle = GetPapiAngle(i);

                        data.position = currentPosition;
                        data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle);
                        lightData.Add(data);

                        currentPosition += sideOffsetVec;
                    }
                }
            }
        }
    }
Пример #2
0
    //Setup all the centerline lights.
    private void SetupCenterlineLights(ref List <SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size)
    {
        if (runwayData.centerlineLights)
        {
            //Calculate the amount of lights.
            int lightAmountInRow = (int)Mathf.Floor(runwayData.length / runwayData.centerlineLightsSpacing);

            //Calculate the offset direction.
            Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[0]);

            //Calculate the start position.
            float rowLength  = (lightAmountInRow - 1) * runwayData.centerlineLightsSpacing;
            float edgeOffset = (runwayData.length - rowLength) * 0.5f;

            Vector3 startOffsetVec  = Math3d.SetVectorLength(lengthOffsetDir, edgeOffset);
            Vector3 startPosition   = runwayData.thresholdPosition[0] + startOffsetVec;
            Vector3 currentPosition = startPosition;

            Vector3 lengthOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, runwayData.centerlineLightsSpacing);

            //Calculate the point where the lights should change color.
            float redA       = 300f + runwayData.centerlineLightsSpacing;
            float redB       = (runwayData.length - (300f + runwayData.centerlineLightsSpacing));
            float alternateA = 900f + runwayData.centerlineLightsSpacing;
            float alternateB = (runwayData.length - (900f + runwayData.centerlineLightsSpacing));

            for (int i = 0; i < lightAmountInRow; i++)
            {
                bool passedRedA       = false;
                bool passedAlternateA = false;
                bool passedRedB       = false;
                bool passedAlternateB = false;

                SpriteLights.LightData data = new SpriteLights.LightData();

                //Is the current light index even or odd?
                bool even = IsEven(i);

                data.position = currentPosition;
                data.rotation = runwayData.rotation[0];

                //Calculate the distance to the threshold.
                float currentDistance = (i * runwayData.centerlineLightsSpacing) + edgeOffset;

                //The last 900 meter of the runway has alternating red and white lights.
                if (currentDistance <= alternateA)
                {
                    passedAlternateA = true;
                }

                //The last 900 meter of the runway has alternating red and white lights.
                if (currentDistance >= alternateB)
                {
                    passedAlternateB = true;
                }

                //The last 300 meter of the runway has red centerline lights.
                if (currentDistance <= redA)
                {
                    data.frontColor = whiteLight;
                    data.brightness = SetBrightness(randomBrightness, brightness);
                    data.backColor  = redLight;

                    passedRedA = true;
                }

                //The last 300 meter of the runway has red centerline lights.
                if (currentDistance >= redB)
                {
                    passedRedB = true;

                    data.frontColor = redLight;
                    data.brightness = SetBrightness(randomBrightness, brightness);
                    data.backColor  = whiteLight;
                }

                //The last 900 meter of the runway has alternating red and white lights.
                if (passedAlternateA && !passedRedA)
                {
                    if (even)
                    {
                        data.frontColor = whiteLight;
                        data.brightness = SetBrightness(randomBrightness, brightness);
                        data.backColor  = redLight;
                    }

                    else
                    {
                        data.frontColor = whiteLight;
                        data.brightness = SetBrightness(randomBrightness, brightness);
                        data.backColor  = whiteLight;
                    }
                }

                //The last 900 meter of the runway has alternating red and white lights.
                if (passedAlternateB && !passedRedB)
                {
                    if (even)
                    {
                        data.frontColor = redLight;
                        data.brightness = SetBrightness(randomBrightness, brightness);
                        data.backColor  = whiteLight;
                    }

                    else
                    {
                        data.frontColor = whiteLight;
                        data.brightness = SetBrightness(randomBrightness, brightness);
                        data.backColor  = whiteLight;
                    }
                }

                //Middle of the runway
                if (!passedRedA && !passedRedB && !passedAlternateA && !passedAlternateB)
                {
                    data.frontColor = whiteLight;
                    data.brightness = SetBrightness(randomBrightness, brightness);
                    data.backColor  = whiteLight;
                }

                data.size = size;

                lightData.Add(data);

                currentPosition += lengthOffsetVec;
            }
        }
    }
Пример #3
0
    //Setup all the threshold lights.
    private void SetupThresholdLights(ref List <SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size)
    {
        for (int side = 0; side < 2; side++)
        {
            //Calculate the amount of lights.
            int lightAmountInRow = (int)Mathf.Ceil(runwayData.width / thresholdLightsSpacing);

            //Calculate the width of the threshold light row.
            float rowWidth = (lightAmountInRow - 1) * thresholdLightsSpacing;

            //Set start position.
            Vector3 sideOffsetDir    = Math3d.GetRightVector(runwayData.rotation[side]);
            Vector3 startOffsetAVec  = Math3d.SetVectorLength(sideOffsetDir, rowWidth * 0.5f);
            Vector3 startPosition    = runwayData.thresholdPosition[side] + startOffsetAVec;
            Vector3 thresholdACorner = startPosition;
            Vector3 currentPosition  = startPosition;

            Vector3 sideOffsetVec = Math3d.SetVectorLength(-sideOffsetDir, thresholdLightsSpacing);

            SpriteLights.LightData data;

            //Create lights.
            for (int i = 0; i < lightAmountInRow; i++)
            {
                data = new SpriteLights.LightData();

                data.position   = currentPosition;
                data.rotation   = runwayData.rotation[side];
                data.frontColor = greenLight;
                data.brightness = SetBrightness(randomBrightness, brightness);
                data.backColor  = redLight;
                data.size       = size;

                lightData.Add(data);

                currentPosition += sideOffsetVec;
            }

            //Create wing bars.
            if (runwayData.thresholdWingbar[side] != ThresholdWingbar.NONE)
            {
                int lightAmount = 0;

                if (runwayData.thresholdWingbar[side] == ThresholdWingbar.LARGE)
                {
                    lightAmount = 9;
                }

                if (runwayData.thresholdWingbar[side] == ThresholdWingbar.SMALL)
                {
                    lightAmount = 4;
                }

                Vector3 barSideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 1.5f);

                //Set start position.
                currentPosition = thresholdACorner;

                //Create wing bars.
                for (int i = 0; i < lightAmount * 2; i++)
                {
                    data = new SpriteLights.LightData();

                    //Set the new start position.
                    if (i == lightAmount)
                    {
                        currentPosition   = runwayData.thresholdPosition[side] - startOffsetAVec;
                        barSideOffsetVec *= -1;
                    }

                    currentPosition += barSideOffsetVec;
                    data.position    = currentPosition;
                    data.rotation    = runwayData.rotation[side];
                    data.frontColor  = greenLight;
                    data.brightness  = SetBrightness(randomBrightness, brightness);
                    data.size        = size;

                    lightData.Add(data);
                }
            }
        }
    }
Пример #4
0
    //Setup all the touch down zone lights.
    private void SetupTDZLights(ref List <SpriteLights.LightData> lightData, ApproachLightData allApproachLightData, RunwayData runwayData, bool randomBrightness, float brightness, float size)
    {
        for (int side = 0; side < 2; side++)
        {
            if (runwayData.lightingType[side] != LightingType.NONE)
            {
                SvgData[] svgData = allApproachLightData.GetApproachLightData(runwayData.lightingType[side]);

                //Set TDZ lights.
                if (runwayData.TDZ[side])
                {
                    svgData = allApproachLightData.GetApproachLightData(LightingType.TDZ);

                    for (int i = 0; i < svgData.Length; i++)
                    {
                        if (svgData[i].materialString == whiteDirectionalSinglesideCString)
                        {
                            SpriteLights.LightData data = new SpriteLights.LightData();
                            Vector3 position            = (runwayData.rotation[side] * svgData[i].position) + runwayData.thresholdPosition[side];

                            data.frontColor = whiteLight;
                            data.brightness = SetBrightness(randomBrightness, brightness);
                            data.position   = position;

                            //Set the direction and upward rotation of the light.
                            data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);
                            data.size     = size;

                            lightData.Add(data);
                        }
                    }
                }
            }
        }
    }
Пример #5
0
    //Setup all the strobe lights.
    private void SetupStrobeLights(ref List <SpriteLights.LightData> lightData, ApproachLightData allApproachLightData, RunwayData runwayData, float strobeTimeStep)
    {
        float groupID = Random.Range(0.0f, 0.99f);

        for (int side = 0; side < 2; side++)
        {
            if (runwayData.lightingType[side] != LightingType.NONE)
            {
                SvgData[] svgData = allApproachLightData.GetApproachLightData(runwayData.lightingType[side]);

                if ((runwayData.strobeType[side] == StrobeType.ODALS) || (runwayData.strobeType[side] == StrobeType.BOTH))
                {
                    for (int i = 0; i < svgData.Length; i++)
                    {
                        SpriteLights.LightData data = new SpriteLights.LightData();
                        Vector3 position            = (runwayData.rotation[side] * svgData[i].position) + runwayData.thresholdPosition[side];

                        if (svgData[i].materialString == strobeCString)
                        {
                            data.position = position;

                            //Set the direction and upward rotation of the light.
                            data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

                            data.strobeID      = svgData[i].id * strobeTimeStep;
                            data.strobeGroupID = groupID;
                            lightData.Add(data);
                        }
                    }
                }

                if ((runwayData.strobeType[side] == StrobeType.REIL) || (runwayData.strobeType[side] == StrobeType.BOTH))
                {
                    float   distanceOffset = 0;
                    Vector3 sideOffsetDir  = Math3d.GetRightVector(runwayData.rotation[side]);

                    //If threshold wing bars are used, the REIL distance must be bigger, otherwise they overlap.
                    if (runwayData.thresholdWingbar[side] == ThresholdWingbar.LARGE)
                    {
                        distanceOffset = 15.5f;
                    }

                    if ((runwayData.thresholdWingbar[side] == ThresholdWingbar.SMALL) || (runwayData.thresholdWingbar[side] == ThresholdWingbar.NONE))
                    {
                        distanceOffset = 12f;
                    }

                    //Right strobe.
                    Vector3 startOffsetAVec     = Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + distanceOffset);
                    Vector3 position            = runwayData.thresholdPosition[side] + startOffsetAVec;
                    SpriteLights.LightData data = new SpriteLights.LightData();

                    data.position = position;

                    //Set the direction and upward rotation of the light.
                    data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

                    //The strobe ID is 0, so it will flash at the same time as all other strobes with ID 0.
                    //The group ID is the same as the walking strobe, so it is synchronized with that.
                    data.strobeID      = 0;
                    data.strobeGroupID = groupID;

                    lightData.Add(data);

                    //Left strobe.
                    position = runwayData.thresholdPosition[side] - startOffsetAVec;
                    data     = new SpriteLights.LightData();

                    data.position = position;

                    //Set the direction and upward rotation of the light.
                    data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

                    data.strobeGroupID = groupID;
                    lightData.Add(data);
                }
            }
        }
    }
Пример #6
0
    //Procedurally crate the runway lights.
    public void CreateRunwayLights()
    {
        int index;

        //Create an array which holds every possible runway.
        RunwayData[] runways          = new RunwayData[2];
        bool         randomBrightness = false;
        float        brightness       = 0.8f; //0.6f
        float        smallerLightSize = 0.7f; //0.8f

        index          = 0;
        runways[index] = new RunwayData();
        runways[index].SetThresholdPosition(new Vector3(0, 0, 0), 3000);
        runways[index].thresholdHeight[0] = 0;
        runways[index].thresholdHeight[1] = 0;
        runways[index].midHeight          = 0;
        runways[index].SetThresholdRotation(0);
        runways[index].width                   = 45;
        runways[index].lightingType[0]         = LightingType.ALSF2;
        runways[index].lightingType[1]         = LightingType.ALSF2;
        runways[index].strobeType[0]           = StrobeType.ODALS;
        runways[index].strobeType[1]           = StrobeType.BOTH;
        runways[index].papiType[0]             = PapiType.PAPIBOTH;
        runways[index].papiType[1]             = PapiType.PAPIBOTH;
        runways[index].centerlineLights        = true;
        runways[index].centerlineLightsSpacing = 15;
        runways[index].edgeLights              = true;
        runways[index].edgeLightsSpacing       = 60;
        runways[index].thresholdWingbar[0]     = ThresholdWingbar.LARGE;
        runways[index].thresholdWingbar[1]     = ThresholdWingbar.LARGE;
        runways[index].TDZ[0]                  = true;
        runways[index].TDZ[1]                  = true;

        index          = 1;
        runways[index] = new RunwayData();
        runways[index].SetThresholdPosition(new Vector3(200, 0, 0), 3000);
        runways[index].thresholdHeight[0] = 0;
        runways[index].thresholdHeight[1] = 0;
        runways[index].midHeight          = 0;
        runways[index].SetThresholdRotation(0);
        runways[index].width                   = 45;
        runways[index].lightingType[0]         = LightingType.ALSF1;
        runways[index].lightingType[1]         = LightingType.ALSF1;
        runways[index].strobeType[0]           = StrobeType.BOTH;
        runways[index].strobeType[1]           = StrobeType.BOTH;
        runways[index].papiType[0]             = PapiType.PAPILEFT;
        runways[index].papiType[1]             = PapiType.PAPILEFT;
        runways[index].centerlineLights        = true;
        runways[index].centerlineLightsSpacing = 15;
        runways[index].edgeLights              = true;
        runways[index].edgeLightsSpacing       = 60;
        runways[index].thresholdWingbar[0]     = ThresholdWingbar.LARGE;
        runways[index].thresholdWingbar[1]     = ThresholdWingbar.LARGE;
        runways[index].TDZ[0]                  = true;
        runways[index].TDZ[1]                  = true;

        /*
         * index = 2;
         * runways[index] = new RunwayData();
         * runways[index].SetThresholdPosition(new Vector3(400, 0, 0), 2500);
         * runways[index].thresholdHeight[0] = 0;
         * runways[index].thresholdHeight[1] = 0;
         * runways[index].midHeight = 0;
         * runways[index].SetThresholdRotation(0);
         * runways[index].width = 40;
         * runways[index].lightingType[0] = LightingType.SALS;
         * runways[index].lightingType[1] = LightingType.SALS;
         * runways[index].strobeType[0] = StrobeType.BOTH;
         * runways[index].strobeType[1] = StrobeType.BOTH;
         * runways[index].papiType[0] = PapiType.PAPILEFT;
         * runways[index].papiType[1] = PapiType.PAPILEFT;
         * runways[index].centerlineLights = false;
         * runways[index].centerlineLightsSpacing = 15;
         * runways[index].edgeLights = true;
         * runways[index].edgeLightsSpacing = 60;
         * runways[index].thresholdWingbar[0] = ThresholdWingbar.SMALL;
         * runways[index].thresholdWingbar[1] = ThresholdWingbar.SMALL;
         * runways[index].TDZ[0] = false;
         * runways[index].TDZ[1] = false;
         *
         * index = 3;
         * runways[index] = new RunwayData();
         * runways[index].SetThresholdPosition(new Vector3(600, 0, 0), 3000);
         * runways[index].thresholdHeight[0] = 0;
         * runways[index].thresholdHeight[1] = 0;
         * runways[index].midHeight = 0;
         * runways[index].SetThresholdRotation(0);
         * runways[index].width = 45;
         * runways[index].lightingType[0] = LightingType.CALVERT2;
         * runways[index].lightingType[1] = LightingType.CALVERT2;
         * runways[index].strobeType[0] = StrobeType.NONE;
         * runways[index].strobeType[1] = StrobeType.NONE;
         * runways[index].papiType[0] = PapiType.PAPIBOTH;
         * runways[index].papiType[1] = PapiType.PAPIBOTH;
         * runways[index].centerlineLights = true;
         * runways[index].centerlineLightsSpacing = 15;
         * runways[index].edgeLights = true;
         * runways[index].edgeLightsSpacing = 60;
         * runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
         * runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
         * runways[index].TDZ[0] = true;
         * runways[index].TDZ[1] = true;
         *
         * index = 4;
         * runways[index] = new RunwayData();
         * runways[index].SetThresholdPosition(new Vector3(800, 0, 0), 3000);
         * runways[index].thresholdHeight[0] = 0;
         * runways[index].thresholdHeight[1] = 0;
         * runways[index].midHeight = 0;
         * runways[index].SetThresholdRotation(0);
         * runways[index].width = 45;
         * runways[index].lightingType[0] = LightingType.CALVERT1;
         * runways[index].lightingType[1] = LightingType.CALVERT1;
         * runways[index].strobeType[0] = StrobeType.NONE;
         * runways[index].strobeType[1] = StrobeType.NONE;
         * runways[index].papiType[0] = PapiType.PAPIRIGHT;
         * runways[index].papiType[1] = PapiType.PAPIRIGHT;
         * runways[index].centerlineLights = true;
         * runways[index].centerlineLightsSpacing = 15;
         * runways[index].edgeLights = true;
         * runways[index].edgeLightsSpacing = 60;
         * runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
         * runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
         * runways[index].TDZ[0] = true;
         * runways[index].TDZ[1] = true;
         */

        //Get the strobe timestep variable.
        strobeTimeStep = InitRunwayLights(runways);

        //Create temporary lists to store the light data,.
        List <SpriteLights.LightData> directionalLightData     = new List <SpriteLights.LightData>();
        List <SpriteLights.LightData> omnidirectionalLightData = new List <SpriteLights.LightData>();
        List <SpriteLights.LightData> strobeLightData          = new List <SpriteLights.LightData>();
        List <SpriteLights.LightData> papiLightData            = new List <SpriteLights.LightData>();

        ApproachLightData allApproachLightData = new ApproachLightData();

        //Get the position and color of the lights from an svg file.
        allApproachLightData.StoreApproachLightData();

        //Loop through all runways.
        for (int i = 0; i < runways.Length; i++)
        {
            //Create the light data and store in a temporary buffer.
            SetupApproachLights(ref directionalLightData, allApproachLightData, runways[i], randomBrightness, brightness, 1f);
            SetupTDZLights(ref directionalLightData, allApproachLightData, runways[i], randomBrightness, brightness, smallerLightSize);
            SetupStrobeLights(ref strobeLightData, allApproachLightData, runways[i], strobeTimeStep);
            SetupThresholdLights(ref directionalLightData, runways[i], false, 0.6f, 1f);
            SetupCenterlineLights(ref directionalLightData, runways[i], randomBrightness, brightness, smallerLightSize);
            SetupEdgeLights(ref omnidirectionalLightData, runways[i], randomBrightness, brightness, 1f);
            SetupPapiLights(ref papiLightData, runways[i], false);
        }

        //Create a parent object.
        GameObject parentObject = new GameObject("RunwayLights");

        //Take all the light data lists and create the actual ligth mesh from it.
        GameObject[] lightObjects = SpriteLights.CreateLights("Runway directional lights", directionalLightData.ToArray(), directionalLightsMat);
        MakeChild(parentObject, lightObjects);

        lightObjects = SpriteLights.CreateLights("Runway omnidirectional lights", omnidirectionalLightData.ToArray(), omnidirectionalRunwayLightsMat);
        MakeChild(parentObject, lightObjects);

        lightObjects = SpriteLights.CreateLights("Runway strobe lights", strobeLightData.ToArray(), strobeLightsMat);
        MakeChild(parentObject, lightObjects);

        lightObjects = SpriteLights.CreateLights("Runway PAPI lights", papiLightData.ToArray(), papiLightsMat);
        MakeChild(parentObject, lightObjects);

        parentObject.transform.position = new Vector3(-2941, 0, 10936);
        parentObject.transform.rotation = Quaternion.Euler(0, -111.5163f, 0);
    }
	//Setup all the centerline lights.
	private void SetupCenterlineLights(ref List<SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size){

		if(runwayData.centerlineLights){

			//Calculate the amount of lights.
			int lightAmountInRow = (int)Mathf.Floor(runwayData.length / runwayData.centerlineLightsSpacing);

			//Calculate the offset direction.
			Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[0]);

			//Calculate the start position.
			float rowLength = (lightAmountInRow - 1) * runwayData.centerlineLightsSpacing;
			float edgeOffset = (runwayData.length - rowLength) * 0.5f;

			Vector3 startOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, edgeOffset);
			Vector3 startPosition = runwayData.thresholdPosition[0] + startOffsetVec;
			Vector3 currentPosition = startPosition;

			Vector3 lengthOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, runwayData.centerlineLightsSpacing);

			//Calculate the point where the lights should change color.
			float redA = 300f + runwayData.centerlineLightsSpacing;		
			float redB = (runwayData.length - (300f + runwayData.centerlineLightsSpacing));
			float alternateA = 900f + runwayData.centerlineLightsSpacing;
			float alternateB = (runwayData.length - (900f + runwayData.centerlineLightsSpacing));

			for(int i = 0; i < lightAmountInRow; i++){

				bool passedRedA = false;
				bool passedAlternateA = false;
				bool passedRedB = false;
				bool passedAlternateB = false;

				SpriteLights.LightData data = new SpriteLights.LightData();

				//Is the current light index even or odd?
				bool even = IsEven(i);

				data.position = currentPosition;
				data.rotation = runwayData.rotation[0];

				//Calculate the distance to the threshold.
				float currentDistance = (i * runwayData.centerlineLightsSpacing) + edgeOffset;

				//The last 900 meter of the runway has alternating red and white lights.
				if(currentDistance <= alternateA){

					passedAlternateA = true;
				}

				//The last 900 meter of the runway has alternating red and white lights.
				if(currentDistance >= alternateB){

					passedAlternateB = true;
				}

				//The last 300 meter of the runway has red centerline lights.
				if(currentDistance <= redA){

					data.frontColor = whiteLight;
					data.brightness = SetBrightness(randomBrightness, brightness);
					data.backColor = redLight;

					passedRedA = true;
				}

				//The last 300 meter of the runway has red centerline lights.
				if(currentDistance >= redB){

					passedRedB = true;

					data.frontColor = redLight;
					data.brightness = SetBrightness(randomBrightness, brightness);
					data.backColor = whiteLight;
				}

				//The last 900 meter of the runway has alternating red and white lights.
				if(passedAlternateA && !passedRedA){

					if(even){

						data.frontColor = whiteLight;
						data.brightness = SetBrightness(randomBrightness, brightness);
						data.backColor = redLight;
					}

					else{

						data.frontColor = whiteLight;
						data.brightness = SetBrightness(randomBrightness, brightness);
						data.backColor = whiteLight;
					}
				}

				//The last 900 meter of the runway has alternating red and white lights.
				if(passedAlternateB && !passedRedB){

					if(even){

						data.frontColor = redLight;
						data.brightness = SetBrightness(randomBrightness, brightness);
						data.backColor = whiteLight;
					}

					else{

						data.frontColor = whiteLight;
						data.brightness = SetBrightness(randomBrightness, brightness);
						data.backColor = whiteLight;
					}
				}

				//Middle of the runway
				if(!passedRedA && !passedRedB && !passedAlternateA && !passedAlternateB){

					data.frontColor = whiteLight;
					data.brightness = SetBrightness(randomBrightness, brightness);
					data.backColor = whiteLight;
				}

				data.size = size;

				lightData.Add(data);

				currentPosition += lengthOffsetVec;
			}
		}
	}
Пример #8
0
    //Setup all the edge lights.
    private void SetupEdgeLights(ref List <SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size)
    {
        float sideFactor = 0;

        //Calculate the amount of lights.
        int lightAmountInRow = (int)Mathf.Floor(runwayData.length / runwayData.edgeLightsSpacing);

        //Calculate the offset direction.
        Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[0]);
        Vector3 sideOffsetDir   = Math3d.GetRightVector(runwayData.rotation[0]);

        //Calculate the start position.
        float rowLength         = (lightAmountInRow - 1) * runwayData.edgeLightsSpacing;
        float edgeForwardOffset = (runwayData.length - rowLength) * 0.5f;

        Vector3 lengthEdgeOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, edgeForwardOffset);
        Vector3 startOffsetVec      = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, runwayData.width * 0.5f);
        Vector3 startPosition       = runwayData.thresholdPosition[0] + startOffsetVec;
        Vector3 currentPosition     = startPosition;

        Vector3 lengthOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, runwayData.edgeLightsSpacing);

        //Calculate the point where the lights should change color.
        float amberA = 600f + runwayData.edgeLightsSpacing;
        float amberB = (runwayData.length - (600f + runwayData.edgeLightsSpacing));

        int doubleLightAmountInRow = lightAmountInRow * 2;

        for (int i = 0; i < doubleLightAmountInRow; i++)
        {
            bool passedAmberA = false;
            bool passedAmberB = false;

            SpriteLights.LightData data = new SpriteLights.LightData();

            //Shift the current position for the other side.
            if (i == lightAmountInRow)
            {
                startOffsetVec  = lengthEdgeOffsetVec + Math3d.SetVectorLength(-sideOffsetDir, runwayData.width * 0.5f);
                currentPosition = runwayData.thresholdPosition[0] + startOffsetVec;

                //Reset flags.
                passedAmberA = false;
                passedAmberB = false;
                sideFactor   = lightAmountInRow;
            }

            data.position = currentPosition;
            data.rotation = runwayData.rotation[0];

            //Calculate the distance to the threshold.
            float currentDistance = ((i - sideFactor) * runwayData.edgeLightsSpacing) + edgeForwardOffset;

            //The last 600 meter of the runway has red centerline lights.
            if (currentDistance <= amberA)
            {
                data.frontColor = whiteLight;
                data.brightness = SetBrightness(randomBrightness, brightness);
                data.backColor  = amberLight;

                passedAmberA = true;
            }

            //The last 300 meter of the runway has red centerline lights.
            if (currentDistance >= amberB)
            {
                passedAmberB = true;

                data.frontColor = amberLight;
                data.brightness = SetBrightness(randomBrightness, brightness);
                data.backColor  = whiteLight;
            }

            //Middle of the runway
            if (!passedAmberA && !passedAmberB)
            {
                data.frontColor = whiteLight;
                data.brightness = SetBrightness(randomBrightness, brightness);
                data.backColor  = whiteLight;
            }

            data.size = size;

            lightData.Add(data);

            currentPosition += lengthOffsetVec;
        }
    }
	//Setup all the touch down zone lights.
	private void SetupTDZLights(ref List<SpriteLights.LightData> lightData, ApproachLightData allApproachLightData, RunwayData runwayData, bool randomBrightness, float brightness, float size){

		for(int side = 0; side < 2; side++){

			if(runwayData.lightingType[side] != LightingType.NONE){

				SvgData[] svgData = allApproachLightData.GetApproachLightData(runwayData.lightingType[side]);

				//Set TDZ lights.
				if(runwayData.TDZ[side]){

					svgData = allApproachLightData.GetApproachLightData(LightingType.TDZ);

					for(int i = 0; i < svgData.Length; i++){

						if(svgData[i].materialString == whiteDirectionalSinglesideCString){

							SpriteLights.LightData data = new SpriteLights.LightData();
							Vector3 position = (runwayData.rotation[side] * svgData[i].position) + runwayData.thresholdPosition[side];

							data.frontColor = whiteLight;
							data.brightness = SetBrightness(randomBrightness, brightness);
							data.position = position;

							//Set the direction and upward rotation of the light.
							data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);
							data.size = size;

							lightData.Add(data);
						}
					}
				}
			}
		}
	}
	//Setup all the threshold lights.
	private void SetupThresholdLights(ref List<SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size){

		for(int side = 0; side < 2; side++){

			//Calculate the amount of lights.
			int lightAmountInRow = (int)Mathf.Ceil(runwayData.width / thresholdLightsSpacing);

			//Calculate the width of the threshold light row.
			float rowWidth = (lightAmountInRow - 1) * thresholdLightsSpacing;

			//Set start position.
			Vector3 sideOffsetDir = Math3d.GetRightVector(runwayData.rotation[side]);		
			Vector3 startOffsetAVec = Math3d.SetVectorLength(sideOffsetDir, rowWidth * 0.5f);
			Vector3 startPosition = runwayData.thresholdPosition[side] + startOffsetAVec;
			Vector3 thresholdACorner = startPosition;
			Vector3 currentPosition = startPosition;

			Vector3 sideOffsetVec = Math3d.SetVectorLength(-sideOffsetDir, thresholdLightsSpacing);

			SpriteLights.LightData data;

			//Create lights.
			for(int i = 0; i < lightAmountInRow; i++){

				data = new SpriteLights.LightData();

				data.position = currentPosition;
				data.rotation = runwayData.rotation[side];
				data.frontColor = greenLight;
				data.brightness = SetBrightness(randomBrightness, brightness);
				data.backColor = redLight;
				data.size = size;

				lightData.Add(data);

				currentPosition += sideOffsetVec;
			}

			//Create wing bars.
			if(runwayData.thresholdWingbar[side] != ThresholdWingbar.NONE){

				int lightAmount = 0;

				if(runwayData.thresholdWingbar[side] == ThresholdWingbar.LARGE){

					lightAmount = 9;
				}

				if(runwayData.thresholdWingbar[side] == ThresholdWingbar.SMALL){

					lightAmount = 4;
				}

				Vector3 barSideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 1.5f);

				//Set start position.	
				currentPosition = thresholdACorner;

				//Create wing bars.
				for(int i = 0; i < lightAmount * 2; i++){

					data = new SpriteLights.LightData();

					//Set the new start position.
					if(i == lightAmount){

						currentPosition = runwayData.thresholdPosition[side] - startOffsetAVec;
						barSideOffsetVec *= -1;
					}

					currentPosition += barSideOffsetVec;
					data.position = currentPosition;
					data.rotation = runwayData.rotation[side];
					data.frontColor = greenLight;
					data.brightness = SetBrightness(randomBrightness, brightness);
					data.size = size;

					lightData.Add(data);
				}
			}
		}
	}
	//Setup all the strobe lights.
	private void SetupStrobeLights(ref List<SpriteLights.LightData> lightData, ApproachLightData allApproachLightData, RunwayData runwayData, float strobeTimeStep){

		float groupID = Random.Range(0.0f, 0.99f); 

		for(int side = 0; side < 2; side++){

			if(runwayData.lightingType[side] != LightingType.NONE){

				SvgData[] svgData = allApproachLightData.GetApproachLightData(runwayData.lightingType[side]);

				if((runwayData.strobeType[side] == StrobeType.ODALS) || (runwayData.strobeType[side] == StrobeType.BOTH)){

					for(int i = 0; i < svgData.Length; i++){

						SpriteLights.LightData data = new SpriteLights.LightData();
						Vector3 position = (runwayData.rotation[side] * svgData[i].position) + runwayData.thresholdPosition[side];

						if(svgData[i].materialString == strobeCString){				

							data.position = position;

							//Set the direction and upward rotation of the light.
							data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

							data.strobeID = svgData[i].id * strobeTimeStep;
							data.strobeGroupID = groupID;
							lightData.Add(data);
						}			
					}
				}

				if((runwayData.strobeType[side] == StrobeType.REIL) || (runwayData.strobeType[side] == StrobeType.BOTH)){

					float distanceOffset = 0;
					Vector3 sideOffsetDir = Math3d.GetRightVector(runwayData.rotation[side]);	

					//If threshold wing bars are used, the REIL distance must be bigger, otherwise they overlap.
					if(runwayData.thresholdWingbar[side] == ThresholdWingbar.LARGE){

						distanceOffset = 15.5f;
					}

					if((runwayData.thresholdWingbar[side] == ThresholdWingbar.SMALL) || (runwayData.thresholdWingbar[side] == ThresholdWingbar.NONE)){

						distanceOffset = 12f;
					}					

					//Right strobe.
					Vector3 startOffsetAVec = Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + distanceOffset);
					Vector3 position = runwayData.thresholdPosition[side] + startOffsetAVec;
					SpriteLights.LightData data = new SpriteLights.LightData();

					data.position = position;

					//Set the direction and upward rotation of the light.
					data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

					//The strobe ID is 0, so it will flash at the same time as all other strobes with ID 0.
					//The group ID is the same as the walking strobe, so it is synchronized with that.
					data.strobeID = 0;
					data.strobeGroupID = groupID;

					lightData.Add(data);

					//Left strobe.
					position = runwayData.thresholdPosition[side] - startOffsetAVec;
					data = new SpriteLights.LightData();

					data.position = position;

					//Set the direction and upward rotation of the light.
					data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * runwayData.lightAngle);

					data.strobeGroupID = groupID;
					lightData.Add(data);
				}
			}
		}
	}
	//Setup all the shader variables.
	private float InitRunwayLights(RunwayData[] runways){

		float strobeTimeStep = runways[0].GetTimeStep();

		SpriteLights.Init(strobeTimeStep, globalBrightnessOffset, FOV, screenHeight);

		return strobeTimeStep;
	}
	//Procedurally crate the runway lights.
	public void CreateRunwayLights(){

		int index;

		//Create an array which holds every possible runway.
		RunwayData[] runways = new RunwayData[2];
		bool randomBrightness = false;
		float brightness = 0.8f; //0.6f
		float smallerLightSize = 0.7f;  //0.8f

		index = 0;
		runways[index] = new RunwayData();
		runways[index].SetThresholdPosition(new Vector3(0, 0, 0), 3000);
		runways[index].thresholdHeight[0] = 0;
		runways[index].thresholdHeight[1] = 0;
		runways[index].midHeight = 0;
		runways[index].SetThresholdRotation(0);
		runways[index].width = 45;
		runways[index].lightingType[0] = LightingType.ALSF2;
		runways[index].lightingType[1] = LightingType.ALSF2;
		runways[index].strobeType[0] = StrobeType.ODALS;
		runways[index].strobeType[1] = StrobeType.BOTH;
		runways[index].papiType[0] = PapiType.PAPIBOTH;
		runways[index].papiType[1] = PapiType.PAPIBOTH;
		runways[index].centerlineLights = true;
		runways[index].centerlineLightsSpacing = 15;
		runways[index].edgeLights = true;
		runways[index].edgeLightsSpacing = 60;
		runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
		runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
		runways[index].TDZ[0] = true;
		runways[index].TDZ[1] = true;

		index = 1;
		runways[index] = new RunwayData();
		runways[index].SetThresholdPosition(new Vector3(200, 0, 0), 3000);
		runways[index].thresholdHeight[0] = 0;
		runways[index].thresholdHeight[1] = 0;
		runways[index].midHeight = 0;
		runways[index].SetThresholdRotation(0);
		runways[index].width = 45;
		runways[index].lightingType[0] = LightingType.ALSF1;
		runways[index].lightingType[1] = LightingType.ALSF1;
		runways[index].strobeType[0] = StrobeType.BOTH;
		runways[index].strobeType[1] = StrobeType.BOTH;
		runways[index].papiType[0] = PapiType.PAPILEFT;
		runways[index].papiType[1] = PapiType.PAPILEFT;
		runways[index].centerlineLights = true;
		runways[index].centerlineLightsSpacing = 15;
		runways[index].edgeLights = true;
		runways[index].edgeLightsSpacing = 60;
		runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
		runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
		runways[index].TDZ[0] = true;
		runways[index].TDZ[1] = true;

		/*
		index = 2;
		runways[index] = new RunwayData();
		runways[index].SetThresholdPosition(new Vector3(400, 0, 0), 2500);
		runways[index].thresholdHeight[0] = 0;
		runways[index].thresholdHeight[1] = 0;
		runways[index].midHeight = 0;
		runways[index].SetThresholdRotation(0);
		runways[index].width = 40;
		runways[index].lightingType[0] = LightingType.SALS;
		runways[index].lightingType[1] = LightingType.SALS;
		runways[index].strobeType[0] = StrobeType.BOTH;
		runways[index].strobeType[1] = StrobeType.BOTH;
		runways[index].papiType[0] = PapiType.PAPILEFT;
		runways[index].papiType[1] = PapiType.PAPILEFT;
		runways[index].centerlineLights = false;
		runways[index].centerlineLightsSpacing = 15;
		runways[index].edgeLights = true;
		runways[index].edgeLightsSpacing = 60;
		runways[index].thresholdWingbar[0] = ThresholdWingbar.SMALL;
		runways[index].thresholdWingbar[1] = ThresholdWingbar.SMALL;
		runways[index].TDZ[0] = false;
		runways[index].TDZ[1] = false;

		index = 3;
		runways[index] = new RunwayData();
		runways[index].SetThresholdPosition(new Vector3(600, 0, 0), 3000);
		runways[index].thresholdHeight[0] = 0;
		runways[index].thresholdHeight[1] = 0;
		runways[index].midHeight = 0;
		runways[index].SetThresholdRotation(0);
		runways[index].width = 45;
		runways[index].lightingType[0] = LightingType.CALVERT2;
		runways[index].lightingType[1] = LightingType.CALVERT2;
		runways[index].strobeType[0] = StrobeType.NONE;
		runways[index].strobeType[1] = StrobeType.NONE;
		runways[index].papiType[0] = PapiType.PAPIBOTH;
		runways[index].papiType[1] = PapiType.PAPIBOTH;
		runways[index].centerlineLights = true;
		runways[index].centerlineLightsSpacing = 15;
		runways[index].edgeLights = true;
		runways[index].edgeLightsSpacing = 60;
		runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
		runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
		runways[index].TDZ[0] = true;
		runways[index].TDZ[1] = true;

		index = 4;
		runways[index] = new RunwayData();
		runways[index].SetThresholdPosition(new Vector3(800, 0, 0), 3000);
		runways[index].thresholdHeight[0] = 0;
		runways[index].thresholdHeight[1] = 0;
		runways[index].midHeight = 0;
		runways[index].SetThresholdRotation(0);
		runways[index].width = 45;
		runways[index].lightingType[0] = LightingType.CALVERT1;
		runways[index].lightingType[1] = LightingType.CALVERT1;
		runways[index].strobeType[0] = StrobeType.NONE;
		runways[index].strobeType[1] = StrobeType.NONE;
		runways[index].papiType[0] = PapiType.PAPIRIGHT;
		runways[index].papiType[1] = PapiType.PAPIRIGHT;
		runways[index].centerlineLights = true;
		runways[index].centerlineLightsSpacing = 15;
		runways[index].edgeLights = true;
		runways[index].edgeLightsSpacing = 60;
		runways[index].thresholdWingbar[0] = ThresholdWingbar.LARGE;
		runways[index].thresholdWingbar[1] = ThresholdWingbar.LARGE;
		runways[index].TDZ[0] = true;
		runways[index].TDZ[1] = true;
		*/

		//Get the strobe timestep variable.
		strobeTimeStep = InitRunwayLights(runways);

		//Create temporary lists to store the light data,.
		List<SpriteLights.LightData> directionalLightData = new List<SpriteLights.LightData>();
		List<SpriteLights.LightData> omnidirectionalLightData = new List<SpriteLights.LightData>();
		List<SpriteLights.LightData> strobeLightData = new List<SpriteLights.LightData>();
		List<SpriteLights.LightData> papiLightData = new List<SpriteLights.LightData>();

		ApproachLightData allApproachLightData = new ApproachLightData();		

		//Get the position and color of the lights from an svg file.
		allApproachLightData.StoreApproachLightData();

		//Loop through all runways.
		for(int i = 0; i < runways.Length; i++){
			
			//Create the light data and store in a temporary buffer.
			SetupApproachLights(ref directionalLightData, allApproachLightData, runways[i], randomBrightness, brightness, 1f);
			SetupTDZLights(ref directionalLightData, allApproachLightData, runways[i], randomBrightness, brightness, smallerLightSize);
			SetupStrobeLights(ref strobeLightData, allApproachLightData, runways[i], strobeTimeStep);
			SetupThresholdLights(ref directionalLightData, runways[i], false, 0.6f, 1f);
			SetupCenterlineLights(ref directionalLightData, runways[i], randomBrightness, brightness, smallerLightSize);
			SetupEdgeLights(ref omnidirectionalLightData, runways[i], randomBrightness, brightness, 1f);
			SetupPapiLights(ref papiLightData, runways[i], false);
		}

		//Create a parent object.
		GameObject parentObject = new GameObject("RunwayLights");

		//Take all the light data lists and create the actual ligth mesh from it.
		GameObject[] lightObjects = SpriteLights.CreateLights("Runway directional lights", directionalLightData.ToArray(), directionalLightsMat);
		MakeChild(parentObject, lightObjects);

		lightObjects = SpriteLights.CreateLights("Runway omnidirectional lights", omnidirectionalLightData.ToArray(), omnidirectionalRunwayLightsMat);
		MakeChild(parentObject, lightObjects);

		lightObjects = SpriteLights.CreateLights("Runway strobe lights", strobeLightData.ToArray(), strobeLightsMat);
		MakeChild(parentObject, lightObjects);

		lightObjects = SpriteLights.CreateLights("Runway PAPI lights", papiLightData.ToArray(), papiLightsMat);
		MakeChild(parentObject, lightObjects);

		parentObject.transform.position = new Vector3(-2941, 0, 10936);
		parentObject.transform.rotation = Quaternion.Euler(0, -111.5163f, 0);
	}
	//Setup all the papi lights.
	private void SetupPapiLights(ref List<SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness){

		for(int side = 0; side < 2; side++){

			if(runwayData.papiType[side] != PapiType.NONE){

				//Calculate the offset direction.
				Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[side]);
				Vector3 sideOffsetDir = Math3d.GetRightVector(runwayData.rotation[side]);
				Vector3 lengthEdgeOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, 337f);

				if((runwayData.papiType[side] == PapiType.PAPIRIGHT) || (runwayData.papiType[side] == PapiType.PAPIBOTH)){
			
					Vector3 startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f);
					Vector3 startPosition = runwayData.thresholdPosition[side] + startOffsetVec;
					Vector3 currentPosition = startPosition;

					Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f);

					for(int i = 0; i < 4; i++){

						SpriteLights.LightData data = new SpriteLights.LightData();

						float angle = GetPapiAngle(i);

						data.position = currentPosition;
						data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle);
						lightData.Add(data);

						currentPosition += sideOffsetVec;
					}
				}

				if((runwayData.papiType[side] == PapiType.PAPILEFT) || (runwayData.papiType[side] == PapiType.PAPIBOTH)){

					sideOffsetDir *= -1;

					Vector3 startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, (runwayData.width * 0.5f) + 15f);
					Vector3 startPosition = runwayData.thresholdPosition[side] + startOffsetVec;
					Vector3 currentPosition = startPosition;

					Vector3 sideOffsetVec = Math3d.SetVectorLength(sideOffsetDir, 9f);

					for(int i = 0; i < 4; i++){

						SpriteLights.LightData data = new SpriteLights.LightData();

						float angle = GetPapiAngle(i);

						data.position = currentPosition;
						data.rotation = runwayData.rotation[side] * Quaternion.Euler(Vector3.right * angle);
						lightData.Add(data);

						currentPosition += sideOffsetVec;
					}
				}
			}
		}
	}
	//Setup all the edge lights.
	private void SetupEdgeLights(ref List<SpriteLights.LightData> lightData, RunwayData runwayData, bool randomBrightness, float brightness, float size){

		float sideFactor = 0;

		//Calculate the amount of lights.
		int lightAmountInRow = (int)Mathf.Floor(runwayData.length / runwayData.edgeLightsSpacing);

		//Calculate the offset direction.
		Vector3 lengthOffsetDir = Math3d.GetForwardVector(runwayData.rotation[0]);
		Vector3 sideOffsetDir = Math3d.GetRightVector(runwayData.rotation[0]);

		//Calculate the start position.
		float rowLength = (lightAmountInRow - 1) * runwayData.edgeLightsSpacing;
		float edgeForwardOffset = (runwayData.length - rowLength) * 0.5f;

		Vector3 lengthEdgeOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, edgeForwardOffset);
		Vector3 startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(sideOffsetDir, runwayData.width * 0.5f);
		Vector3 startPosition = runwayData.thresholdPosition[0] + startOffsetVec;
		Vector3 currentPosition = startPosition;

		Vector3 lengthOffsetVec = Math3d.SetVectorLength(lengthOffsetDir, runwayData.edgeLightsSpacing);

		//Calculate the point where the lights should change color.
		float amberA = 600f + runwayData.edgeLightsSpacing;		
		float amberB = (runwayData.length - (600f + runwayData.edgeLightsSpacing));

		int doubleLightAmountInRow = lightAmountInRow * 2;

		for(int i = 0; i < doubleLightAmountInRow; i++){

			bool passedAmberA = false;
			bool passedAmberB = false;

			SpriteLights.LightData data = new SpriteLights.LightData();

			//Shift the current position for the other side.
			if(i == lightAmountInRow){

				startOffsetVec = lengthEdgeOffsetVec + Math3d.SetVectorLength(-sideOffsetDir, runwayData.width * 0.5f);
				currentPosition = runwayData.thresholdPosition[0] + startOffsetVec;

				//Reset flags.
				passedAmberA = false;
				passedAmberB = false;
				sideFactor = lightAmountInRow;
			}

			data.position = currentPosition;
			data.rotation = runwayData.rotation[0];

			//Calculate the distance to the threshold.
			float currentDistance = ((i - sideFactor) * runwayData.edgeLightsSpacing) + edgeForwardOffset;

			//The last 600 meter of the runway has red centerline lights.
			if(currentDistance <= amberA){

				data.frontColor = whiteLight;
				data.brightness = SetBrightness(randomBrightness, brightness);
				data.backColor = amberLight;

				passedAmberA = true;
			}

			//The last 300 meter of the runway has red centerline lights.
			if(currentDistance >= amberB){

				passedAmberB = true;

				data.frontColor = amberLight;
				data.brightness = SetBrightness(randomBrightness, brightness);
				data.backColor = whiteLight;
			}

			//Middle of the runway
			if(!passedAmberA && !passedAmberB){

				data.frontColor = whiteLight;
				data.brightness = SetBrightness(randomBrightness, brightness);
				data.backColor = whiteLight;
			}

			data.size = size;

			lightData.Add(data);

			currentPosition += lengthOffsetVec;
		}
	}