XNA Game Development Forums
2012/05/18 06:27:52 *
Welcome, Guest. Please login or register.

Login with username, password and session length
 
   Home   Help Search Calendar Login Register  
Pages: [1]
  Print  
Author Topic: Question: Texturing Terrain  (Read 2337 times)
Ashe
Newbie
*
Offline Offline

Posts: 3


View Profile
« on: 2007/03/11 22:33:59 »

Hello Everyone,

I have a few questions about terrain that hopefully someone can help me out with.  If you create a terrain using a heightmap, what are a few methods used to texture this terrain?  I have read a little about Texture Splatting, Detail Texture, and Texture Blending, but I am not sure how you create a road/path using those techniques.

What is considered the "best" way or most "up-to-date" way to accomplish this texturing task?

If you were to use a static mesh, is a .fbx the best route?  Do you just UVMap the whole terrain model and let the engine read the UVMap?  Is it considered a good idea (or is it even possible) to have the engine use a multi-texture material from like 3DS Max for terrain and buildings?

Is it best to create an engine with a Level/Scene Editor that can actually paint the texture directly on the model, if that is the case, does the scene editor have to save the heightmap/model and textures you apply to it out as a new model and texture?

My main question is how to create a path/road on a large terrain?

Thanks,

-Ashe
Logged
DaphydTheBard
Jr. Member
**
Offline Offline

Posts: 55


View Profile
« Reply #1 on: 2007/03/17 10:28:36 »

In case it's of any help, here's my XNATerrain Class:

Code:
#region Using Directives

using System;
using System.Collections.Generic;
using System.Text;
using System.IO;

using Microsoft.Xna.Framework;
using Microsoft.Xna.Framework.Audio;
using Microsoft.Xna.Framework.Content;
using Microsoft.Xna.Framework.Graphics;
using Microsoft.Xna.Framework.Input;
using Microsoft.Xna.Framework.Storage;

using XNACore.Graphics;
using XNACore.Helpers;

#endregion


namespace XNACore.Graphics
{
    public class XNATerrain
    {
        #region Structures

        public struct VertexPositionNormalColored
        {
            public Vector3 Position;
            public Color Color;
            public Vector3 Normal;

            public static int SizeInBytes = 7 * 4;
            public static VertexElement[] VertexElements = new VertexElement[]
              {
                  new VertexElement( 0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0 ),
                  new VertexElement( 0, sizeof(float) * 3, VertexElementFormat.Color, VertexElementMethod.Default, VertexElementUsage.Color, 0 ),
                  new VertexElement( 0, sizeof(float) * 4, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0 ),
              };
        }

        public struct VertexMultitextured
        {
            public Vector3 Position;
            public Vector3 Normal;
            public Vector4 TextureCoordinate;
            public Vector4 TexWeights;

            public static int SizeInBytes = (3 + 3 + 4 + 4) * 4;
            public static VertexElement[] VertexElements = new VertexElement[]
             {
                 new VertexElement( 0, 0, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Position, 0 ),
                 new VertexElement( 0, sizeof(float) * 3, VertexElementFormat.Vector3, VertexElementMethod.Default, VertexElementUsage.Normal, 0 ),
                 new VertexElement( 0, sizeof(float) * 6, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 0 ),
                 new VertexElement( 0, sizeof(float) * 10, VertexElementFormat.Vector4, VertexElementMethod.Default, VertexElementUsage.TextureCoordinate, 1 ),
             };
        }


        #endregion

        #region Variables

        private VertexBuffer terrainVertexBuffer;
        private IndexBuffer terrainIndexBuffer;
        private Texture2D heightMap;
        private Texture2D heightMapA;
        private int WIDTH;
        private int HEIGHT;
        private float[,] heightData;

        private XNAGame objGame = null;
        private XNAViewPort objView = null;
        private Effect objEffect;

        private Texture2D textureSand;
        private Texture2D textureGrass;
        private Texture2D textureRock;
        private Texture2D textureSnow;

        private const int SCALE = 1;

        #endregion

        #region Constructor

        public XNATerrain(ref XNAGame xnaGame, ref XNAViewPort xnaView,
            Texture2D heightMapTexture,
            Texture2D heightMapTextureA,
            Texture2D sandTexture,
            Texture2D grassTexture,
            Texture2D rockTexture,
            Texture2D snowTexture)
        {
            objGame = xnaGame;
            objView = xnaView;
            heightMap = heightMapTexture;
            heightMapA = heightMapTextureA;

            LoadHeightData();
            SetUpTerrainVertices();
            SetUpTerrainterrainIndices();

            objEffect = objGame.Content.Load<Effect>(FolderHelper.ShadersFolder() + "Terrain");

            textureSand = sandTexture;
            textureGrass = grassTexture;
            textureRock = rockTexture;
            textureSnow = snowTexture;

        }

        #endregion       

        #region Private Methods

