Click here to load reader
Upload
mohammad-shaker
View
379
Download
2
Tags:
Embed Size (px)
Citation preview
Mohammad Shakermohammadshaker.com
@ZGTRShaker2011, 2012, 2013, 2014
XNA Game DevelopmentL07 – Skybox and Terrian
SkyBox
• Advanced SkyBoxes
– With Terrain
• Riemers web site
– http://www.riemers.net/eng/Tutorials/XNA/Csharp/series4.php
– Rbwhitaker web site
• http://rbwhitaker.wikidot.com/skyboxes-1
SkyBox
• How to make a sky?!
Skydome
• Skydome
Skydome
• Skydome
– You’ll use is a conventional 3D model, previously
made in a modeling tool and processed by the
Content Pipeline.
– Handled through XNA’s Model class!
Skydome
• Skydome
– You’ll use is a conventional 3D model, previously
made in a modeling tool and processed by the
Content Pipeline.
– Handled through XNA’s Model class!
Skydome
• Whenever the camera moves, the skybox or skydome should move with the
camera, so the camera always remains in the center of the volume
Skydome
• Skydome
– the sky is created as a hemisphere using only one texture, and is positioned above the scene
– is easy to animate its textures!
Skydome
• Skydome
– the sky is created as a hemisphere using only one texture, and is positioned above the scene
– is easy to animate its textures!
Skydome
• Skydome
– the sky is created as a hemisphere using only one texture, and is positioned above the scene
– is easy to animate its textures!
Skydome
• Skydome
– the sky is created as a hemisphere using only one texture, and is positioned above the scene
– is easy to animate its textures!
Creating skydomeApress, Chapter 13, Skydome approach
Creating skydome
• Loading the skydome “Hemisphere”
public void Load(string modelFileName)
{
model = Content.Load<Model>(GameAssetsPath.MODELS PATH + modelFileName);
}
Creating skydome
• Updating the Sky
public override void Update(GameTime time)
{
BaseCamera camera = cameraManager.ActiveCamera;
// Center the camera in the SkyDome
transformation.Translate = new Vector3(camera.Position.X,
0.0f, camera.Position.Z);
// Rotate the SkyDome slightly
transformation.Rotate += new Vector3(0,
(float)time.ElapsedGameTime.TotalSeconds * 0.5f, 0);
base.Update(time);
}
Creating skydome
• Drawing the Sky
public override void Draw(GameTime time)
{
GraphicsDevice.DepthStencilState = DepthStencilState.None;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
base.Draw(time);
}
Creating skydome
• Drawing the Sky
public override void Draw(GameTime time)
{
GraphicsDevice.DepthStencilState = DepthStencilState.None;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
base.Draw(time);
}
Creating skydome
• Drawing the Sky
public override void Draw(GameTime time)
{
GraphicsDevice.DepthStencilState = DepthStencilState.None;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.DepthStencilState = DepthStencilState.None;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.DepthStencilState = DepthStencilState.Default;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Creating skydome
public override void Draw(GameTime time)
{
GraphicsDevice.RenderState.DepthBufferEnable = false;
foreach (ModelMesh modelMesh in model.Meshes)
{
// We are only rendering models with BasicEffect
foreach (BasicEffect basicEffect in modelMesh.Effects)
SetEffectMaterial(basicEffect);
modelMesh.Draw();
}
GraphicsDevice.RenderState.DepthBufferEnable = true;
base.Draw(time);
}
Another way?
SkyBox!
SkyBox
• The camera is always positioned in the center of the sky
• Innovative approach!
– Illusion of Endless Boundaries!
SkyBox
• How to create it?
SkyBox
• Creating the Box
– six faces, each face has a different texture
SkyBox
• Creating the Box
– six faces, each face has a different texture
SkyBox
• Creating the Box
– six faces, each face has a different texture
– only 12 triangles!
SkyBox
• Microsoft Book, Chapter 10
– “Adding Skies and Horizons to Your Levels”
SkyBox
• Loading Textures, Global Scope
Texture2D frontTexture, backTexture, groundTexture,
leftTexture, rightTexture, skyTexture;
SkyBox
• Loading Textures, Global Scope
• LoadContent()
Texture2D frontTexture, backTexture, groundTexture,
leftTexture, rightTexture, skyTexture;
frontTexture = Content.Load<Texture2D>("Images\\front");
backTexture = Content.Load<Texture2D>("Images\\back");
leftTexture = Content.Load<Texture2D>("Images\\left");
rightTexture = Content.Load<Texture2D>("Images\\right");
groundTexture = Content.Load<Texture2D>("Images\\ground2");
skyTexture = Content.Load<Texture2D>("Images\\sky");
SkyBox
• Then drawing 4 textures with? each time we (translate, rotate,... etc)
SkyBox
• Then drawing 4 textures with Transformation each time we (translate, rotate,... etc)
SkyBox
• Then drawing 4 textures with Transformation each time we (translate, rotate,... etc)
SkyBox
SkyBox
SkyBox
SkyBox
SkyBox
SkyBox at rbwhitaker web site
SkyBox at rbwhitaker web site
Where to look for skybox and textures?
• Acquiring SkyBox Textures
– A Google image search for "skybox" will usually give you all sorts of good skyboxes
– .dds file format
– terathon.com
– http://developer.amd.com/archive/gpu/cubemapgen/pages/default.aspx
Terrain
Terrain
• Advanced Terrains
– Rbwhitaker web site
• http://rbwhitaker.wikidot.com/skyboxes-1
– Riemers web site
• http://www.riemers.net/eng/Tutorials/XNA/Csharp/series4.php
• http://www.riemers.net/eng/Tutorials/XNA/Csharp/series1.php
– Innovative games web site
• http://www.innovativegames.net/blog/blog/2009/05/29/xna-game-engine-tutorial-12-introduction-
to-hlsl-and-improved-terrain/
Terrain
– Innovative games Web Site
Terrain
– Innovative games Web Site
Terrain
• Innovative games
• Web Site Terrain with fog!
Terrainhttp://www.packtpub.com/article/environmental-effects
Terrain
• http://www.packtpub.com/article/environmental-effects
Terrain - packtpub
Terrain
– Many ways to create a terrain
• From
– From File “image”
– From File “raw”
• With \ Without
– With Shaders
– Without Shaders
Terrain
• Using Planetside’s Terragen!
– Create your own customized terrain!
– www.planetside.co.uk/terragen/
• Using EarthSculptor
– http://www.earthsculptor.com/
Height map
Planetside’sTerragen
Planetside’sTerragen
Planetside’s Terragen
Planetside’sTerragen
Earth Sculptor
Earth Sculptor
Terrain – Rimer’s,Creating from file “image”
http://www.riemers.net/eng/Tutorials/XNA/Csharp/Series1/Terrain_from_file.php
Terrain – Rimer’s,Creating from file “image”
Terrain - packtpub
• How to do it perfectly?!
Terrain
Chapter 11, Generating a TerrainPage: 227
TerrainTerrain
Terrain
• Height Maps
Terrain
• Height Maps
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Creating Terrain Class
Texture2D heightMapTexture = Content.Load<Texture2D>(heightMapFileName);
int heightMapSize = heightMapTexture.Width*heightMapTexture.Height;
heightMap = new Color[heightMapSize];
heightMapTexture.GetData<Color>(heightMap);
this.vertexCountX = heightMapTexture.Width;
this.vertexCountZ = heightMapTexture.Height;
Terrain
• Manipulate through VertexBuffer
Terrain
• Manipulate through VertexBuffer
Terrain
• Manipulate through VertexBuffer
Terrain
private int[] GenerateTerrainIndices()
{
int numIndices = numTriangles * 3;
int[] indices = new int[numIndices];
int indicesCount = 0;
for (int i = 0; i < (vertexCountZ - 1); i++)
{
for (int j = 0; j < (vertexCountX - 1); j++)
{
int index = j + i * vertexCountZ;
// First triangle
indices[indicesCount++] = index;
indices[indicesCount++] = index + 1;
indices[indicesCount++] = index + vertexCountX + 1;
// Second triangle
indices[indicesCount++] = index + vertexCountX + 1;
indices[indicesCount++] = index + vertexCountX;
indices[indicesCount++] = index;
}
}
return indices;
}
Terrain
private int[] GenerateTerrainIndices()
{
int numIndices = numTriangles * 3;
int[] indices = new int[numIndices];
int indicesCount = 0;
for (int i = 0; i < (vertexCountZ - 1); i++)
{
for (int j = 0; j < (vertexCountX - 1); j++)
{
int index = j + i * vertexCountZ;
// First triangle
indices[indicesCount++] = index;
indices[indicesCount++] = index + 1;
indices[indicesCount++] = index + vertexCountX + 1;
// Second triangle
indices[indicesCount++] = index + vertexCountX + 1;
indices[indicesCount++] = index + vertexCountX;
indices[indicesCount++] = index;
}
}
return indices;
}
Terrain
• Generating the Position and Texture Coordinate of the Vertices
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;How to get the “Height” that correspond to each “Color value”?!
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;
Terrain
you’ll simply take the red color component of each color as height for a vertex
Terrain
• Generating the Position and Texture Coordinate of the Vertices
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;
Terrain
• Generating the Position and Texture Coordinate of the Vertices
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;Are we done just yet?
Terrain
• Generating the Position and Texture Coordinate of the Vertices
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;Texturing!
Terrain
• Generating the Position and Texture Coordinate of the Vertices
for (float i = -halfTerrainDepth; i <= halfTerrainDepth; i += blockScale)
for (float j = -halfTerrainWidth; j <= halfTerrainWidth; j += blockScale)
vertices[vertexCount].Position = new Vector3(j,heightMap[vertexCount].R * heightScale, i);
float terrainWidth = (vertexCountX - 1) * blockScale;
float terrainDepth = (vertexCountZ - 1) * blockScale;
float halfTerrainWidth = terrainWidth * 0.5f;
float halfTerrainDepth = terrainDepth * 0.5f;
Each vertex also has a U and V texture coordinate that should vary
between (0, 0) and (1, 1), where (0, 0) corresponds to the top left,
(1, 0) to the top right and (1, 1) to the bottom right of the texture
Terrain
• Texturing
float tu = 0; float tv = 0;
float tuDerivative = 1.0f / (vertexCountX - 1);
float tvDerivative = 1.0f / (vertexCountZ - 1);
Terrain
• Texturing
float tu = 0; float tv = 0;
float tuDerivative = 1.0f / (vertexCountX - 1);
float tvDerivative = 1.0f / (vertexCountZ - 1);
Terrain
• Creating Normals
Multitexturing Techniques
Multitexturing
Advanced Terrain
• Multitexturing
“App1-MultitexturedTerrain”
Advanced Terrain
Advanced Terrain
“App1-MultitexturedTerrain”
Advanced TerrainNormal Mapping Technique
Advanced Terrain – Normal Mapping Technique
Advanced Terrain – Normal Mapping Technique
Advanced Terrain – Normal Mapping Technique
Advanced Terrain – Normal Mapping Technique
Using the normal mapping technique, you can add the illusion of small-scale detailsto the terrain’s mesh, without needing to increase the complexity of its mesh
You create this illusion by slightly manipulating the lighting in each pixel of yourterrain. Variations in lighting are created by the deviated normals.
Remember that the amount of lighting falling onto a triangle is determined by thenormals of its vertices.
• Creating the Terrain Effects (Apress, Page 277)
Find this at “App2-MultitexturedNormalMappedTerrain”
Terrain - Querying the Terrain’s Height
Terrain - Querying the Terrain’s Height?
Terrain
• Querying the Terrain’s Height?
Terrain
• Querying the Terrain’s Height?
– you first need to calculate this position relative to the terrain’s vertex grid.
– You can do this by subtracting the queried world position from the terrain’s origin position,
making sure to take the terrain’s world translation and rotation into account.
Terrain
• Querying the Terrain’s Height?
– you first need to calculate this position relative to the terrain’s vertex grid.
– You can do this by subtracting the queried world position from the terrain’s origin position,
making sure to take the terrain’s world translation and rotation into account.
• Then you need to know in which quad of the terrain grid the position you are
querying is located, which you can do by dividing the calculated position (relative
to the terrain) by the terrain’s block scale.
Terrain
• Quad Tree
Terrain
• Quad Tree – The concept
Terrain
• Check out the videos in the appendix
Terrain
• Querying the Terrain’s Height?
– you first need to calculate this position relative to the terrain’s vertex grid.
– You can do this by subtracting the queried world position from the terrain’s origin position,
making sure to take the terrain’s world translation and rotation into account.
• Then you need to know in which quad of the terrain grid the position you are
querying is located, which you can do by dividing the calculated position (relative
to the terrain) by the terrain’s block scale.
How to get our current
position?!
Terrain
• Querying the Terrain’s Height?
No Built-in Methods
Terrain
• Querying the Terrain’s Height?
Creating our own Transformation classYou can store the transformations that are currently set on the
terrain (translate, rotate, and scale) inside the Terrain class, using the Transformation class created in Chapter 10, Apress.
Terrain
• Querying the Terrain’s Height
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• Querying the Terrain’s Height
// Get the position relative to the terrain grid
Vector2 positionInGrid = new Vector2(
positionX - (StartPosition.X + Transformation.Translate.X),
positionZ - (StartPosition.Y + Transformation.Translate.Z));
// Calculate the grid position
Vector2 blockPosition = new Vector2(
(int)(positionInGrid.X / blockScale),
(int)(positionInGrid.Y / blockScale));
Terrain
• A block in the terrain grid. If the x position inside the block is bigger than the z
position, the object is in the top triangle. Otherwise, the object is in the bottom
triangle.
Terrain
• After finding in which triangle the object is positioned, you can obtain the height
of a position inside this triangle through a bilinear interpolation of the height of
the triangle’s vertices.
• Use the following code for the GetHeight method to calculate the height of a
terrain’s position
private float GetHeight(float positionX, float positionZ)
Advanced TerrainRay and Terrain Collision
Advanced Terrain - Ray and Terrain Collision
Advanced Terrain - Ray and Terrain Collision
Advanced Terrain - Ray and Terrain Collision
• Quite Straight forward
// A good ray step is half of the blockScale
Vector3 rayStep = ray.Direction * blockScale * 0.5f;
Vector3 rayStartPosition = ray.Position;
// Linear search - Loop until you find a point inside and outside the terrain
Vector3 lastRayPosition = ray.Position;
ray.Position += rayStep;
float height = GetHeight(ray.Position);
while (ray.Position.Y > height && height >= 0)
{
lastRayPosition = ray.Position;
ray.Position += rayStep;
height = GetHeight(ray.Position);
}
Terrain
• Chapter 25: Terrain with Height Detection
• From “.raw” file
Terrain - packtpub
• How to do it perfectly?!
Terrain - packtpub
• Read the Height map and convert it to a proper array
Terrain - packtpub
• How to get the Heights?!
Color[] heightMapData = new Color[width * length];heightMap.GetData<Color>(heightMapData);
Terrain - packtpub
• How to get the Heights?!
Color[] heightMapData = new Color[width * length];heightMap.GetData<Color>(heightMapData);
Terrain - packtpub
heights[,]
Terrain - packtpub
• Read the Height map and convert it to a proper array?!
Terrain - packtpub
• Read the Height map and convert it to a proper array?!
Terrain - packtpub
• Read the Height map and convert it to a proper array?!
Terrain
• The demonstration used in this chapter shows how to create and implement a
height map using an 8-bit “.raw” grayscale image.
• Each pixel in the.raw image stores information about the elevation in a range
between 0 and 255.
• the height data in each pixel can then be accessed with the pixel row and column
number!
Terrain
• Proper texture covers your terrain,
• Original terrain created is 257 pixels wide by 257 pixels high
floorTexture = Content.Load<Texture2D>("Images\\terrain");
const int NUM_COLS = 257;
const int NUM_ROWS = 257;
Terrain
• The vertex buffer used for storing the terrain vertices must now use the height
information from the height map.
InitializeVertexBuffer() // for NUM_COLS, NUM_ROWS
Terrain
• Controlling Height!
void UpdateCameraHeight()
{
const float HOVER_AMOUNT = 0.25f;
float height = CellHeight(cam.position);
cam.view.Y += height - cam.position.Y + HOVER_AMOUNT;
cam.position.Y += height - cam.position.Y + HOVER_AMOUNT;
}
Terrain
• Controlling Height!
void UpdateCameraHeight()
{
const float HOVER_AMOUNT = 0.25f;
float height = CellHeight(cam.position);
cam.view.Y += height - cam.position.Y + HOVER_AMOUNT;
cam.position.Y += height - cam.position.Y + HOVER_AMOUNT;
}
Terrain
• How to know the current HoverAmount?!
Terrain
• How to know the current HoverAmount?!
Terrain
• How to know the current HoverAmount?!
Terrain – Back to our awesome terrain
• http://www.packtpub.com/article/environmental-effects
Advanced Terrain - Multitexturing
Advanced Terrain – Multitexturing / packtpub
• Just another custom shader!
Advanced Terrain – Spice it Up!
Advanced Terrain – Spice it Up!Adding a detail texture
to the terrain
Advanced Terrain –Detailing / packtpub
• Snow Texture!
Advanced Terrain –Detailing / packtpub
Advanced Terrain –Detailing / packtpub
• Details appear when camera is close to the terrain to fake a higher resolution
texture
Advanced Terrain –Detailing / packtpub
Advanced Terrain –Detailing / packtpub
Advanced Terrain –Detailing / packtpub
• How to add all these tress and bushes!
– Code?!!!!! :@
– XML
Advanced Terrain –Detailing / packtpub
Advanced Terrain –Detailing / packtpub
• Clouds! \ Billboarding!
Advanced Terrain –Detailing / packtpub
Advanced Terrain
Advanced Terrain
Advanced Terrain