Beispiel #1
0
        /// <summary>
        /// This function is called when the game is Updating in response to user input.
        /// It'll move the tank around the heightmap, and update all of the tank's
        /// necessary state.
        /// </summary>
        public void Update(float elapsed, float turnAmount, Vector3 movement, HeightMapInfo heightMapInfo, Vector2 turretVector)
        {
            facingDirection += turnAmount * TankTurnSpeed * elapsed;

            // next, we'll create a rotation matrix from the direction the tank is
            // facing, and use it to transform the vector.

            Vector3 velocity = Vector3.Transform(movement, orientation);

            velocity *= TankVelocity;

            turretRotationValue = turretVector.X;
            cannonRotationValue = turretVector.Y;

            // Now we know how much the user wants to move. We'll construct a temporary
            // vector, newPosition, which will represent where the user wants to go. If
            // that value is on the heightmap, we'll allow the move.
            Vector3 newPosition = position + velocity * elapsed;

            if (heightMapInfo.IsOnHeightmap(newPosition))
            {
                // now that we know we're on the heightmap, we need to know the correct
                // height and normal at this position.
                heightMapInfo.GetHeightAndNormal(newPosition,
                                                 out newPosition.Y, out normal);


                // As discussed in the doc, we'll use the normal of the heightmap
                // and our desired forward direction to recalculate our orientation
                // matrix. It's important to normalize, as well.


                // now we need to roll the tank's wheels "forward." to do this, we'll
                // calculate how far they have rolled, and from there calculate how much
                // they must have rotated.
                float distanceMoved = Vector3.Distance(position, newPosition);
                float theta         = distanceMoved / TankWheelRadius;
                int   rollDirection = movement.Z > 0 ? 1 : -1;

                wheelRotationValue += theta * rollDirection;

                // once we've finished all computations, we can set our position to the
                // new position that we calculated.
                position = newPosition;
            }
            orientation    = Matrix.CreateRotationY(FacingDirection);
            orientation.Up = normal;

            orientation.Right = Vector3.Cross(orientation.Forward, orientation.Up);
            orientation.Right = Vector3.Normalize(orientation.Right);

            orientation.Forward = Vector3.Cross(orientation.Up, orientation.Right);
            orientation.Forward = Vector3.Normalize(orientation.Forward);
        }