        private void LoadHeightData()
        {
            float minimumHeight = 255;
            float maximumHeight = 0;

            WIDTH = heightMapA.Width;
            HEIGHT = heightMapA.Height;

            Color[] heightMapColors = new Color[WIDTH * HEIGHT];
            heightMapA.GetData(heightMapColors);

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

            for (int x = 0; x < WIDTH; x++)
                for (int y = 0; y < HEIGHT; y++)
                {
                   heightData[x, y] = (heightData[x, y] - minimumHeight) / (maximumHeight - minimumHeight) * 30;                   
                }
        }

        private void SetUpTerrainVertices()
        {
            WIDTH = heightMap.Width;
            HEIGHT = heightMap.Height;

            VertexMultitextured[] terrainVertices = new VertexMultitextured[WIDTH * HEIGHT];

            for (int x = 0; x < WIDTH; x++)
                for (int y = 0; y < HEIGHT; y++)
                {
                    terrainVertices[x + y * WIDTH].Position = new Vector3(x * SCALE, y * SCALE, heightData[x * SCALE, y * SCALE]);
                    terrainVertices[x + y * WIDTH].Normal = new Vector3(0, 0, 1);
                    terrainVertices[x + y * WIDTH].TextureCoordinate.X = (float)x / 30.0f;
                    terrainVertices[x + y * WIDTH].TextureCoordinate.Y = (float)y / 30.0f;

                    terrainVertices[x + y * WIDTH].TexWeights.X = MathHelper.Clamp(1.0f - Math.Abs(heightData[x * SCALE, y * SCALE] - 0) / 8.0f, 0, 1);
                    terrainVertices[x + y * WIDTH].TexWeights.Y = MathHelper.Clamp(1.0f - Math.Abs(heightData[x * SCALE, y * SCALE] - 12) / 6.0f, 0, 1);
                    terrainVertices[x + y * WIDTH].TexWeights.Z = MathHelper.Clamp(1.0f - Math.Abs(heightData[x * SCALE, y * SCALE] - 20) / 6.0f, 0, 1);
                    terrainVertices[x + y * WIDTH].TexWeights.W = MathHelper.Clamp(1.0f - Math.Abs(heightData[x * SCALE, y * SCALE] - 30) / 6.0f, 0, 1);

                    float totalWeight = terrainVertices[x + y * WIDTH].TexWeights.X;
                    totalWeight += terrainVertices[x + y * WIDTH].TexWeights.Y;
                    totalWeight += terrainVertices[x + y * WIDTH].TexWeights.Z;
                    totalWeight += terrainVertices[x + y * WIDTH].TexWeights.W;
                    terrainVertices[x + y * WIDTH].TexWeights.X /= totalWeight;
                    terrainVertices[x + y * WIDTH].TexWeights.Y /= totalWeight;
                    terrainVertices[x + y * WIDTH].TexWeights.Z /= totalWeight;
                    terrainVertices[x + y * WIDTH].TexWeights.W /= totalWeight;

                }

            for (int x = 1; x < WIDTH - 1; x++)
            {
                for (int y = 1; y < HEIGHT - 1; y++)
                {
                    Vector3 normX = new Vector3((terrainVertices[x - 1 + y * WIDTH].Position.Z - terrainVertices[x + 1 + y * WIDTH].Position.Z) / 2, 0, 1);
                    Vector3 normY = new Vector3(0, (terrainVertices[x + (y - 1) * WIDTH].Position.Z - terrainVertices[x + (y + 1) * WIDTH].Position.Z) / 2, 1);
                    terrainVertices[x + y * WIDTH].Normal = normX + normY;
                    terrainVertices[x + y * WIDTH].Normal.Normalize();
                }
            }


            terrainVertexBuffer = new VertexBuffer(objGame.Device , VertexMultitextured.SizeInBytes * WIDTH * HEIGHT, ResourceUsage.WriteOnly, ResourceManagementMode.Automatic);

            terrainVertexBuffer.SetData(terrainVertices);
        }


        private void SetUpTerrainterrainIndices()
        {
            int[] terrainIndices = new int[(WIDTH - 1) * (HEIGHT - 1) * 6];
            for (int x = 0; x < WIDTH - 1; x++)
            {
                for (int y = 0; y < HEIGHT - 1; y++)
                {
                    terrainIndices[(x + y * (WIDTH - 1)) * 6] = (x + 1) + (y + 1) * WIDTH;
                    terrainIndices[(x + y * (WIDTH - 1)) * 6 + 1] = (x + 1) + y * WIDTH;
                    terrainIndices[(x + y * (WIDTH - 1)) * 6 + 2] = x + y * WIDTH;

                    terrainIndices[(x + y * (WIDTH - 1)) * 6 + 3] = (x + 1) + (y + 1) * WIDTH;
                    terrainIndices[(x + y * (WIDTH - 1)) * 6 + 4] = x + y * WIDTH;
                    terrainIndices[(x + y * (WIDTH - 1)) * 6 + 5] = x + (y + 1) * WIDTH;
                }
            }

            terrainIndexBuffer = new IndexBuffer(objGame.Device, typeof(int), (WIDTH - 1) * (HEIGHT - 1) * 6, ResourceUsage.WriteOnly, ResourceManagementMode.Automatic);
            terrainIndexBuffer.SetData(terrainIndices);
        }

