/// <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);
 }
Exemple #2
0
        /// <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,
                BufferUsage.WriteOnly);
            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,
                BufferUsage.WriteOnly);
            railIb.SetData(indices);
            #endregion
        }
        /// <summary>
        /// Create track columns
        /// </summary>
        /// <param name="points">Points</param>
        /// <param name="landscape">Landscape for getting the ground height</param>
        public TrackColumns(List<TrackVertex> points, Landscape landscape)
        {
            if (landscape == null)
                return;

            #region Find out column positions
            float lastColumnsDistance = ColumnsDistance;
            List<Matrix> columnPointSpacesTop = new List<Matrix>();
            List<Matrix> columnPointSpacesBottom = new List<Matrix>();
            for (int num = 0; num < points.Count; num++)
            {
                // Distance of the current position to the next position
                float distance = Vector3.Distance(
                    points[(num + 1) % points.Count].pos, points[num].pos);

                // Uniform calculation of the distance for the columns,
                // so it doesn't matter if there is a gap of 2 or 200 m
                // Have we reach or go over the ColumnsDistance?
                if (lastColumnsDistance - distance <= 0)
                {
                    // 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 holderPoint = Vector3.CatmullRom(p1, p2, p3, p4,
                        lastColumnsDistance / distance);

                    // Just find out how much this point is pointing up
                    float draft = Vector3.Dot(points[num].up, new Vector3(0, 0, 1));
                    // And don't add if height is too small!
                    float columnHeight = holderPoint.Z -
                        landscape.GetMapHeight(holderPoint.X, holderPoint.Y);

                    // Store the position for this holder
                    if (draft > 0.3f &&//< 0 MaxColumnGenerationAngel &&
                        columnHeight > MinimumColumnHeight)
                    {
                        columnPositions.Add(holderPoint);

                        // The unit vectors for our local point space
                        Vector3 right = points[num].right;
                        Vector3 dir = points[num].dir;
                        Vector3 up = points[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;

                        // Remember point space
                        columnPointSpacesTop.Add(pointSpace);

                        // Same for bottom, but don't use up vector (let it stay default)
                        pointSpace = Matrix.Identity;
                        Vector3 upVector = new Vector3(0, 0, 1);
                        // Rebuild right vector (to make it 90 degree to our up vector)
                        Vector3 rightVector = Vector3.Cross(dir, upVector);
                        pointSpace.M11 = rightVector.X;
                        pointSpace.M12 = rightVector.Y;
                        pointSpace.M13 = rightVector.Z;
                        pointSpace.M21 = dir.X;
                        pointSpace.M22 = dir.Y;
                        pointSpace.M23 = dir.Z;
                        columnPointSpacesBottom.Add(pointSpace);
                    }

                    // We have just set a pile, the next pile will be set after
                    // reaching the next holder gap.
                    lastColumnsDistance += ColumnsDistance;
                }

                // 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.
                lastColumnsDistance -= distance;
            }
            #endregion

            #region Generate vertex buffer
            columnVertices = new TangentVertex[
                columnPositions.Count * BaseColumnVertices.Length * 2];

            // Go through all columns
            for (int num = 0; num < columnPositions.Count; num++)
            {
                Vector3 pos = columnPositions[num];

                // Find out the current landscape height here
                Vector3 bottomPos = new Vector3(pos.X, pos.Y,
                    landscape.GetMapHeight(pos.X, pos.Y) +
                    ColumnGroundHeight);
                Vector3 topPos = new Vector3(pos.X, pos.Y,
                    pos.Z - TopColumnSubHeight);
                // Calculate top v tex coord for this column
                float topTexV =
                    Vector3.Distance(topPos, bottomPos) / (MathHelper.Pi * 2);

                // Use the BaseColumnVertices twice, once for the bottom and then for the
                // top part of our generated column.
                for (int topBottom = 0; topBottom < 2; topBottom++)
                {
                    // Go to all BaseColumnVertices
                    for (int i = 0; i < BaseColumnVertices.Length; i++)
                    {
                        int vertIndex = num * BaseColumnVertices.Length * 2 +
                            topBottom * BaseColumnVertices.Length + i;

                        // For the top positions, modify them them to fit directly
                        // on the bottom side of our road. Same for bottom, but don't
                        // modify the z value
                        Matrix transformMatrix = topBottom == 0 ?
                            columnPointSpacesBottom[num] : columnPointSpacesTop[num];

                        // We don't have to transform the vertices much, just adjust
                        // the z value and the v tex coord.
                        columnVertices[vertIndex] =
                            new TangentVertex(
                            (topBottom == 0 ? bottomPos : topPos) +
                            Vector3.Transform(BaseColumnVertices[i].pos,
                                transformMatrix),
                            BaseColumnVertices[i].U, topBottom == 0 ? 0 : topTexV,
                            Vector3.Transform(BaseColumnVertices[i].normal,
                                transformMatrix),
                            Vector3.Transform(-BaseColumnVertices[i].tangent,
                            transformMatrix));
                    }
                }

                // Also add the bottom position to the list of holders we want
                // to render later.
                if (landscape != null &&
                    // This is not really required, we can easily optimize this out.
                    BaseGame.HighDetail)
                    landscape.AddObjectToRender(
                        "RoadColumnSegment",
                        new Vector3(bottomPos.X, bottomPos.Y,
                        bottomPos.Z - ColumnGroundHeight));
            }

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

            #region GenerateIndexBuffer
            // Count of quads (polygons) we have for each column
            int quadPolysPerColumn = BaseColumnVertices.Length - 1;
            int[] indices =
                new int[(2 * 3 * quadPolysPerColumn) * columnPositions.Count];
            // Current vertex index
            int vertexIndex = 0;
            // Helper variable, current index of the indices list
            int indicesIndex = 0;
            for (int num = 0; num < columnPositions.Count; num++)
            {
                // Set all quads of the column
                for (int j = 0; j < quadPolysPerColumn; j++)
                {
                    indicesIndex = 3 * 2 * (num * quadPolysPerColumn + j);

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

                    // 2. Polygon
                    indices[indicesIndex + 3] = indices[indicesIndex + 1];
                    indices[indicesIndex + 4] = indices[indicesIndex];
                    indices[indicesIndex + 5] =
                        vertexIndex + BaseColumnVertices.Length + j;
                }

                // Go to next column
                vertexIndex += BaseColumnVertices.Length * 2;
            }

            // Create the index buffer from our indices.
            // fix
            //columnIb = new IndexBuffer(
            //    BaseGame.Device,
            //    typeof(int),
            //    indices.Length,
            //    ResourceUsage.WriteOnly,
            //    ResourceManagementMode.Automatic);
            columnIb = new IndexBuffer(
                BaseGame.Device,
                typeof(int),
                indices.Length,
                BufferUsage.WriteOnly);
            columnIb.SetData(indices);
            #endregion
        }
