Exemplo n.º 1
0
 /// <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);
     }
 }
        /// <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
        }
Exemplo n.º 3
0
        /*now done in track class!
         * /// <summary>
         * /// Matrix list for each of the holder pile objects we have to render.
         * /// </summary>
         * List<Matrix> holderPileMatrices = new List<Matrix>();
         */
        #endregion

        #region Constructor
        /// <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
        }         // GuardRail(points, mode, landscape)
Exemplo n.º 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
                        {
                            helperStartedNum = num;
                            remType          = roadHelper.type;
                        }

                        // Remove this roadHelper (don't use it again)!
                        roadHelpers.Remove(roadHelper);
                        break;
                    }
                }
            }

            // 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);
                }
            }
            #endregion
        }