        #endregion

        #region Public Methods

        public void Flatten()
        {
            WIDTH = heightMapA.Width;
            HEIGHT = heightMapA.Height;

             for (int x = 0; x < WIDTH; x++)
                 for (int y = 0; y < HEIGHT; y++)
                 {
                     heightData[x, y] = 1.0f;
                 }

             SetUpTerrainVertices();
             SetUpTerrainterrainIndices();
        }


        public void Render()
        {
            objEffect.CurrentTechnique = objEffect.Techniques["MultiTextured"];
            objEffect.Parameters["xSandTexture"].SetValue(textureSand );
            objEffect.Parameters["xGrassTexture"].SetValue(textureGrass );
            objEffect.Parameters["xRockTexture"].SetValue(textureRock );
            objEffect.Parameters["xSnowTexture"].SetValue(textureSnow );


            Matrix worldMatrix = Matrix.Identity
                * Matrix.CreateRotationX(MathHelper.ToRadians(270))
                * Matrix.CreateRotationY(MathHelper.ToRadians(270));
               
               
            objEffect.Parameters["xWorld"].SetValue(worldMatrix);
            objEffect.Parameters["xView"].SetValue(objView.MatrixView);
            objEffect.Parameters["xProjection"].SetValue(objView.MatrixProjection );
            objEffect.Parameters["xEnableLighting"].SetValue(true);
            objEffect.Parameters["xLightDirection"].SetValue(new Vector3(-0.5f, -0.5f, -1));
            objEffect.Parameters["xAmbient"].SetValue(0.15f);

           
           
            objEffect.Begin();
            foreach (EffectPass pass in objEffect.CurrentTechnique.Passes)
            {
                pass.Begin();

                objGame.Device.Vertices[0].SetSource(terrainVertexBuffer, 0, VertexMultitextured.SizeInBytes);
                objGame.Device.Indices = terrainIndexBuffer;
                objGame.Device.VertexDeclaration = new VertexDeclaration(objGame.Device , VertexMultitextured.VertexElements);
                objGame.Device.DrawIndexedPrimitives(PrimitiveType.TriangleList, 0, 0, WIDTH * HEIGHT, 0, (WIDTH - 1) * (HEIGHT - 1) * 2);

                pass.End();
            }
            objEffect.End();
        }

        public float GetHeight(int x, int y)
        {
            try
            { return heightData[x, y]; }
            catch
            {
                return 0.0f;
            }
            finally {}
                   
        }

        #endregion
    }
}
Logged
Pages: [1]
  Print  
 
Jump to:  

Related Topics
Subject Started by Replies Views Last post
MOVED: Terrain Object Show Off Board Chr0n1x 0 2317 Last post 2007/01/27 23:23:52
by Chr0n1x
Terrain Traversing/Collision Hazy Mind XNA Engine Quinn 1 1604 Last post 2007/02/28 00:27:04
by Ardman
Question about Getting 2D screen coordinates General Discussion DaphydTheBard 6 2462 Last post 2007/02/27 03:23:36
by DaphydTheBard
Question about getting rotation angles from Quaternions... General Discussion DaphydTheBard 7 3131 Last post 2007/03/20 07:27:20
by DaphydTheBard
Array Question General Discussion LucianX 11 3350 Last post 2007/04/13 04:51:19
by Nemo Krad
Tutorial 3 help... new question i believe Hazy Mind XNA Engine hansonc 9 3126 Last post 2007/05/15 01:32:01
by BackwardsBoxers
tutorial 3 sprite question Hazy Mind 3D Engine precious roy 2 2728 Last post 2009/10/18 08:53:11
by Wekbaite73
FPS question General Discussion XNASorcerer 2 1468 Last post 2007/04/28 15:23:19
by XNASorcerer
HMObject design question Hazy Mind XNA Engine jdowling 1 1266 Last post 2007/05/11 23:05:38
by Tiago
Thanks And A question Hazy Mind XNA Engine zachaller 3 1567 Last post 2007/06/19 03:36:22
by Nemo Krad
Terrain with Bumpmap Show Off Board Nemo Krad 8 3950 Last post 2007/06/29 01:22:38
by Nemo Krad
Terrain orientation Hazy Mind XNA Engine Theoderich 1 1375 Last post 2007/07/30 00:20:17
by murga
Texturing Models Hazy Mind XNA Engine Peregrinati 4 2106 Last post 2008/12/15 12:14:41
by Peregrinati
Powered by MySQL Powered by PHP Powered by SMF 1.1.12 | SMF © 2006-2009, Simple Machines LLC Valid XHTML 1.0! Valid CSS!
Page created in 1.118 seconds with 18 queries.