Exemple #4
0
        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>
		/// Initializes and loads some content, previously referred to as the
		/// "car stuff".
		/// </summary>
		private void LoadResources()
		{
			LoadEvent("Models...", null);
			// Load models
			carModel = new Model("Car");
			carSelectionPlate = new Model("CarSelectionPlate");

			LoadEvent("Landscape...", null);
			// Load landscape
			landscape = new Landscape(Level.Beginner);

			LoadEvent("Textures...", null);
			// Load textures, first one is grabbed from the imported one through
			// the car.x model, the other two are loaded seperately.
			carTextures = new Texture[3];
			carTextures[0] = new Texture("RacerCar");
			carTextures[1] = new Texture("RacerCar2");
			carTextures[2] = new Texture("RacerCar3");
			colorSelectionTexture = new Texture("ColorSelection");
			brakeTrackMaterial = new Material("track");

			LoadEvent("All systems go!", null);
			Thread.Sleep(1000);
		}
Exemple #6
0
        /// <summary>
        /// Load
        /// </summary>
        /// <param name="inputPoints">Input points</param>
        /// <param name="widthHelpers">Width helpers</param>
        /// <param name="roadHelpers">Road helpers</param>
        /// <param name="neutralObjects">Neutral objects</param>
        /// <param name="landscape">Landscape</param>
        protected void Load(Vector3[] inputPoints,
			List<TrackData.WidthHelper> widthHelpers,
			List<TrackData.RoadHelper> roadHelpers,
			List<TrackData.NeutralObject> neutralObjects,
			Landscape landscape)
        {
            #region Kill all previously loaded data
            points.Clear();
            helperPositions.Clear();

            // Kill all loaded objects
            if (landscape != null)
                landscape.KillAllLoadedObjects();
            #endregion

            #region Make sure we got valid data
            if (inputPoints == null ||
                inputPoints.Length < 3)
                throw new ArgumentException("inputPoints is invalid, we need at "+
                    "least 3 valid input points to generate a TrackLine.");
            #endregion

            #region Check if all points are ABOVE the landscape
            if (landscape != null)
            {
                // Go through all spline points
                for (int num = 0; num < inputPoints.Length; num++)
                {
                    // Get landscape height here
                    float landscapeHeight = landscape.GetMapHeight(
                        inputPoints[num].X, inputPoints[num].Y) +
                        // add little to fix ground errors
                        MinimumLandscapeDistance * 2.25f;

                    // And make sure we are always above it!
                    if (inputPoints[num].Z < landscapeHeight)
                        inputPoints[num].Z = landscapeHeight;
                } // for (num)

                // Second pass, check 24 interpolation points between all inputPoints
                for (int num = 0; num < inputPoints.Length; num++)
                    for (int iter = 1; iter < 25; iter++)
              {
                        float iterPercent = iter / 25.0f;

                        float iterHeight = inputPoints[num].Z * (1 - iterPercent) +
                            inputPoints[(num + 1) % inputPoints.Length].Z * iterPercent;

                        // Check 2x2 points (in all directions) to make sure
                        // we don't go through the landscape at the sides
                        for (int x = 0; x < 2; x++)
                            for (int y = 0; y < 2; y++)
                            {
                                // Also get height at middle to next pos
                                float landscapeHeight = landscape.GetMapHeight(
                                    -5.0f + 10.0f * x +
                                    inputPoints[num].X * (1 - iterPercent) +
                                    inputPoints[(num + 1) % inputPoints.Length].X * iterPercent,
                                    -5.0f + 10.0f * y +
                                    inputPoints[num].Y * (1 - iterPercent) +
                                    inputPoints[(num + 1) % inputPoints.Length].Y * iterPercent)+
                                    // add little to fix ground errors
                                    MinimumLandscapeDistance * 1.6f;// 1.5f;//1.25f;

                                // Increase both positions if this point is under the landscape
                                if (iterHeight < landscapeHeight)
                                {
                                    float increaseHeight = landscapeHeight - iterHeight;
                                    inputPoints[num].Z += increaseHeight;
                                    inputPoints[(num + 1) % inputPoints.Length].Z +=
                                        increaseHeight;
                                } // if (iterHeight)
                            } // for
              } // for for (iter)
            } // if (landscape)
            //Log.Write("Input points: " + StringHelper.WriteArrayData(inputPoints));
            #endregion

            #region Search for any loopings indicated by 2 points above each other
            // Go through all spline points (ignore first and last 3, this
            // makes it easier to remove points and add new ones).
            for (int num = 1; num < inputPoints.Length-3; num++)
            {
                // X/Y distance has to be 4 times smaller than Z distance
                Vector3 distVec = inputPoints[num + 1] - inputPoints[num];
                float xyDist = (float)Math.Sqrt(
                    distVec.X*distVec.X+distVec.Y*distVec.Y);
                float zDist = Math.Abs(distVec.Z);
                // Also check if next point is down again.
                Vector3 distVec2 = inputPoints[num + 2] - inputPoints[num + 1];
                if (zDist / 2 > xyDist &&
                    Math.Abs(distVec.Z + distVec2.Z) < zDist / 2)
                {
                    // Find out which direction we are going
                    Vector3 dir = inputPoints[num] - inputPoints[num - 1];
                    dir.Normalize();
                    Vector3 upVec = new Vector3(0, 0, 1);
                    Vector3 rightVec = Vector3.Cross(dir, upVec);
                    // Matrix build helper matrix to rotate our looping points
                    Matrix rotMatrix = new Matrix(
                        rightVec.X, rightVec.Y, rightVec.Z, 0,
                        dir.X, dir.Y, dir.Z, 0,
                        upVec.X, upVec.Y, upVec.Z, 0,
                        0, 0, 0, 1);

                    // Ok do a looping with zDist as height.
                    // Start with the current point, loop around and end with the
                    // point after the looping. We will remove the current and the
                    // next 2 points, but add 9 new points instead for our smooth loop.
                    // See LoopingPoints for the looping itself.
                    Vector3 startLoopPos = inputPoints[num];
                    Vector3 endLoopPos = inputPoints[num + 2];

                    // Insert 7 new points (9 new points, but we reuse
                    // start, middle and end points which are num, num+1 and num+2,
                    // plus an additional point after the looping to keep the road
                    // straight!)
                    Vector3[] remInputPoints = (Vector3[])inputPoints.Clone();
                    inputPoints = new Vector3[inputPoints.Length + 7];
                    // Copy everything over
                    for (int copyNum = 0; copyNum < remInputPoints.Length; copyNum++)
                        if (copyNum < num)
                            inputPoints[copyNum] = remInputPoints[copyNum];
                        else
                            inputPoints[copyNum + 7] = remInputPoints[copyNum];

                    // Ok, now we can add our loop
                    for (int loopNum = 0; loopNum < LoopingPoints.Length; loopNum++)
                    {
                        // Interpolate between start and end pos to land at the end pos!
                        float loopPercent = loopNum / (float)(LoopingPoints.Length - 1);
                        inputPoints[num + loopNum] =
                            startLoopPos * (1 - loopPercent) +
                            endLoopPos * loopPercent +
                            zDist * Vector3.Transform(LoopingPoints[loopNum], rotMatrix);
                    } // for (loopNum)

                    // Add extra point to keep the road straight
                    Vector3 newRoadDir =
                        inputPoints[num + 10] - inputPoints[num + 8];
                    // Don't go more than zDist * 2 units away!
                    if (newRoadDir.Length() > zDist * 2)
                    {
                        newRoadDir.Normalize();
                        newRoadDir = newRoadDir * zDist;
                        inputPoints[num + 9] = inputPoints[num + 8] + newRoadDir;
                    } // if (newRoadDir.Length)
                    else
                        // Just add an interpolation point
                        inputPoints[num + 9] =
                            (inputPoints[num + 8] + inputPoints[num + 10])/2.0f;

                    // Advance 10 points until we check for the next loop
                    num += 10;

                    // That's it, good work everyone ^^
                } // if (zDist)
            } // for (num)
            #endregion

            #region Generate all points with help of catmull rom splines
            // Generate all points with help of catmull rom splines
            for (int num = 0; num < inputPoints.Length; num++)
            {
                // Get the 4 required points for the catmull rom spline
                Vector3 p1 = inputPoints[num-1 < 0 ? inputPoints.Length-1 : num-1];
                Vector3 p2 = inputPoints[num];
                Vector3 p3 = inputPoints[(num + 1) % inputPoints.Length];
                Vector3 p4 = inputPoints[(num + 2) % inputPoints.Length];

                // Calculate number of iterations we use here based
                // on the distance of the 2 points we generate new points from.
                float distance = Vector3.Distance(p2, p3);
                int numberOfIterations =
                    (int)(NumberOfIterationsPer100Meters * (distance / 100.0f));
                if (numberOfIterations <= 0)
                    numberOfIterations = 1;

                Vector3 lastPos = p1;
                for (int iter = 0; iter < numberOfIterations; iter++)
                {
                    TrackVertex newVertex = new TrackVertex(
                        Vector3.CatmullRom(p1, p2, p3, p4,
                        iter / (float)numberOfIterations));

                    /*sucks, too bumpy!
                    // Warning: Can make the road too bumpy, for that reason we smooth!
                    // Get landscape height here
                    if (landscape != null)
                    {
                        float landscapeHeight = landscape.GetMapHeight(
                            newVertex.pos.X, newVertex.pos.Y) +
                            MinimumLandscapeDistance;

                        // Check if point is ABOVE the landscape!
                        if (newVertex.pos.Z < landscapeHeight)
                            newVertex.pos.Z = //landscapeHeight;
                                lastPos.Z * 0.9f + newVertex.pos.Z * 0.1f;

                        lastPos = newVertex.pos;
                        if (lastPos.Z < landscapeHeight)
                            lastPos.Z = landscapeHeight;
                    } // if (landscape)
                    else
                    //*/
                        lastPos = newVertex.pos;

                    points.Add(newVertex);
                } // for (iter)
            } // for (num)
            #endregion

            #region Generate up vectors, very important for our road building
            // Pre up vectors are used to first generate all optimal up vectors
            // for the track, but this is not useful for driving because we need
            // the road to point up always except for loopings.
            List<Vector3> preUpVectors = new List<Vector3>();

            // Now generate all up vectors, first pass does optimal up vectors.
            Vector3 defaultUpVec = new Vector3(0, 0, 1);
            Vector3 lastUpVec = defaultUpVec;
            for (int num = 0; num < points.Count; num++)
            {
                // Get direction we are driving in at this point,
                // interpolate with help of last and next points.
                Vector3 dir = points[(num + 1) % points.Count].pos -
                    points[num - 1 < 0 ? points.Count - 1 : num - 1].pos;
                dir.Normalize();

                // Now calculate the optimal up vector for this point
                Vector3 middlePoint = (points[(num + 1) % points.Count].pos +
                    points[num - 1 < 0 ? points.Count - 1 : num - 1].pos) / 2.0f;
                Vector3 optimalUpVector = middlePoint - points[num].pos;
                if (optimalUpVector.Length() < 0.0001f)
                    optimalUpVector = lastUpVec;
                optimalUpVector.Normalize();

                // Store the optimalUpVectors in the preUpVectors list
                preUpVectors.Add(optimalUpVector);

                // Also save dir vector
                points[num].dir = dir;

                // And remember the last upVec in case the road is going straight ahead
                lastUpVec = optimalUpVector;
            } // for (num)

            // Interpolate the first up vector for a smoother road at the start pos
            preUpVectors[0] = preUpVectors[preUpVectors.Count - 1] + preUpVectors[1];
            preUpVectors[0].Normalize();
            #endregion

            #region Interpolate the up vectors and also add the dir and right vectors
            // Second pass, interpolated precalced values and apply our logic :)
            //preUpVectors[0] =
            lastUpVec = Vector3.Lerp(defaultUpVec, preUpVectors[0],
                1.5f * CurveFactor * UpFactorCorrector);
            //lastUpVec = preUpVectors[0];
            Vector3 lastUpVecUnmodified = lastUpVec;// defaultUpVec;
            Vector3 lastRightVec = Vector3.Zero;
            for (int num = 0; num < points.Count; num++)
            {
                // Grab dir vector (could be calculated here too)
                Vector3 dir = points[num].dir;

                // First of all interpolate the preUpVectors
                Vector3 upVec =
                    //single input: preUpVectors[num];
                    Vector3.Zero;
                for (int smoothNum = -NumberOfUpSmoothValues / 2;
                    smoothNum <= NumberOfUpSmoothValues / 2; smoothNum++)
                    upVec +=
                        preUpVectors[(num + points.Count + smoothNum) % points.Count];
                upVec.Normalize();

                // Find out if this road piece is upside down and if we are
                // moving up or down. This is VERY important for catching loopings.
                bool upsideDown = upVec.Z < -0.25f &&
                    lastUpVecUnmodified.Z < -0.05f;
                bool movingUp = dir.Z > 0.75f;
                bool movingDown = dir.Z < -0.75f;

                //float changeAngle2 =
                //  GetAngleBetweenVectors(lastUpVec, upVec);
                //if (num < 100)
                //  Log.Write("changeAngel2=" + changeAngle2);

                // Mix in the last vector to make curves weaker
                upVec = Vector3.Lerp(lastUpVec, upVec, CurveFactor);
                upVec.Normalize();
                // Store the last value to check for loopings.
                lastUpVecUnmodified = upVec;

                // Don't mix in default up if we head up or are upside down!
                // Its very useful to know if we move up or down to fix the
                // problematic areas at loopings by pointing stuff correct right away.
                if (movingUp)
                    lastUpVec = Vector3.Lerp(upVec, -defaultUpVec, UpFactorCorrector);
                else if (movingDown)
                    lastUpVec = Vector3.Lerp(upVec, defaultUpVec, UpFactorCorrector);
                else if (upsideDown)
                    lastUpVec = Vector3.Lerp(upVec, -defaultUpVec, UpFactorCorrector);
                else
                    lastUpVec = Vector3.Lerp(upVec, defaultUpVec, UpFactorCorrector);

                // If we are very close to the ground, make the road point up more!
                if (//upsideDown == false &&
                    landscape != null)
                {
                    // Get landscape height here
                    float landscapeHeight = landscape.GetMapHeight(
                        points[num].pos.X, points[num].pos.Y);

                    // If point is close to the landscape, let everything point up more
                    if (points[num].pos.Z - landscapeHeight <
                        MinimumLandscapeDistance * 4)
                        lastUpVec = Vector3.Lerp(upVec, defaultUpVec,
                            1.75f * UpFactorCorrector);
                } // if (upsideDown == false &&)

                // And finally calculate rightVectors with just a cross product.
                // Used to render the track later.
                Vector3 rightVec = Vector3.Cross(dir, upVec);
                rightVec.Normalize();
                points[num].right = rightVec;

                //*tst
                // Recalculate up vector with help of right and dir.
                // This makes the up vector to always point up 90 degrees.
                upVec = Vector3.Cross(rightVec, dir);
                upVec.Normalize();
                points[num].up = upVec;
                //*/

                //// Make sure we never rotate the road more than a few degrees
                //if (lastRightVec.Length() > 0)
                //{
                //  float changeAngle =
                //    GetAngleBetweenVectors(lastRightVec, rightVec);
                //  if (num < 100)
                //    Log.Write("changeAngel=" + changeAngle);
                //} // if (lastRightVec.Length)

                //// Remember right vec for comparison in the next frame.
                //lastRightVec = rightVec;
            } // for (num)
            #endregion

            #region Smooth up vectors!
            lastUpVec = points[0].up;
            for (int num = 0; num < points.Count; num++)
                preUpVectors[num] = points[num].up;
            for (int num = 0; num < points.Count; num++)
            {
                // Interpolate up vectors again
                Vector3 upVec = Vector3.Zero;
                for (int smoothNum = -NumberOfUpSmoothValues;
                    smoothNum <= NumberOfUpSmoothValues; smoothNum++)
                {
                    upVec +=
                        preUpVectors[(num + points.Count + smoothNum) % points.Count];
                } // for (smoothNum)
                upVec.Normalize();
                points[num].up = upVec;

                // Also rebuild right vector
                Vector3 dir = points[num].dir;
                points[num].right = Vector3.Cross(dir, upVec);

                /*suxx
                // Grab dir and up vector
                Vector3 dir = points[num].dir;
                Vector3 upVec = points[num].up;
                /*suxx
                // Compare with previous up vector
                float changeAngle =
                    GetAngleBetweenVectors(lastUpVec, upVec);
                /*tst
                bool upsideDown = upVec.Z < -0.25f &&
                    lastUpVecUnmodified.Z < -0.05f;
                bool movingUp = dir.Z > 0.75f;
                bool movingDown = dir.Z < -0.75f;
                lastUpVecUnmodified = upVec;
                if (Math.Abs(changeAngle) > 0.02f &&
                    upsideDown == false &&
                    movingUp == false &&
                    movingDown == false)
                {
                    points[num].up = Vector3.SmoothStep(lastUpVec, upVec, 0.33f);//.25f);
                    // Also rebuild right vector
                    points[num].right = Vector3.Cross(dir, points[num].up);
                } // if (Math.Abs)
                 */
                /*suxx
                //if (Math.Abs(changeAngle) > 0.02f)
                {
                    points[num].up = Vector3.SmoothStep(lastUpVec, upVec, 0.05f);//.25f);
                    // Also rebuild right vector
                    points[num].right = Vector3.Cross(dir, points[num].up);
                } // if (Math.Abs)
                lastUpVec = upVec;
                 */
                //if (num < 100)
                //  Log.Write("changeAngel=" + changeAngle);
            } // for (num)
            #endregion

            AdjustRoadWidths(widthHelpers);

            GenerateUTextureCoordinates();

            GenerateTunnelsAndLandscapeObjects(
                roadHelpers, neutralObjects, landscape);
        }