Beispiel #2
0
        void SetUpTerrain()
        {
            #region Loading Height Data
            Texture2D heightMap     = Content.Load <Texture2D>("Land");
            float     minimumHeight = float.MaxValue;
            float     maximumHeight = float.MinValue;

            float heightRange = 20;
            waterHeight = heightRange * 0.10f;

            terrainWidth  = heightMap.Width;
            terrainLength = heightMap.Height;

            Color[] heightMapColors = new Color[terrainWidth * terrainLength];
            heightMap.GetData(heightMapColors);

            heightData = new float[terrainWidth, terrainLength];
            for (int x = 0; x < terrainWidth; x++)
            {
                for (int y = 0; y < terrainLength; y++)
                {
                    heightData[x, y] = heightMapColors[x + y * terrainWidth].R;
                    if (heightData[x, y] < minimumHeight)
                    {
                        minimumHeight = heightData[x, y];
                    }
                    if (heightData[x, y] > maximumHeight)
                    {
                        maximumHeight = heightData[x, y];
                    }
                }
            }

            for (int x = 0; x < terrainWidth; x++)
            {
                for (int y = 0; y < terrainLength; y++)
                {
                    heightData[x, y] = (heightData[x, y] - minimumHeight) / (maximumHeight - minimumHeight) * heightRange;
                }
            }
            #endregion
            #region Generating Vertices
            terrainVertices = new VertexMultitextured[terrainWidth * terrainLength];

            for (int x = 0; x < terrainWidth; x++)
            {
                for (int y = 0; y < terrainLength; y++)
                {
                    float height = heightData[x, y];
                    terrainVertices[x + y * terrainWidth].Position            = new Vector3(x, height, y);
                    terrainVertices[x + y * terrainWidth].TextureCoordinate.X = (float)x / 30.0f;
                    terrainVertices[x + y * terrainWidth].TextureCoordinate.Y = (float)y / 30.0f;
                    terrainVertices[x + y * terrainWidth].TexWeights.X        = MathHelper.Clamp(1.0f - Math.Abs(height - 0) / (heightRange / 4), 0, 1);                   //sand
                    terrainVertices[x + y * terrainWidth].TexWeights.Y        = MathHelper.Clamp(1.0f - Math.Abs(height - heightRange / 3) / (heightRange / 4), 0, 1);     //grass
                    terrainVertices[x + y * terrainWidth].TexWeights.Z        = MathHelper.Clamp(1.0f - Math.Abs(height - 2 * heightRange / 3) / (heightRange / 4), 0, 1); //rock
                    terrainVertices[x + y * terrainWidth].TexWeights.W        = MathHelper.Clamp(1.0f - Math.Abs(height - heightRange) / (heightRange / 4), 0, 1);         //snow

                    float total = terrainVertices[x + y * terrainWidth].TexWeights.X;
                    total += terrainVertices[x + y * terrainWidth].TexWeights.Y;
                    total += terrainVertices[x + y * terrainWidth].TexWeights.Z;
                    total += terrainVertices[x + y * terrainWidth].TexWeights.W;

                    terrainVertices[x + y * terrainWidth].TexWeights.X /= total;
                    terrainVertices[x + y * terrainWidth].TexWeights.Y /= total;
                    terrainVertices[x + y * terrainWidth].TexWeights.Z /= total;
                    terrainVertices[x + y * terrainWidth].TexWeights.W /= total;
                }
            }
            #endregion
            #region Generating Indices
            terrainIndices = new int[(terrainWidth - 1) * (terrainLength - 1) * 6];
            int counter = 0;
            for (int y = 0; y < terrainLength - 1; y++)
            {
                for (int x = 0; x < terrainWidth - 1; x++)
                {
                    int lowerLeft  = x + (y + 1) * terrainWidth;
                    int lowerRight = (x + 1) + (y + 1) * terrainWidth;
                    int topLeft    = x + y * terrainWidth;
                    int topRight   = (x + 1) + y * terrainWidth;

                    terrainIndices[counter++] = topLeft;
                    terrainIndices[counter++] = lowerRight;
                    terrainIndices[counter++] = lowerLeft;

                    terrainIndices[counter++] = topLeft;
                    terrainIndices[counter++] = topRight;
                    terrainIndices[counter++] = lowerRight;
                }
            }
            #endregion
            #region Calculating Normals
            for (int i = 0; i < terrainVertices.Length; i++)
            {
                terrainVertices[i].Normal = new Vector3(0, 0, 0);
            }

            for (int i = 0; i < terrainIndices.Length / 3; i++)
            {
                int index1 = terrainIndices[i * 3];
                int index2 = terrainIndices[i * 3 + 1];
                int index3 = terrainIndices[i * 3 + 2];

                Vector3 side1  = terrainVertices[index1].Position - terrainVertices[index3].Position;
                Vector3 side2  = terrainVertices[index1].Position - terrainVertices[index2].Position;
                Vector3 normal = Vector3.Cross(side1, side2);

                terrainVertices[index1].Normal += normal;
                terrainVertices[index2].Normal += normal;
                terrainVertices[index3].Normal += normal;
            }

            for (int i = 0; i < terrainVertices.Length; i++)
            {
                terrainVertices[i].Normal.Normalize();
                float temp = terrainVertices[i].Normal.Y;
                temp = MathHelper.Clamp((float)Math.Pow(temp, 2), 0, 1);
                float mag = terrainVertices[i].TexWeights.Length();
                terrainVertices[i].TexWeights.Normalize();
                terrainVertices[i].TexWeights *= temp;
                terrainVertices[i].TexWeights += Vector4.UnitZ * (1 - temp);
                terrainVertices[i].TexWeights *= mag;
            }
            #endregion
            #region Loading Buffers
            terrainVertexBuffer = new VertexBuffer(GraphicsDevice, VertexMultitextured.VertexDeclaration, terrainVertices.Length, BufferUsage.WriteOnly);
            terrainVertexBuffer.SetData(terrainVertices);

            terrainIndexBuffer = new IndexBuffer(GraphicsDevice, typeof(int), terrainIndices.Length, BufferUsage.WriteOnly);
            terrainIndexBuffer.SetData(terrainIndices);
            #endregion
            #region Water
            VertexPositionTexture[] waterVertices = new VertexPositionTexture[6];

            waterVertices[0] = new VertexPositionTexture(new Vector3(0, waterHeight, terrainLength), new Vector2(0, 1));
            waterVertices[2] = new VertexPositionTexture(new Vector3(terrainWidth, waterHeight, 0), new Vector2(1, 0));
            waterVertices[1] = new VertexPositionTexture(new Vector3(0, waterHeight, 0), new Vector2(0, 0));

            waterVertices[3] = new VertexPositionTexture(new Vector3(0, waterHeight, terrainLength), new Vector2(0, 1));
            waterVertices[5] = new VertexPositionTexture(new Vector3(terrainWidth, waterHeight, terrainLength), new Vector2(1, 1));
            waterVertices[4] = new VertexPositionTexture(new Vector3(terrainWidth, waterHeight, 0), new Vector2(1, 0));

            waterVertexBuffer = new VertexBuffer(GraphicsDevice, VertexPositionTexture.VertexDeclaration, waterVertices.Length, BufferUsage.WriteOnly);
            waterVertexBuffer.SetData(waterVertices);

            effect.Parameters["xFogColor0"].SetValue(new Vector4(new Vector3(0.7f), 1));
            effect.Parameters["xFogColor1"].SetValue(Color.WhiteSmoke.ToVector4());
            effect.Parameters["xWaterBumpMap"].SetValue(waterBumpMap);
            effect.Parameters["xWaveLength"].SetValue(0.5f);
            effect.Parameters["xWaveHeight"].SetValue(0.1f);
            Vector3 windDirection = new Vector3(1, 0, 0);
            effect.Parameters["xWindForce"].SetValue(7.0f);
            effect.Parameters["xWindDirection"].SetValue(windDirection);
            #endregion
            Vector3[,] normals = new Vector3[terrainWidth, terrainLength];
            for (int x = 0; x < terrainWidth; x++)
            {
                for (int y = 0; y < terrainLength; y++)
                {
                    normals[x, y] = terrainVertices[x + y * terrainWidth].Normal;
                }
            }
            heightMapInfo = new HeightMapInfo(heightData, normals, 1);
        }