private void GenerateTunnelsAndLandscapeObjects(
			List<TrackData.RoadHelper> roadHelpers,
			List<TrackData.NeutralObject> neutralObjects,
			Landscape landscape)
        {
            #region Find out where the tunnels are
            // Go through all tunnel helpers along the road,
            // everything close enough (<25) is interessting for us.
            int helperStartedNum = -1;
            TrackData.RoadHelper.HelperType remType =
                TrackData.RoadHelper.HelperType.Reset;
            for (int num = 0; num < points.Count; num++)
            {
                Vector3 pos = points[num].pos;
                foreach (TrackData.RoadHelper roadHelper in roadHelpers)
                {
                    float dist = Vector3.Distance(roadHelper.pos, pos);
                    if (dist < 25.0f)
                    {
                        if (helperStartedNum >= 0)
                        {
                            helperPositions.Add(new RoadHelperPosition(
                                remType, helperStartedNum, num));
                            // Reset?
                            if (roadHelper.type == TrackData.RoadHelper.HelperType.Reset)
                                helperStartedNum = -1;
                            else
                            {
                                // Start new part
                                helperStartedNum = num;
                                remType = roadHelper.type;
                            } // else
                        } // if (helperStartedNum)
                        else
                        {
                            helperStartedNum = num;
                            remType = roadHelper.type;
                        } // else

                        // Remove this roadHelper (don't use it again)!
                        roadHelpers.Remove(roadHelper);
                        break;
                    } // if (dist)
                } // foreach (roadHelper)
            } // for (num)

            // Still a helper open? Then close it close before the end!
            if (helperStartedNum > 0)
                helperPositions.Add(new RoadHelperPosition(
                    remType, helperStartedNum, points.Count - 3));
            #endregion

            #region Copy over neutral objects for landscape rendering
            if (landscape != null)
            {
                for (int num = 0; num < neutralObjects.Count; num++)
                {
                    TrackData.NeutralObject obj = neutralObjects[num];
                    landscape.AddObjectToRender(obj.modelName, obj.matrix, false);
                } // for (num)
            } // if (landscape)
            #endregion
        }
        /// <summary>
        /// Create guard rail
        /// </summary>
        /// <param name="points">Points of the road itself</param>
        /// <param name="mode">Mode, left or right</param>
        /// <param name="landscape">Landscape</param>
        public GuardRail(List<TrackVertex> points, Modes mode,
			Landscape landscape)
        {
            #region Generate guardrail points
            // First generate a list of points at the side of the road where
            // we are going to generate all the guard rail vertices.
            // Note: We use only half as much points as points provides!
            railPoints = new TrackVertex[points.Count / 2 + 1];
            for (int num = 0; num < railPoints.Length; num++)
            {
                // Make sure we have a closed line, we might have to skip the
                // last points entry because we devided through 2.
                int pointNum = num * 2;
                if (pointNum >= points.Count - 1)
                    pointNum = points.Count - 1;

                // Just copy the points over and manipulate the position and the
                // right vector depending on which side of the guard rail we are
                // going to generate here.
                if (mode == Modes.Left)
                {
                    railPoints[num] = points[pointNum].LeftTrackVertex;
                    // Invert the direction and right vector for the left side
                    // This makes everything point in the other road direction!
                    railPoints[num].right = -railPoints[num].right;
                    railPoints[num].dir = -railPoints[num].dir;
                    // Move it a little inside the road
                    railPoints[num].pos -=
                        railPoints[num].right * InsideRoadDistance;
                } // if (mode)
                else
                {
                    railPoints[num] = points[pointNum].RightTrackVertex;
                    // Move it a little inside the road
                    railPoints[num].pos -=
                        railPoints[num].right * InsideRoadDistance;
                } // else
            } // for (num)
            #endregion

            #region Generate vertex buffer
            railVertices =
                new TangentVertex[railPoints.Length * GuardRailVertices.Length];

            // Current texture coordinate for the guardrail in our current direction.
            float uTexValue = 0.5f;
            float lastHolderGap = 0;//HolderGap;
            for (int num = 0; num < railPoints.Length; num++)
            {
                // The unit vectors for our local point space
                Vector3 right = railPoints[num].right;
                Vector3 dir = railPoints[num].dir;
                Vector3 up = railPoints[num].up;

                // Create the coordinate system for the current point by the 3 unit
                // vectors.
                Matrix pointSpace = Matrix.Identity;
                pointSpace.M11 = right.X;
                pointSpace.M12 = right.Y;
                pointSpace.M13 = right.Z;
                pointSpace.M21 = dir.X;
                pointSpace.M22 = dir.Y;
                pointSpace.M23 = dir.Z;
                pointSpace.M31 = up.X;
                pointSpace.M32 = up.Y;
                pointSpace.M33 = up.Z;

                Vector3 localPos = railPoints[num].pos;
                // Adjust the position for the guardrail, put it up a little.
                localPos += up * GuardRailHeight;

                // Set the beginning- or ending point for the guardrail around the
                // current spline position
                for (int i = 0; i < GuardRailVertices.Length; i++)
                {
                    // Transform each of our guardrail points by our local point space
                    // and translate it to our current position.
                    Vector3 pos = Vector3.Transform(
                        GuardRailVertices[i].pos * CorrectionScale,
                        pointSpace * Matrix.CreateTranslation(localPos));
                    // Also transform our normal and tangent data
                    Vector3 normal = Vector3.TransformNormal(
                        // Left side needs inverted normals (side is inverted)
                        (mode == Modes.Left ? -1 : 1) *
                        GuardRailVertices[i].normal,
                        pointSpace);
                    Vector3 tangent = Vector3.TransformNormal(
                        -GuardRailVertices[i].tangent,
                        //GuardRailVertices[i].normal,
                        //new Vector3(0, 0, -1),
                        pointSpace);

                    // Store vertex
                    railVertices[num * GuardRailVertices.Length + i] =
                        new TangentVertex(pos,
                        uTexValue, GuardRailVertices[i].V,
                        normal, tangent);
                } // for (int)

                // Distance of the current position to the next position
                float distance = Vector3.Distance(
                    railPoints[(num + 1) % railPoints.Length].pos, railPoints[num].pos);

                // Uniform calculation of the texture coordinates for the guardrail,
                // so it doesn't matter if there is a gap of 2 or 200 m
                // -> through "1 / HolderGap" we guarantee that the drilling
                //		(from the texture) is always set in the front of the pile,
                //		no matter which holder gap is set
                // Note: Only display a holder for every 3 texture loops.
                uTexValue += (1 / HolderGap) * distance * 2.0f;

                // Have we reach or go over the holder gap ?
                if (lastHolderGap - distance <= 0)
                {
                    // Catmull interpolation, instead the linear interpolation, for a
                    // better position calculation, especially in curves
                    Vector3 p1 =
                        railPoints[num - 1 < 0 ? railPoints.Length - 1 : num - 1].pos;
                    Vector3 p2 = railPoints[num].pos;
                    Vector3 p3 = railPoints[(num + 1) % railPoints.Length].pos;
                    Vector3 p4 = railPoints[(num + 2) % railPoints.Length].pos;

                    Vector3 holderPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                        lastHolderGap / distance);

                    // Store the calculated render matrix for this holder pile object
                    if (landscape != null &&
                        // Completely ignore all guard rails for ps1.1
                        // to save performance (few thousand objects per track less)
                        BaseGame.CanUsePS20 &&
                        BaseGame.HighDetail)
                        landscape.AddObjectToRender(
                            "GuardRailHolder",
                            // Fix scaling a little
                            //Matrix.CreateScale(0.9f) *
                            Matrix.CreateScale(1.125f) *
                            // First the translation to get the pile to the back of the
                            // guardrail and not in the middle
                            Matrix.CreateTranslation(HolderPileCorrectionVector) *
                            // the ordinary transformation to the current point space
                            pointSpace *
                            // at least we calculate to correct position where the pile
                            // reaches exactly the holder gap
                            Matrix.CreateTranslation(holderPoint),
                            // Optimize performance: Set this to false,
                            // but then we won't have shadows for the holder piles.
                            false);//true);

                    // We have just set a pile, the next pile will be set after
                    // reaching the next holder gap.
                    lastHolderGap += HolderGap;
                } // if (lastHolderGap)

                // The distance we have to cover until the next position.
                // We subtract our current distance from the remaining gap distance,
                // which will then be checked in the next loop.
                lastHolderGap -= distance;
            } // for (num)

            // Create the vertex buffer from our vertices.
            railVb = new VertexBuffer(
                BaseGame.Device,
                typeof(TangentVertex),
                railVertices.Length,
                ResourceUsage.WriteOnly,
                ResourceManagementMode.Automatic);
            railVb.SetData(railVertices);
            #endregion

            #region GenerateIndexBuffer
            // Count of quads (polygons) which creates the current guardrail segment
            int quadPolysPerStrip = GuardRailVertices.Length - 1;
            int[] indices =
                new int[(2 * 3 * quadPolysPerStrip) * (railPoints.Length - 1)];
            // Current vertex index
            int vertexIndex = 0;
            // Helper variable, current index of the indices list
            int indicesIndex = 0;
            for (int num = 0; num < railPoints.Length - 1; num++)
            {
                // Set all quads of the guardrail
                for (int j = 0; j < quadPolysPerStrip; j++)
                {
                    indicesIndex = 3 * 2 * (num * quadPolysPerStrip + j);

                    // 1. Polygon
                    indices[indicesIndex] = vertexIndex + j;
                    indices[indicesIndex + 1] = vertexIndex + 1 + j;
                    indices[indicesIndex + 2] =
                        vertexIndex + 1 + GuardRailVertices.Length + j;

                    // 2. Polygon
                    indices[indicesIndex + 3] = indices[indicesIndex + 2];
                    indices[indicesIndex + 4] =
                        vertexIndex + GuardRailVertices.Length + j;
                    indices[indicesIndex + 5] = indices[indicesIndex];
                } // for (int)

                vertexIndex += GuardRailVertices.Length;
            } // for (num)

            // Create the index buffer from our indices.
            railIb = new IndexBuffer(
                BaseGame.Device,
                typeof(int),
                indices.Length,
                ResourceUsage.WriteOnly,
                ResourceManagementMode.Automatic);
            railIb.SetData(indices);
            #endregion
        }
        private void GenerateObjectsForTrack(Landscape landscape)
        {
            #region Generate palms and laterns for the road
            // Auto generate palms and laterns at the side of our road.
            float lastGap = 0;//PalmAndLaternGap;
            int generatedNum = 0;
            for (int num = 0; num < points.Count; num++)
            {
                bool palms = false;
                bool laterns = false;

                // Check if there are any palms or laterns here
                foreach (RoadHelperPosition helper in helperPositions)
                    if (num >= helper.startNum &&
                        num <= helper.endNum)
                    {
                        if (helper.type == TrackData.RoadHelper.HelperType.Palms)
                            palms = true;
                        else if (helper.type == TrackData.RoadHelper.HelperType.Laterns)
                            laterns = true;
                    } // foreach if (helper.startNum)

                // No palms or laterns here?
                if (palms == false &&
                    laterns == false)
                    // Then skip
                    continue;

                // Distance of the current position to the next position
                float distance = Vector3.Distance(
                    points[(num + 1) % points.Count].pos, points[num].pos);

                // Have we reach or go over the holder gap ?
                if (lastGap - distance <= 0)
                {
                    // The unit vectors for our local point space
                    Vector3 right = points[num].right;
                    Vector3 dir = points[num].dir;
                    Vector3 up = points[num].up;

                    // Find out if this is a looping
                    bool upsideDown = up.Z < +0.05f;
                    bool movingUp = dir.Z > 0.65f;
                    bool movingDown = dir.Z < -0.65f;
                    if (upsideDown || movingUp || movingDown)
                        // Skip generation here!
                        continue;

                    // Create the coordinate system for the current point by the 3 unit
                    // vectors.
                    Matrix pointSpace = Matrix.Identity;
                    pointSpace.Right = right;
                    pointSpace.Up = dir;
                    pointSpace.Forward = -up;

                    // Catmull interpolation, instead the linear interpolation, for a
                    // better position calculation, especially in curves.
                    Vector3 p1 = points[num - 1 < 0 ? points.Count - 1 : num - 1].pos;
                    Vector3 p2 = points[num].pos;
                    Vector3 p3 = points[(num + 1) % points.Count].pos;
                    Vector3 p4 = points[(num + 2) % points.Count].pos;

                    Vector3 objPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                        lastGap / distance);

                    generatedNum++;

                    // Store the calculated render matrix for this holder pile object
                    if (landscape != null)
                    {
                        if (palms)
                        {
                            // Check height, skip palm generation if height is more than 11m
                            if (objPoint.Z -
                                landscape.GetMapHeight(objPoint.X, objPoint.Y) < 11)//15)
                            {
                                int randomNum = RandomHelper.GetRandomInt(4);
                                // Less propability for small palm
                                if (randomNum == 3)
                                    randomNum = RandomHelper.GetRandomInt(4);
                                landscape.AddObjectToRender(
                                    // Random palms
                                    randomNum == 0 ? "AlphaPalm" :
                                    randomNum == 1 ? "AlphaPalm2" :
                                    randomNum == 2 ? "AlphaPalm3" : "AlphaPalmSmall",
                                    // Scale them up a little
                                    Matrix.CreateScale(1.25f) *
                                    // Randomly rotate palms
                                    Matrix.CreateRotationZ(
                                    RandomHelper.GetRandomFloat(0, MathHelper.Pi * 2)) *
                                    // Put left/right
                                    Matrix.CreateTranslation(right *
                                        (generatedNum % 2 == 0 ? 0.6f : -0.6f) *
                                        points[num].roadWidth * TrackVertex.RoadWidthScale) *
                                    // Put below the landscape to make it stick to the ground
                                    Matrix.CreateTranslation(new Vector3(0, 0, -50)) *
                                    // the ordinary transformation to the current point space
                                    //unused: pointSpace *
                                    // And finally we calculate to correct position where the palm
                                    // reaches exactly the holder gap
                                    Matrix.CreateTranslation(objPoint),
                                    // Enable this for shadow map generation
                                    true);
                            } // if
                        } // if (palms)
                        else
                        {
                            landscape.AddObjectToRender(
                                // Random palms or laterns?
                                "Laterne",
                                // Rotate laterns fixed left/right
                                Matrix.CreateRotationZ(
                                generatedNum % 2 == 0 ? MathHelper.Pi : 0.0f) *
                                // Put left/right
                                Matrix.CreateTranslation(new Vector3(
                                    (generatedNum % 2 == 0 ? 0.5f : -0.5f) *
                                    points[num].roadWidth * TrackVertex.RoadWidthScale - 0.35f,
                                    0, -0.2f)) *
                                // the ordinary transformation to the current point space
                                pointSpace *
                                // At last we calculate to correct position where the latern
                                // reaches exactly the holder gap
                                Matrix.CreateTranslation(objPoint),
                                // Enable this for shadow map generation
                                true);
                        } // else
                    } // if (landscape)

                    // We have just set a pile, the next pile will be set after
                    // reaching the next holder gap.
                    lastGap += PalmAndLaternGap;
                } // if (lastHolderGap)

                // The distance we have to cover until the next position.
                // We subtract our current distance from the remaining gap distance,
                // which will then be checked in the next loop.
                lastGap -= distance;
            } // for (num)
            #endregion

            #region Generate signs and checkpoints
            // Add the goal and start light models always!
            if (landscape != null)
            {
                Vector3 startRight = points[0].right;
                Vector3 startDir = points[0].dir;
                Vector3 startUp = points[0].up;
                Matrix startPointSpace = Matrix.Identity;
                startPointSpace.Right = startRight;
                startPointSpace.Up = startDir;
                startPointSpace.Forward = -startUp;
                landscape.AddObjectToRender(
                    // Use SpeedyRacer banners
                    "Banner6",
                    // Scale them up to fit on the road
                    Matrix.CreateScale(points[0].roadWidth) *
                    // Scale up 1.1, but compensate 1.2f done in landscape.AddObject
                    Matrix.CreateScale(2.0f) *//1.051f) *
                    Matrix.CreateTranslation(new Vector3(0, -5.1f, 0)) *
                    // the ordinary transformation to the current point space
                    startPointSpace *
                    // Add the correct position where the goal is
                    Matrix.CreateTranslation(points[0].pos),
                    // Enable this for shadow map generation
                    true);
                landscape.AddObjectToRender(
                    // All 3 modes are handled and updated in BasePlayer class
                    "StartLight3",
                    Matrix.CreateScale(1.1f) *
                    // Put startlight 6 meters away, and on the right road side!
                    Matrix.CreateTranslation(new Vector3(
                    points[0].roadWidth * TrackVertex.RoadWidthScale * 0.50f - 0.3f,
                    6, -0.2f)) *
                    // the ordinary transformation to the current point space
                    startPointSpace *
                    // Add the correct position where the goal is
                    Matrix.CreateTranslation(points[0].pos),
                    // Enable this for shadow map generation
                    true);
            } // if (landscape)

            // Make sure we don't reuse any of the old checkpoint positions.
            checkpointSegmentPositions.Clear();

            // Auto generate checkpoints every 500 meters.
            lastGap = CheckpointGap;
            float signGap = SignGap;
            // Don't add another one near the end!
            for (int num = 0; num < points.Count - 24; num++)
            {
                // Distance of the current position to the next position
                float distance = Vector3.Distance(
                    points[(num + 1) % points.Count].pos, points[num].pos);

                // The unit vectors for our local point space
                Vector3 right = points[num].right;
                Vector3 dir = points[num].dir;
                Vector3 up = points[num].up;

                // Find out if this is a looping
                bool upsideDown = up.Z < +0.05f;
                bool movingUp = dir.Z > 0.65f;
                bool movingDown = dir.Z < -0.65f;
                if (upsideDown || movingUp || movingDown)
                    // Skip generation here!
                    continue;

                // Create the coordinate system for the current point by the 3 unit
                // vectors.
                Matrix pointSpace = Matrix.Identity;
                pointSpace.Right = right;
                pointSpace.Up = dir;
                pointSpace.Forward = -up;

                // Catmull interpolation, instead the linear interpolation, for a
                // better position calculation, especially in curves.
                Vector3 p1 = points[num - 1 < 0 ? points.Count - 1 : num - 1].pos;
                Vector3 p2 = points[num].pos;
                Vector3 p3 = points[(num + 1) % points.Count].pos;
                Vector3 p4 = points[(num + 2) % points.Count].pos;

                // Have we reach or go over the holder gap ?
                if (lastGap - distance <= 0 &&
                    landscape != null)
                {
                    Vector3 objPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                        lastGap / distance);

                    // Store the calculated render matrix for this holder pile object
                    int randomNum = RandomHelper.GetRandomInt(6);
                    landscape.AddObjectToRender(
                        // Random banners
                        randomNum == 0 ? "Banner" :
                        randomNum == 1 ? "Banner2" :
                        randomNum == 2 ? "Banner3" :
                        randomNum == 3 ? "Banner4" :
                        randomNum == 4 ? "Banner5" : "Banner6",
                        // Scale them up to fit on the road
                        Matrix.CreateScale(2.0f * points[num].roadWidth) *//points[num].roadWidth) *
                        Matrix.CreateTranslation(new Vector3(0, 0, -0.1f)) *
                        // the ordinary transformation to the current point space
                        pointSpace *
                        // And finally we calculate to correct position where the palm
                        // reaches exactly the holder gap
                        Matrix.CreateTranslation(objPoint),
                        // Enable this for shadow map generation
                        true);

                    // Remember this segment for easier checking later.
                    checkpointSegmentPositions.Add(num);

                    // We have just set a pile, the next pile will be set after
                    // reaching the next holder gap.
                    lastGap += CheckpointGap;
                } // if (lastHolderGap)
                else if (signGap - distance <= 0 &&
                    num >= 25 &&
                    landscape != null)
                {
                    Vector3 objPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                        signGap / distance);

                    // Find out how curvy this point is by going back 25 points.
                    Vector3 backPos = points[(num - 25) % points.Count].pos;
                    // Calculate virtualBackPos as if the road were straight
                    bool loopingAhead = points[(num + 60) % points.Count].up.Z < 0.15f;
                    // Calc angle
                    Vector3 angleVec = Vector3.Normalize(backPos - points[num].pos);
                    float roadAngle = Vector3Helper.GetAngleBetweenVectors(
                        angleVec,
                        Vector3.Normalize(-points[num].dir));
                    // If road goes to the left, use negative angle value!
                    if (Vector3.Distance(points[num].right, angleVec) <
                        Vector3.Distance(-points[num].right, angleVec))
                        roadAngle = -roadAngle;

                    // Now compare, if the backPos is more than 12 meters down,
                    // add a warning sign.
                    if (loopingAhead)//backPos.Z > virtualBackPos.Z + 20)
                    {
                        landscape.AddObjectToRender(
                            "SignWarning",
                            //Matrix.CreateRotationZ(-MathHelper.Pi/2.0f) *
                            // Put it on the right side
                            Matrix.CreateTranslation(new Vector3(
                            points[num].roadWidth * TrackVertex.RoadWidthScale * 0.5f - 0.1f,
                            0, -0.25f)) *
                            // the ordinary transformation to the current point space
                            pointSpace *
                            // And finally we calculate to correct position where the obj
                            // reaches exactly the holder gap
                            Matrix.CreateTranslation(objPoint),
                            // Enable this for shadow map generation
                            true);
                    } // if (backPos.Z)
                    // Else check if the angle less than -24 degrees (pi/7.5)
                    else if (roadAngle < -MathHelper.Pi / 7.5f)
                    {
                        // Show right road sign
                        landscape.AddObjectToRender(
                            "SignCurveRight",
                            Matrix.CreateRotationZ(MathHelper.Pi / 2.0f) *
                            // Put it on the left side
                            Matrix.CreateTranslation(new Vector3(
                            -points[num].roadWidth * TrackVertex.RoadWidthScale * 0.5f - 0.15f,
                            0, -0.25f)) *
                            // the ordinary transformation to the current point space
                            pointSpace *
                            // And finally we calculate to correct position where the obj
                            // reaches exactly the holder gap
                            Matrix.CreateTranslation(objPoint),
                            // Enable this for shadow map generation
                            true);
                    } // else if
                    // Same for other side
                    else if (roadAngle > MathHelper.Pi / 7.5f)
                    {
                        // Show right road sign
                        landscape.AddObjectToRender(
                            "SignCurveLeft",
                            Matrix.CreateRotationZ(-MathHelper.Pi / 2.0f) *
                            // Put it on the right side
                            Matrix.CreateTranslation(new Vector3(
                            points[num].roadWidth * TrackVertex.RoadWidthScale * 0.5f - 0.15f,
                            0, -0.25f)) *
                            // the ordinary transformation to the current point space
                            pointSpace *
                            // And finally we calculate to correct position where the obj
                            // reaches exactly the holder gap
                            Matrix.CreateTranslation(objPoint),
                            // Enable this for shadow map generation
                            true);
                    } // else if
                    // Also generate banner signs if roadAngle is at least 18 degrees
                    else if (roadAngle < -MathHelper.Pi / 10.0f ||
                        roadAngle > MathHelper.Pi / 10.0f ||
                        // Randomly generate sign
                        RandomHelper.GetRandomInt(9) == 4)
                    {
                        // Also mix in random curve signs, this is still a curve
                        int rndValue = RandomHelper.GetRandomInt(3);
                        // Randomize again if not that curvy here
                        if (rndValue == 0 &&
                            Math.Abs(roadAngle) < MathHelper.Pi / 24)
                            rndValue = RandomHelper.GetRandomInt(3);
                        else if (Math.Abs(roadAngle) < MathHelper.Pi / 20 &&
                            RandomHelper.GetRandomInt(2) == 1)
                            roadAngle *= -1;

                        // Show right road sign
                        landscape.AddObjectToRender(
                            rndValue == 0 ?
                            (roadAngle > 0 ? "SignCurveLeft" : "SignCurveRight") :
                            (rndValue == 1 ? "Sign" : "Sign2"),
                            Matrix.CreateRotationZ(
                            (roadAngle > 0 ? -1 : 1) * MathHelper.Pi / 2.0f) *
                            // Put it on the left side
                            Matrix.CreateTranslation(new Vector3(
                            (roadAngle > 0 ? 1 : -1) *
                            points[num].roadWidth * TrackVertex.RoadWidthScale * 0.5f -
                            (rndValue == 0 ? 0.15f : 0.005f),
                            0, -0.25f)) *
                            // the ordinary transformation to the current point space
                            pointSpace *
                            // And finally we calculate to correct position where the obj
                            // reaches exactly the holder gap
                            Matrix.CreateTranslation(objPoint),
                            // Enable this for shadow map generation
                            true);
                    } // else if

                    // We have just set a sign (or not), check for next sign after gap.
                    signGap += SignGap;
                } // else if

                // The distance we have to cover until the next position.
                // We subtract our current distance from the remaining gap distance,
                // which will then be checked in the next loop.
                lastGap -= distance;
                signGap -= distance;
            } // for (num)
            #endregion

            #region Add random landscape objects to fill our level up
            // Randomly generate, but don't collide with existing objects
            // or the track!
            for (int num = 0; num < points.Count; num += 2)
            {
                if (landscape != null)
                {
                    // Get landscape height here
                    float landscapeHeight =
                        landscape.GetMapHeight(points[num].pos.X, points[num].pos.Y);

                    // Skip object generation at great heights!
                    if (points[num].pos.Z - landscapeHeight > 60.0f)
                        continue;
                } // if

                // The unit vectors for our local point space
                Vector3 right = points[num].right;
                Vector3 dir = points[num].dir;
                Vector3 up = points[num].up;

                // Find out if this is a looping
                bool upsideDown = up.Z < +0.05f;
                bool movingUp = dir.Z > 0.65f;
                bool movingDown = dir.Z < -0.65f;
                if (upsideDown || movingUp || movingDown)
                    // Skip generation here!
                    continue;

                // Reduce number of landscape objects dramatically if not using
                // highest game settings.
                int randomMaxPropability =
                    BaseGame.CanUsePS30 ? 2 ://3 : //6 :
                    BaseGame.CanUsePS20 ? 5 : //9 :
                    9;//13;
                // Reduce to half as much objects if high detail is off.
                if (BaseGame.HighDetail == false)
                    randomMaxPropability *= 2;

                // Generate stuff in 20% of the cases
                if (RandomHelper.GetRandomInt(randomMaxPropability) == 0 &&
                    landscape != null)
                {
                    // Get random name
                    int randomObjNum = RandomHelper.GetRandomInt(
                        landscape.autoGenerationNames.Length);

                    // If above 4, generate again
                    if (randomObjNum >= 4)
                        randomObjNum = RandomHelper.GetRandomInt(
                            landscape.autoGenerationNames.Length);

                    // Don't generate so many casinos
                    if (randomObjNum == landscape.autoGenerationNames.Length-1 &&
                        RandomHelper.GetRandomInt(3) < 2)
                        randomObjNum = RandomHelper.GetRandomInt(
                            landscape.autoGenerationNames.Length);

                    // Ok, generate
                    float distance = RandomHelper.GetRandomFloat(26, 88);//33, 88);
                    // For casinos make sure the object is far enough away.
                    if (randomObjNum == landscape.autoGenerationNames.Length - 1)
                        distance += 20;
                    bool side = RandomHelper.GetRandomInt(2) == 0;
                    float rotation = RandomHelper.GetRandomFloat(0, MathHelper.Pi * 2);
                    landscape.AddObjectToRender(
                        landscape.autoGenerationNames[randomObjNum],
                        rotation,
                        points[num].pos,
                        points[num].right, distance * (side ? 1 : -1));
                } // if (RandomHelper.GetRandomInt)
            } // for (num)
            #endregion
        }
 /// <summary>
 /// Add all models
 /// </summary>
 /// <param name="landscape">Landscape</param>
 /// <param name="parentMatrix">Parent matrix</param>
 public void AddAllModels(Landscape landscape, Matrix parentMatrix)
 {
     // Just add all models in our combi
     foreach (CombiObject obj in objects)
         landscape.AddObjectToRender(obj.modelName,
             obj.matrix * parentMatrix, false);
 }