Exemple #7
0
 /// <summary>
 /// Load
 /// </summary>
 /// <param name="colladaTrack">Collada track</param>
 /// <param name="landscape">Landscape</param>
 protected void Load(TrackData colladaTrack, Landscape landscape)
 {
     Load(colladaTrack.TrackPoints.ToArray(),
         colladaTrack.WidthHelpers,
         colladaTrack.RoadHelpers,
         colladaTrack.NeutralsObjects,
         landscape);
 }
Exemple #8
0
        /// <summary>
        /// Create track line
        /// </summary>
        /// <param name="inputPoints">Input Points, will form a closed curve
        /// </param>
        public TrackLine(Vector3[] inputPoints,
			List<TrackData.WidthHelper> widthHelpers,
			List<TrackData.RoadHelper> roadHelpers,
			List<TrackData.NeutralObject> neutralObjects,
			Landscape landscape)
        {
            Load(inputPoints, widthHelpers, roadHelpers, neutralObjects, landscape);
        }
Exemple #9
0
        /// <summary>
        /// Create track line
        /// </summary>
        /// <param name="inputPointsFromColladaTrack">
        /// Input points from collada track</param>
        public TrackLine(TrackData inputPointsFromColladaTrack,
			Landscape landscape)
            : this(inputPointsFromColladaTrack.TrackPoints.ToArray(),
			inputPointsFromColladaTrack.WidthHelpers,
			inputPointsFromColladaTrack.RoadHelpers,
			inputPointsFromColladaTrack.NeutralsObjects,
			landscape)
        {
        }
Exemple #10
0
        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 RacingGame 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(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(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 6, generate again
                    if (randomObjNum >= 6)
                        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>
 /// Dispose
 /// </summary>
 /// <param name="someObject">Some object</param>
 public static void Dispose(ref Landscape someObject)
 {
     if (someObject != null)
         someObject.Dispose();
     someObject = null;
 }
Exemple #12
0
        /// <summary>
        /// Reload
        /// </summary>
        /// <param name="setTrackName">Track name</param>
        /// <param name="landscape">Landscape</param>
        public void Reload(string setTrackName, Landscape landscape)
        {
            // Do we need to load the base track again?
            // Always reload! Else we might mess up the checkpoints, etc.
            base.Load(TrackData.Load(setTrackName), landscape);

            GenerateVerticesAndObjects(landscape);
        }
Exemple #13
0
 /// <summary>
 /// Create track
 /// </summary>
 /// <param name="setTrackName">Track name to load</param>
 /// <param name="landscape">Landscape to check if we are above it</param>
 public Track(string setTrackName, Landscape landscape)
     : base(TrackData.Load(setTrackName), landscape)
 {
     GenerateVerticesAndObjects(landscape);
 }
Exemple #14
0
        /// <summary>
        /// Generate vertices and objects
        /// </summary>
        private void GenerateVerticesAndObjects(Landscape landscape)
        {
            #region Generate the road vertices
            // Each road segment gets 5 points:
            // left, left middle, middle, right middle, right.
            // The reason for this is that we would bad triangle errors if the
            // road gets wider and wider. This happens because we need to render
            // quad, but we can only render triangles, which often have different
            // orientations, which makes the road very bumpy. This still happens
            // with 8 polygons instead of 2, but it is much better this way.
            // Another trick is not to do so much iterations in TrackLine, which
            // causes this problem. Better to have a not so round track, but at
            // least the road up/down itself is smooth.
            // The last point is duplicated (see TrackLine) because we have 2 sets
            // of texture coordinates for it (begin block, end block).
            // So for the index buffer we only use points.Count-1 blocks.
            roadVertices = new TangentVertex[points.Count * 5];

            // Current texture coordinate for the roadway (in direction of movement)
            for (int num = 0; num < points.Count; num++)
            {
                // Get vertices with help of the properties in the TrackVertex class.
                // For the road itself we only need vertices for the left and right
                // side, which are vertex number 0 and 1.
                roadVertices[num * 5 + 0] = points[num].RightTangentVertex;
                roadVertices[num * 5 + 1] = points[num].MiddleRightTangentVertex;
                roadVertices[num * 5 + 2] = points[num].MiddleTangentVertex;
                roadVertices[num * 5 + 3] = points[num].MiddleLeftTangentVertex;
                roadVertices[num * 5 + 4] = points[num].LeftTangentVertex;
            } // for (num)

            roadVb = new VertexBuffer(
                BaseGame.Device,
                typeof(TangentVertex),
                roadVertices.Length,
                BufferUsage.WriteOnly);
            roadVb.SetData(roadVertices);

            // Also calculate all indices, we have 8 polygons for each segment with
            // 3 vertices each. We got 1 segment less than points because the
            // last point is duplicated (different tex coords).
            int[] indices = new int[(points.Count - 1) * 8 * 3];
            int vertexIndex = 0;
            for (int num = 0; num < points.Count - 1; num++)
            {
                // We only use 3 vertices (and the next 3 vertices),
                // but we have to construct all 24 indices for our 4 polygons.
                for (int sideNum = 0; sideNum < 4; sideNum++)
                {
                    // Each side needs 2 polygons.

                    // 1. Polygon
                    indices[num * 24 + 6 * sideNum + 0] =
                        vertexIndex + sideNum;
                    indices[num * 24 + 6 * sideNum + 1] =
                        vertexIndex + 5 + 1 + sideNum;
                    indices[num * 24 + 6 * sideNum + 2] =
                        vertexIndex + 5 + sideNum;

                    // 2. Polygon
                    indices[num * 24 + 6 * sideNum + 3] =
                        vertexIndex + 5 + 1 + sideNum;
                    indices[num * 24 + 6 * sideNum + 4] =
                        vertexIndex + sideNum;
                    indices[num * 24 + 6 * sideNum + 5] =
                        vertexIndex + 1 + sideNum;
                } // for (num)

                // Go to the next 5 vertices
                vertexIndex += 5;
            } // for (num)

            // Set road back index buffer
            roadIb = new IndexBuffer(
                BaseGame.Device,
                typeof(int),
                indices.Length,
                BufferUsage.WriteOnly);
            roadIb.SetData(indices);
            #endregion

            #region Generate the road back vertices
            // We need 4 vertices per cross-section edge of the road back hull
            roadBackVertices = new TangentVertex[points.Count * 4];
            for (int num = 0; num < points.Count; num++)
            {
                // Left side of the road
                roadBackVertices[num * 4 + 0] =
                    points[num].LeftTangentVertex;
                roadBackVertices[num * 4 + 0].uv = new Vector2(
                    roadBackVertices[num * 4 + 0].U * RoadBackHullTextureWidthFactor,
                    0.0f);

                // Left lower side of the road
                roadBackVertices[num * 4 + 1] =
                    points[num].BottomLeftSideTangentVertex;
                roadBackVertices[num * 4 + 1].uv = new Vector2(
                    roadBackVertices[num * 4 + 0].U * RoadBackHullTextureWidthFactor,
                    RoadBackSideTextureHeight);

                // Right lower side of the road
                roadBackVertices[num * 4 + 2] =
                    points[num].BottomRightSideTangentVertex;
                roadBackVertices[num * 4 + 2].uv = new Vector2(
                    roadBackVertices[num * 4 + 0].U * RoadBackHullTextureWidthFactor,
                    1.0f - RoadBackSideTextureHeight);

                // Right side of the road
                roadBackVertices[num * 4 + 3] =
                    points[num].RightTangentVertex;
                roadBackVertices[num * 4 + 3].uv = new Vector2(
                    roadBackVertices[num * 4 + 3].U * RoadBackHullTextureWidthFactor,
                    1.0f);
            } // for (num)

            // Set road back vertex buffer
            roadBackVb = new VertexBuffer(
                BaseGame.Device,
                typeof(TangentVertex),
                roadBackVertices.Length,
                BufferUsage.WriteOnly);
            roadBackVb.SetData(roadBackVertices);

            // Also calculate all indices, we have 6 polygons for each segment with
            // 3 vertices each. We got 1 segment less than points because the
            // last point is duplicated (different tex coords).
            int[] backIndices = new int[(points.Count-1) * 6 * 3];
            vertexIndex = 0;
            for (int num = 0; num < points.Count-1; num++)
            {
                // We only use 4 vertices (and the next 4 vertices),
                // but we have to construct all 18 indices for our 6 polygons.
                for (int sideNum = 0; sideNum < 3; sideNum++)
                {
                    // Each side needs 2 polygons.

                    // 1. Polygon
                    backIndices[num * 18 + 6 * sideNum + 0] =
                        vertexIndex + sideNum;
                    backIndices[num * 18 + 6 * sideNum + 1] =
                        vertexIndex + 5 + sideNum;
                    backIndices[num * 18 + 6 * sideNum + 2] =
                        vertexIndex + 4 + sideNum;

                    // 2. Polygon
                    backIndices[num * 18 + 6 * sideNum + 3] =
                        vertexIndex + 5 + sideNum;
                    backIndices[num * 18 + 6 * sideNum + 4] =
                        vertexIndex + sideNum;
                    backIndices[num * 18 + 6 * sideNum + 5] =
                        vertexIndex + 1 + sideNum;
                } // for (num)

                // Go to the next 4 vertices
                vertexIndex += 4;
            } // for (num)

            // Set road back index buffer
            roadBackIb = new IndexBuffer(
                BaseGame.Device,
                typeof(int),
                backIndices.Length,
                BufferUsage.WriteOnly);
            roadBackIb.SetData(backIndices);
            #endregion

            #region Generate the road tunnel vertices
            // Only generate tunnels for the parts were we want to have tunnels for.
            int totalTunnelLength = 0;
            foreach (RoadHelperPosition tunnelPos in helperPositions)
                if (tunnelPos.type == TrackData.RoadHelper.HelperType.Tunnel)
                    totalTunnelLength += 1+(tunnelPos.endNum - tunnelPos.startNum);

            // Lets use 4 vertices per segment, we could improve that later
            // by adding more vertices for a round tunnel.
            roadTunnelVertices = new TangentVertex[totalTunnelLength * 4];
            vertexIndex = 0;
            foreach (RoadHelperPosition tunnelPos in helperPositions)
                if (tunnelPos.type == TrackData.RoadHelper.HelperType.Tunnel)
                    for (int num = tunnelPos.startNum; num <= tunnelPos.endNum; num++)
                {
                    // Left side of the road
                    roadTunnelVertices[vertexIndex + 0] =
                        points[num].LeftTangentVertex;
                    roadTunnelVertices[vertexIndex + 0].uv = new Vector2(
                        roadTunnelVertices[vertexIndex + 0].U * RoadTunnelTextureWidthFactor,
                        0.0f);

                    // Left top side of the road
                    roadTunnelVertices[vertexIndex + 1] =
                        points[num].TunnelTopLeftSideTangentVertex;
                    roadTunnelVertices[vertexIndex + 1].uv = new Vector2(
                        roadTunnelVertices[vertexIndex + 1].U * RoadTunnelTextureWidthFactor,
                        RoadTunnelSideTextureHeight);

                    // Right top side of the road
                    roadTunnelVertices[vertexIndex + 2] =
                        points[num].TunnelTopRightSideTangentVertex;
                    roadTunnelVertices[vertexIndex + 2].uv = new Vector2(
                        roadTunnelVertices[vertexIndex + 2].U * RoadTunnelTextureWidthFactor,
                        1.0f - RoadTunnelSideTextureHeight);

                    // Right side of the road
                    roadTunnelVertices[vertexIndex + 3] =
                        points[num].RightTangentVertex;
                    roadTunnelVertices[vertexIndex + 3].uv = new Vector2(
                        roadTunnelVertices[vertexIndex + 3].U * RoadTunnelTextureWidthFactor,
                        1.0f);

                    // Adjust normals for the 2 lower points
                    roadTunnelVertices[vertexIndex + 0].normal *= -1;
                    roadTunnelVertices[vertexIndex + 3].normal *= -1;
                    roadTunnelVertices[vertexIndex + 0].tangent *= -1;
                    roadTunnelVertices[vertexIndex + 3].tangent *= -1;

                    vertexIndex += 4;
                } // foreach for (num)

            // Set road back vertex buffer
            if (roadTunnelVertices.Length > 0)
            {
                roadTunnelVb = new VertexBuffer(
                    BaseGame.Device,
                    typeof(TangentVertex),
                    roadTunnelVertices.Length,
                    BufferUsage.WriteOnly);
                roadTunnelVb.SetData(roadTunnelVertices);

                // Also calculate all indices, we have 6 polygons for each segment with
                // 3 vertices each. We got 1 segment less than points because the
                // last point is duplicated (different tex coords).
                int totalIndices = 0;
                foreach (RoadHelperPosition tunnelPos in helperPositions)
                    if (tunnelPos.type == TrackData.RoadHelper.HelperType.Tunnel)
                        totalIndices += (tunnelPos.endNum - tunnelPos.startNum);
                roadTunnelIndices = new int[totalIndices * 6 * 3];
                vertexIndex = 0;
                int tunnelIndex = 0;
                foreach (RoadHelperPosition tunnelPos in helperPositions)
                    if (tunnelPos.type == TrackData.RoadHelper.HelperType.Tunnel)
                {
                    for (int num = tunnelPos.startNum; num < tunnelPos.endNum; num++)
                    {
                        // We only use 4 vertices (and the next 4 vertices),
                        // but we have to construct all 18 indices for our 6 polygons.
                        for (int sideNum = 0; sideNum < 3; sideNum++)
                        {
                            // Each side needs 2 polygons.
                            // Note: This polygons are rendered with culling off because
                            // we want to see the inside and outside of the tunnel.

                            // 1. Polygon
                            roadTunnelIndices[tunnelIndex + 0] =
                                vertexIndex + sideNum;
                            roadTunnelIndices[tunnelIndex + 2] =
                                vertexIndex + 4 + sideNum;
                            roadTunnelIndices[tunnelIndex + 1] =
                                vertexIndex + 5 + sideNum;

                            // 2. Polygon
                            roadTunnelIndices[tunnelIndex + 3] =
                                vertexIndex + 5 + sideNum;
                            roadTunnelIndices[tunnelIndex + 5] =
                                vertexIndex + 1 + sideNum;
                            roadTunnelIndices[tunnelIndex + 4] =
                                vertexIndex + sideNum;

                            tunnelIndex += 6;
                        } // for (sideNum)

                        // Go to the next 4 vertices
                        vertexIndex += 4;
                    } // for (num)

                    // Skip 4 vertices till the next tunnel
                    vertexIndex += 4;
                } // foreach (tunnelPos)

                // Set road back index buffer
                roadTunnelIb = new IndexBuffer(
                    BaseGame.Device,
                    typeof(int),
                    roadTunnelIndices.Length,
                    BufferUsage.WriteOnly);
                roadTunnelIb.SetData(roadTunnelIndices);
            } // if
            #endregion

            #region Generate guard rails
            leftRail = new GuardRail(points, GuardRail.Modes.Left, landscape);
            rightRail = new GuardRail(points, GuardRail.Modes.Right, landscape);
            #endregion

            #region Generate columns
            columns = new TrackColumns(points, landscape);
            #endregion

            GenerateObjectsForTrack(landscape);
        }
 /// <summary>
 /// Load
 /// </summary>
 /// <param name="trackData">track</param>
 /// <param name="landscape">Landscape</param>
 protected void Load(TrackData trackData, Landscape landscape)
 {
     Load(trackData.TrackPoints.ToArray(),
         trackData.WidthHelpers,
         trackData.RoadHelpers,
         trackData.NeutralsObjects,
         landscape);
 }
        /// <summary>
        /// Load car stuff
        /// </summary>
        protected override void Initialize()
        {
            base.Initialize();

            // Load models
            carModel = new Model("Car");
            carSelectionPlate = new Model("CarSelectionPlate");

            // Load landscape
            landscape = new Landscape(Level.Beginner);

            // Load textures, first one is grabbed from the imported one through
            // the car.x model, the other two are loaded seperately.
            carTextures = new Texture[3];
            carTextures[0] = new Texture("RacerCar%0");
            carTextures[1] = new Texture("RacerCar2");
            carTextures[2] = new Texture("RacerCar3");
            colorSelectionTexture = new Texture("ColorSelection");
            brakeTrackMaterial = new Material("track");

              //For testing:
            //Directly start the game and load a certain level, this code is
              // only used in the debug mode. Remove it when you are don with
              // testing! If you press Esc you will also quit the game and not
              // just end up in the menu again.
              //gameScreens.Clear();
              //gameScreens.Push(new GameScreen());
        }